From 9fbc9105a62e5ca309d5152407dea0db86cc1709 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 8 Oct 2018 15:47:22 -0700 Subject: [PATCH 001/375] Update tests --- .../tests/ChannelTests/ChannelPoolTest.m | 164 ++++ .../tests/ChannelTests/ChannelTests.m | 93 ++ src/objective-c/tests/ChannelTests/Info.plist | 22 + src/objective-c/tests/GRPCClientTests.m | 291 +++++- src/objective-c/tests/InteropTests.h | 21 + src/objective-c/tests/InteropTests.m | 201 +++++ .../tests/InteropTestsCallOptions/Info.plist | 22 + .../InteropTestsCallOptions.m | 116 +++ .../tests/InteropTestsLocalCleartext.m | 12 + src/objective-c/tests/InteropTestsLocalSSL.m | 16 + .../InteropTestsMultipleChannels/Info.plist | 22 + .../InteropTestsMultipleChannels.m | 259 ++++++ src/objective-c/tests/InteropTestsRemote.m | 18 + src/objective-c/tests/Podfile | 10 +- .../tests/Tests.xcodeproj/project.pbxproj | 832 +++++++++++++++++- .../xcschemes/ChannelTests.xcscheme | 92 ++ .../InteropTestsCallOptions.xcscheme | 56 ++ .../InteropTestsLocalCleartext.xcscheme | 8 - .../InteropTestsMultipleChannels.xcscheme | 56 ++ .../xcschemes/InteropTestsRemote.xcscheme | 2 - src/objective-c/tests/run_tests.sh | 10 + 21 files changed, 2305 insertions(+), 18 deletions(-) create mode 100644 src/objective-c/tests/ChannelTests/ChannelPoolTest.m create mode 100644 src/objective-c/tests/ChannelTests/ChannelTests.m create mode 100644 src/objective-c/tests/ChannelTests/Info.plist create mode 100644 src/objective-c/tests/InteropTestsCallOptions/Info.plist create mode 100644 src/objective-c/tests/InteropTestsCallOptions/InteropTestsCallOptions.m create mode 100644 src/objective-c/tests/InteropTestsMultipleChannels/Info.plist create mode 100644 src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m create mode 100644 src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/ChannelTests.xcscheme create mode 100644 src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsCallOptions.xcscheme create mode 100644 src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsMultipleChannels.xcscheme diff --git a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m new file mode 100644 index 00000000000..3b6b10b1a5f --- /dev/null +++ b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m @@ -0,0 +1,164 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import + +#import "../../GRPCClient/private/GRPCChannel.h" +#import "../../GRPCClient/private/GRPCChannelPool.h" + +#define TEST_TIMEOUT 32 + +NSString *kDummyHost = @"dummy.host"; + +@interface ChannelPoolTest : XCTestCase + +@end + +@implementation ChannelPoolTest + ++ (void)setUp { + grpc_init(); +} + +- (void)testCreateChannel { + NSString *kDummyHost = @"dummy.host"; + GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; + options1.transportType = GRPCTransportTypeInsecure; + GRPCCallOptions *options2 = [options1 copy]; + GRPCChannelConfiguration *config1 = + [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; + GRPCChannelConfiguration *config2 = + [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options2]; + GRPCChannelPool *pool = [[GRPCChannelPool alloc] initWithChannelDestroyDelay:1]; + + __weak XCTestExpectation *expectCreateChannel = + [self expectationWithDescription:@"Create first channel"]; + GRPCChannel *channel1 = + [pool channelWithConfiguration:config1 + createChannel:^{ + [expectCreateChannel fulfill]; + return [GRPCChannel createChannelWithConfiguration:config1]; + }]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; + GRPCChannel *channel2 = [pool channelWithConfiguration:config2 + createChannel:^{ + XCTFail(@"Should not create a second channel."); + return (GRPCChannel *)nil; + }]; + XCTAssertEqual(channel1, channel2); +} + +- (void)testChannelTimeout { + NSTimeInterval kChannelDestroyDelay = 1.0; + GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; + options1.transportType = GRPCTransportTypeInsecure; + GRPCChannelConfiguration *config1 = + [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; + GRPCChannelPool *pool = + [[GRPCChannelPool alloc] initWithChannelDestroyDelay:kChannelDestroyDelay]; + GRPCChannel *channel1 = + [pool channelWithConfiguration:config1 + createChannel:^{ + return [GRPCChannel createChannelWithConfiguration:config1]; + }]; + [pool unrefChannelWithConfiguration:config1]; + __weak XCTestExpectation *expectTimerDone = [self expectationWithDescription:@"Timer elapse."]; + NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:kChannelDestroyDelay + 1 + repeats:NO + block:^(NSTimer *_Nonnull timer) { + [expectTimerDone fulfill]; + }]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; + timer = nil; + GRPCChannel *channel2 = + [pool channelWithConfiguration:config1 + createChannel:^{ + return [GRPCChannel createChannelWithConfiguration:config1]; + }]; + XCTAssertNotEqual(channel1, channel2); +} + +- (void)testChannelTimeoutCancel { + NSTimeInterval kChannelDestroyDelay = 3.0; + GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; + options1.transportType = GRPCTransportTypeInsecure; + GRPCChannelConfiguration *config1 = + [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; + GRPCChannelPool *pool = + [[GRPCChannelPool alloc] initWithChannelDestroyDelay:kChannelDestroyDelay]; + GRPCChannel *channel1 = + [pool channelWithConfiguration:config1 + createChannel:^{ + return [GRPCChannel createChannelWithConfiguration:config1]; + }]; + [channel1 unmanagedCallUnref]; + sleep(1); + GRPCChannel *channel2 = + [pool channelWithConfiguration:config1 + createChannel:^{ + return [GRPCChannel createChannelWithConfiguration:config1]; + }]; + XCTAssertEqual(channel1, channel2); + sleep((int)kChannelDestroyDelay + 2); + GRPCChannel *channel3 = + [pool channelWithConfiguration:config1 + createChannel:^{ + return [GRPCChannel createChannelWithConfiguration:config1]; + }]; + XCTAssertEqual(channel1, channel3); +} + +- (void)testClearChannels { + GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; + options1.transportType = GRPCTransportTypeInsecure; + GRPCMutableCallOptions *options2 = [[GRPCMutableCallOptions alloc] init]; + options2.transportType = GRPCTransportTypeDefault; + GRPCChannelConfiguration *config1 = + [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; + GRPCChannelConfiguration *config2 = + [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options2]; + GRPCChannelPool *pool = [[GRPCChannelPool alloc] initWithChannelDestroyDelay:1]; + + GRPCChannel *channel1 = + [pool channelWithConfiguration:config1 + createChannel:^{ + return [GRPCChannel createChannelWithConfiguration:config1]; + }]; + GRPCChannel *channel2 = + [pool channelWithConfiguration:config2 + createChannel:^{ + return [GRPCChannel createChannelWithConfiguration:config2]; + }]; + XCTAssertNotEqual(channel1, channel2); + + [pool clear]; + GRPCChannel *channel3 = + [pool channelWithConfiguration:config1 + createChannel:^{ + return [GRPCChannel createChannelWithConfiguration:config1]; + }]; + GRPCChannel *channel4 = + [pool channelWithConfiguration:config2 + createChannel:^{ + return [GRPCChannel createChannelWithConfiguration:config2]; + }]; + XCTAssertNotEqual(channel1, channel3); + XCTAssertNotEqual(channel2, channel4); +} + +@end diff --git a/src/objective-c/tests/ChannelTests/ChannelTests.m b/src/objective-c/tests/ChannelTests/ChannelTests.m new file mode 100644 index 00000000000..0a8b7ae6ee6 --- /dev/null +++ b/src/objective-c/tests/ChannelTests/ChannelTests.m @@ -0,0 +1,93 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import + +#import "../../GRPCClient/GRPCCallOptions.h" +#import "../../GRPCClient/private/GRPCChannel.h" + +@interface ChannelTests : XCTestCase + +@end + +@implementation ChannelTests + ++ (void)setUp { + grpc_init(); +} + +- (void)testSameConfiguration { + NSString *host = @"grpc-test.sandbox.googleapis.com"; + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.userAgentPrefix = @"TestUAPrefix"; + NSMutableDictionary *args = [NSMutableDictionary new]; + args[@"abc"] = @"xyz"; + options.additionalChannelArgs = [args copy]; + GRPCChannel *channel1 = [GRPCChannel channelWithHost:host callOptions:options]; + GRPCChannel *channel2 = [GRPCChannel channelWithHost:host callOptions:options]; + XCTAssertEqual(channel1, channel2); + GRPCMutableCallOptions *options2 = [options mutableCopy]; + options2.additionalChannelArgs = [args copy]; + GRPCChannel *channel3 = [GRPCChannel channelWithHost:host callOptions:options2]; + XCTAssertEqual(channel1, channel3); +} + +- (void)testDifferentHost { + NSString *host1 = @"grpc-test.sandbox.googleapis.com"; + NSString *host2 = @"grpc-test2.sandbox.googleapis.com"; + NSString *host3 = @"http://grpc-test.sandbox.googleapis.com"; + NSString *host4 = @"dns://grpc-test.sandbox.googleapis.com"; + NSString *host5 = @"grpc-test.sandbox.googleapis.com:80"; + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.userAgentPrefix = @"TestUAPrefix"; + NSMutableDictionary *args = [NSMutableDictionary new]; + args[@"abc"] = @"xyz"; + options.additionalChannelArgs = [args copy]; + GRPCChannel *channel1 = [GRPCChannel channelWithHost:host1 callOptions:options]; + GRPCChannel *channel2 = [GRPCChannel channelWithHost:host2 callOptions:options]; + GRPCChannel *channel3 = [GRPCChannel channelWithHost:host3 callOptions:options]; + GRPCChannel *channel4 = [GRPCChannel channelWithHost:host4 callOptions:options]; + GRPCChannel *channel5 = [GRPCChannel channelWithHost:host5 callOptions:options]; + XCTAssertNotEqual(channel1, channel2); + XCTAssertNotEqual(channel1, channel3); + XCTAssertNotEqual(channel1, channel4); + XCTAssertNotEqual(channel1, channel5); +} + +- (void)testDifferentChannelParameters { + NSString *host = @"grpc-test.sandbox.googleapis.com"; + GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; + options1.transportType = GRPCTransportTypeDefault; + NSMutableDictionary *args = [NSMutableDictionary new]; + args[@"abc"] = @"xyz"; + options1.additionalChannelArgs = [args copy]; + GRPCMutableCallOptions *options2 = [[GRPCMutableCallOptions alloc] init]; + options2.transportType = GRPCTransportTypeInsecure; + options2.additionalChannelArgs = [args copy]; + GRPCMutableCallOptions *options3 = [[GRPCMutableCallOptions alloc] init]; + options3.transportType = GRPCTransportTypeDefault; + args[@"def"] = @"uvw"; + options3.additionalChannelArgs = [args copy]; + GRPCChannel *channel1 = [GRPCChannel channelWithHost:host callOptions:options1]; + GRPCChannel *channel2 = [GRPCChannel channelWithHost:host callOptions:options2]; + GRPCChannel *channel3 = [GRPCChannel channelWithHost:host callOptions:options3]; + XCTAssertNotEqual(channel1, channel2); + XCTAssertNotEqual(channel1, channel3); +} + +@end diff --git a/src/objective-c/tests/ChannelTests/Info.plist b/src/objective-c/tests/ChannelTests/Info.plist new file mode 100644 index 00000000000..6c40a6cd0c4 --- /dev/null +++ b/src/objective-c/tests/ChannelTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index a0de8ba8990..bad22d30cbb 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -86,6 +86,58 @@ static GRPCProtoMethod *kFullDuplexCallMethod; @end +// Convenience class to use blocks as callbacks +@interface ClientTestsBlockCallbacks : NSObject + +- (instancetype)initWithInitialMetadataCallback:(void (^)(NSDictionary *))initialMetadataCallback + messageCallback:(void (^)(id))messageCallback + closeCallback:(void (^)(NSDictionary *, NSError *))closeCallback; + +@end + +@implementation ClientTestsBlockCallbacks { + void (^_initialMetadataCallback)(NSDictionary *); + void (^_messageCallback)(id); + void (^_closeCallback)(NSDictionary *, NSError *); + dispatch_queue_t _dispatchQueue; +} + +- (instancetype)initWithInitialMetadataCallback:(void (^)(NSDictionary *))initialMetadataCallback + messageCallback:(void (^)(id))messageCallback + closeCallback:(void (^)(NSDictionary *, NSError *))closeCallback { + if ((self = [super init])) { + _initialMetadataCallback = initialMetadataCallback; + _messageCallback = messageCallback; + _closeCallback = closeCallback; + _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); + } + return self; +} + +- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { + if (_initialMetadataCallback) { + _initialMetadataCallback(initialMetadata); + } +} + +- (void)receivedMessage:(id)message { + if (_messageCallback) { + _messageCallback(message); + } +} + +- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { + if (_closeCallback) { + _closeCallback(trailingMetadata, error); + } +} + +- (dispatch_queue_t)dispatchQueue { + return _dispatchQueue; +} + +@end + #pragma mark Tests /** @@ -237,6 +289,55 @@ static GRPCProtoMethod *kFullDuplexCallMethod; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } +- (void)testMetadataWithV2API { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"RPC unauthorized."]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + request.fillUsername = YES; + request.fillOauthScope = YES; + + GRPCRequestOptions *callRequest = + [[GRPCRequestOptions alloc] initWithHost:(NSString *)kRemoteSSLHost + path:kUnaryCallMethod.HTTPPath + safety:GRPCCallSafetyDefault]; + __block NSDictionary *init_md; + __block NSDictionary *trailing_md; + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.oauth2AccessToken = @"bogusToken"; + GRPCCall2 *call = [[GRPCCall2 alloc] + initWithRequestOptions:callRequest + handler:[[ClientTestsBlockCallbacks alloc] + initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { + init_md = initialMetadata; + } + messageCallback:^(id message) { + XCTFail(@"Received unexpected response."); + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + trailing_md = trailingMetadata; + if (error) { + XCTAssertEqual(error.code, 16, + @"Finished with unexpected error: %@", error); + XCTAssertEqualObjects(init_md, + error.userInfo[kGRPCHeadersKey]); + XCTAssertEqualObjects(trailing_md, + error.userInfo[kGRPCTrailersKey]); + NSString *challengeHeader = init_md[@"www-authenticate"]; + XCTAssertGreaterThan(challengeHeader.length, 0, + @"No challenge in response headers %@", + init_md); + [expectation fulfill]; + } + }] + callOptions:options]; + + [call start]; + [call writeWithData:[request data]]; + [call finish]; + + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + - (void)testResponseMetadataKVO { __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."]; @@ -329,6 +430,77 @@ static GRPCProtoMethod *kFullDuplexCallMethod; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } +- (void)testUserAgentPrefixWithV2API { + __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."]; + __weak XCTestExpectation *recvInitialMd = + [self expectationWithDescription:@"Did not receive initial md."]; + + GRPCRequestOptions *request = [[GRPCRequestOptions alloc] initWithHost:kHostAddress + path:kEmptyCallMethod.HTTPPath + safety:GRPCCallSafetyDefault]; + NSDictionary *headers = + [NSDictionary dictionaryWithObjectsAndKeys:@"", @"x-grpc-test-echo-useragent", nil]; + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.transportType = GRPCTransportTypeInsecure; + options.userAgentPrefix = @"Foo"; + options.initialMetadata = headers; + GRPCCall2 *call = [[GRPCCall2 alloc] + initWithRequestOptions:request + handler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:^( + NSDictionary *initialMetadata) { + NSString *userAgent = initialMetadata[@"x-grpc-test-echo-useragent"]; + // Test the regex is correct + NSString *expectedUserAgent = @"Foo grpc-objc/"; + expectedUserAgent = + [expectedUserAgent stringByAppendingString:GRPC_OBJC_VERSION_STRING]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@" grpc-c/"]; + expectedUserAgent = + [expectedUserAgent stringByAppendingString:GRPC_C_VERSION_STRING]; + expectedUserAgent = + [expectedUserAgent stringByAppendingString:@" (ios; chttp2; "]; + expectedUserAgent = [expectedUserAgent + stringByAppendingString:[NSString + stringWithUTF8String:grpc_g_stands_for()]]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@")"]; + XCTAssertEqualObjects(userAgent, expectedUserAgent); + + NSError *error = nil; + // Change in format of user-agent field in a direction that does not match + // the regex will likely cause problem for certain gRPC users. For details, + // refer to internal doc https://goo.gl/c2diBc + NSRegularExpression *regex = [NSRegularExpression + regularExpressionWithPattern: + @" grpc-[a-zA-Z0-9]+(-[a-zA-Z0-9]+)?/[^ ,]+( \\([^)]*\\))?" + options:0 + error:&error]; + + NSString *customUserAgent = [regex + stringByReplacingMatchesInString:userAgent + options:0 + range:NSMakeRange(0, [userAgent length]) + withTemplate:@""]; + XCTAssertEqualObjects(customUserAgent, @"Foo"); + [recvInitialMd fulfill]; + } + messageCallback:^(id message) { + XCTAssertNotNil(message); + XCTAssertEqual([message length], 0, + @"Non-empty response received: %@", message); + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + if (error) { + XCTFail(@"Finished with unexpected error: %@", error); + } else { + [completion fulfill]; + } + }] + callOptions:options]; + [call writeWithData:[NSData data]]; + [call start]; + + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + - (void)testTrailers { __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."]; @@ -420,6 +592,52 @@ static GRPCProtoMethod *kFullDuplexCallMethod; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } +- (void)testIdempotentProtoRPCWithV2API { + __weak XCTestExpectation *response = [self expectationWithDescription:@"Expected response."]; + __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + request.responseSize = 100; + request.fillUsername = YES; + request.fillOauthScope = YES; + GRPCRequestOptions *requestOptions = + [[GRPCRequestOptions alloc] initWithHost:kHostAddress + path:kUnaryCallMethod.HTTPPath + safety:GRPCCallSafetyIdempotentRequest]; + + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.transportType = GRPCTransportTypeInsecure; + GRPCCall2 *call = [[GRPCCall2 alloc] + initWithRequestOptions:requestOptions + handler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + messageCallback:^(id message) { + NSData *data = (NSData *)message; + XCTAssertNotNil(data, @"nil value received as response."); + XCTAssertGreaterThan(data.length, 0, + @"Empty response received."); + RMTSimpleResponse *responseProto = + [RMTSimpleResponse parseFromData:data error:NULL]; + // We expect empty strings, not nil: + XCTAssertNotNil(responseProto.username, + @"Response's username is nil."); + XCTAssertNotNil(responseProto.oauthScope, + @"Response's OAuth scope is nil."); + [response fulfill]; + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", + error); + [completion fulfill]; + }] + callOptions:options]; + + [call start]; + [call writeWithData:[request data]]; + [call finish]; + + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + - (void)testAlternateDispatchQueue { const int32_t kPayloadSize = 100; RMTSimpleRequest *request = [RMTSimpleRequest message]; @@ -509,6 +727,38 @@ static GRPCProtoMethod *kFullDuplexCallMethod; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } +- (void)testTimeoutWithV2API { + __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; + + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.timeout = 0.001; + GRPCRequestOptions *requestOptions = + [[GRPCRequestOptions alloc] initWithHost:kHostAddress + path:kFullDuplexCallMethod.HTTPPath + safety:GRPCCallSafetyDefault]; + + GRPCCall2 *call = [[GRPCCall2 alloc] + initWithRequestOptions:requestOptions + handler: + [[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + messageCallback:^(id data) { + XCTFail( + @"Failure: response received; Expect: no response received."); + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + XCTAssertNotNil(error, + @"Failure: no error received; Expect: receive " + @"deadline exceeded."); + XCTAssertEqual(error.code, GRPCErrorCodeDeadlineExceeded); + [completion fulfill]; + }] + callOptions:options]; + + [call start]; + + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + - (int)findFreePort { struct sockaddr_in addr; unsigned int addr_len = sizeof(addr); @@ -580,15 +830,52 @@ static GRPCProtoMethod *kFullDuplexCallMethod; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } +- (void)testTimeoutBackoffWithOptionsWithTimeout:(double)timeout Backoff:(double)backoff { + const double maxConnectTime = timeout > backoff ? timeout : backoff; + const double kMargin = 0.1; + + __weak XCTestExpectation *completion = [self expectationWithDescription:@"Timeout in a second."]; + NSString *const kDummyAddress = [NSString stringWithFormat:@"8.8.8.8:1"]; + GRPCRequestOptions *requestOptions = + [[GRPCRequestOptions alloc] initWithHost:kDummyAddress path:@"" safety:GRPCCallSafetyDefault]; + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.connectMinTimeout = timeout; + options.connectInitialBackoff = backoff; + options.connectMaxBackoff = 0; + + NSDate *startTime = [NSDate date]; + GRPCCall2 *call = [[GRPCCall2 alloc] + initWithRequestOptions:requestOptions + handler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + messageCallback:^(id data) { + XCTFail(@"Received message. Should not reach here."); + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + XCTAssertNotNil(error, + @"Finished with no error; expecting error"); + XCTAssertLessThan( + [[NSDate date] timeIntervalSinceDate:startTime], + maxConnectTime + kMargin); + [completion fulfill]; + }] + callOptions:options]; + + [call start]; + + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + // The numbers of the following three tests are selected to be smaller than the default values of // initial backoff (1s) and min_connect_timeout (20s), so that if they fail we know the default // values fail to be overridden by the channel args. -- (void)testTimeoutBackoff2 { +- (void)testTimeoutBackoff1 { [self testTimeoutBackoffWithTimeout:0.7 Backoff:0.3]; + [self testTimeoutBackoffWithOptionsWithTimeout:0.7 Backoff:0.4]; } -- (void)testTimeoutBackoff3 { +- (void)testTimeoutBackoff2 { [self testTimeoutBackoffWithTimeout:0.3 Backoff:0.7]; + [self testTimeoutBackoffWithOptionsWithTimeout:0.3 Backoff:0.8]; } - (void)testErrorDebugInformation { diff --git a/src/objective-c/tests/InteropTests.h b/src/objective-c/tests/InteropTests.h index 039d92a8d35..e223839d3ac 100644 --- a/src/objective-c/tests/InteropTests.h +++ b/src/objective-c/tests/InteropTests.h @@ -18,6 +18,8 @@ #import +#import + /** * Implements tests as described here: * https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md @@ -38,4 +40,23 @@ * remote servers enconde responses with different overhead (?), so this is defined per-subclass. */ - (int32_t)encodingOverhead; + +/** + * The type of transport to be used. The base implementation returns default. Subclasses should + * override to appropriate settings. + */ ++ (GRPCTransportType)transportType; + +/** + * The root certificates to be used. The base implementation returns nil. Subclasses should override + * to appropriate settings. + */ ++ (NSString *)pemRootCert; + +/** + * The root certificates to be used. The base implementation returns nil. Subclasses should override + * to appropriate settings. + */ ++ (NSString *)hostNameOverride; + @end diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 9d796068818..54af7036c35 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -74,6 +74,58 @@ BOOL isRemoteInteropTest(NSString *host) { return [host isEqualToString:@"grpc-test.sandbox.googleapis.com"]; } +// Convenience class to use blocks as callbacks +@interface InteropTestsBlockCallbacks : NSObject + +- (instancetype)initWithInitialMetadataCallback:(void (^)(NSDictionary *))initialMetadataCallback + messageCallback:(void (^)(id))messageCallback + closeCallback:(void (^)(NSDictionary *, NSError *))closeCallback; + +@end + +@implementation InteropTestsBlockCallbacks { + void (^_initialMetadataCallback)(NSDictionary *); + void (^_messageCallback)(id); + void (^_closeCallback)(NSDictionary *, NSError *); + dispatch_queue_t _dispatchQueue; +} + +- (instancetype)initWithInitialMetadataCallback:(void (^)(NSDictionary *))initialMetadataCallback + messageCallback:(void (^)(id))messageCallback + closeCallback:(void (^)(NSDictionary *, NSError *))closeCallback { + if ((self = [super init])) { + _initialMetadataCallback = initialMetadataCallback; + _messageCallback = messageCallback; + _closeCallback = closeCallback; + _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); + } + return self; +} + +- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { + if (_initialMetadataCallback) { + _initialMetadataCallback(initialMetadata); + } +} + +- (void)receivedMessage:(id)message { + if (_messageCallback) { + _messageCallback(message); + } +} + +- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { + if (_closeCallback) { + _closeCallback(trailingMetadata, error); + } +} + +- (dispatch_queue_t)dispatchQueue { + return _dispatchQueue; +} + +@end + #pragma mark Tests @implementation InteropTests { @@ -91,6 +143,18 @@ BOOL isRemoteInteropTest(NSString *host) { return 0; } ++ (GRPCTransportType)transportType { + return GRPCTransportTypeDefault; +} + ++ (NSString *)pemRootCert { + return nil; +} + ++ (NSString *)hostNameOverride { + return nil; +} + + (void)setUp { NSLog(@"InteropTest Started, class: %@", [[self class] description]); #ifdef GRPC_COMPILE_WITH_CRONET @@ -131,6 +195,33 @@ BOOL isRemoteInteropTest(NSString *host) { [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } +- (void)testEmptyUnaryRPCWithV2API { + XCTAssertNotNil(self.class.host); + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"]; + + GPBEmpty *request = [GPBEmpty message]; + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.transportType = self.class.transportType; + options.pemRootCert = self.class.pemRootCert; + options.hostNameOverride = self.class.hostNameOverride; + + [_service + emptyCallWithMessage:request + responseHandler:[[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + messageCallback:^(id message) { + if (message) { + id expectedResponse = [GPBEmpty message]; + XCTAssertEqualObjects(message, expectedResponse); + [expectation fulfill]; + } + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + XCTAssertNil(error, @"Unexpected error: %@", error); + }] + callOptions:options]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + - (void)testLargeUnaryRPC { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; @@ -380,6 +471,57 @@ BOOL isRemoteInteropTest(NSString *host) { [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } +- (void)testPingPongRPCWithV2API { + XCTAssertNotNil(self.class.host); + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPong"]; + + NSArray *requests = @[ @27182, @8, @1828, @45904 ]; + NSArray *responses = @[ @31415, @9, @2653, @58979 ]; + + __block int index = 0; + + id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] + requestedResponseSize:responses[index]]; + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.transportType = self.class.transportType; + options.pemRootCert = self.class.pemRootCert; + options.hostNameOverride = self.class.hostNameOverride; + + __block GRPCStreamingProtoCall *call = [_service + fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] + initWithInitialMetadataCallback:nil + messageCallback:^(id message) { + XCTAssertLessThan(index, 4, + @"More than 4 responses received."); + id expected = [RMTStreamingOutputCallResponse + messageWithPayloadSize:responses[index]]; + XCTAssertEqualObjects(message, expected); + index += 1; + if (index < 4) { + id request = [RMTStreamingOutputCallRequest + messageWithPayloadSize:requests[index] + requestedResponseSize:responses[index]]; + [call writeWithMessage:request]; + } else { + [call finish]; + } + } + closeCallback:^(NSDictionary *trailingMetadata, + NSError *error) { + XCTAssertNil(error, + @"Finished with unexpected error: %@", + error); + XCTAssertEqual(index, 4, + @"Received %i responses instead of 4.", + index); + [expectation fulfill]; + }] + callOptions:options]; + [call writeWithMessage:request]; + + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + - (void)testEmptyStreamRPC { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"]; @@ -418,6 +560,28 @@ BOOL isRemoteInteropTest(NSString *host) { [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } +- (void)testCancelAfterBeginRPCWithV2API { + XCTAssertNotNil(self.class.host); + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBegin"]; + + // A buffered pipe to which we never write any value acts as a writer that just hangs. + __block GRPCStreamingProtoCall *call = [_service + streamingInputCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] + initWithInitialMetadataCallback:nil + messageCallback:^(id message) { + XCTFail(@"Not expected to receive message"); + } + closeCallback:^(NSDictionary *trailingMetadata, + NSError *error) { + XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); + [expectation fulfill]; + }] + callOptions:nil]; + [call cancel]; + + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + - (void)testCancelAfterFirstResponseRPC { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = @@ -454,6 +618,43 @@ BOOL isRemoteInteropTest(NSString *host) { [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } +- (void)testCancelAfterFirstResponseRPCWithV2API { + XCTAssertNotNil(self.class.host); + __weak XCTestExpectation *completionExpectation = + [self expectationWithDescription:@"Call completed."]; + __weak XCTestExpectation *responseExpectation = + [self expectationWithDescription:@"Received response."]; + + __block BOOL receivedResponse = NO; + + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.transportType = self.class.transportType; + options.pemRootCert = self.class.pemRootCert; + options.hostNameOverride = self.class.hostNameOverride; + + id request = + [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 requestedResponseSize:@31415]; + + __block GRPCStreamingProtoCall *call = [_service + fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] + initWithInitialMetadataCallback:nil + messageCallback:^(id message) { + XCTAssertFalse(receivedResponse); + receivedResponse = YES; + [call cancel]; + [responseExpectation fulfill]; + } + closeCallback:^(NSDictionary *trailingMetadata, + NSError *error) { + XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); + [completionExpectation fulfill]; + }] + callOptions:options]; + + [call writeWithMessage:request]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + - (void)testRPCAfterClosingOpenConnections { XCTAssertNotNil(self.class.host); __weak XCTestExpectation *expectation = diff --git a/src/objective-c/tests/InteropTestsCallOptions/Info.plist b/src/objective-c/tests/InteropTestsCallOptions/Info.plist new file mode 100644 index 00000000000..6c40a6cd0c4 --- /dev/null +++ b/src/objective-c/tests/InteropTestsCallOptions/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/src/objective-c/tests/InteropTestsCallOptions/InteropTestsCallOptions.m b/src/objective-c/tests/InteropTestsCallOptions/InteropTestsCallOptions.m new file mode 100644 index 00000000000..db51cb1cfbb --- /dev/null +++ b/src/objective-c/tests/InteropTestsCallOptions/InteropTestsCallOptions.m @@ -0,0 +1,116 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import + +#import +#import +#import +#import +#import +#import + +#define NSStringize_helper(x) #x +#define NSStringize(x) @NSStringize_helper(x) +static NSString *kRemoteHost = NSStringize(HOST_PORT_REMOTE); +const int32_t kRemoteInteropServerOverhead = 12; + +static const NSTimeInterval TEST_TIMEOUT = 16000; + +@interface InteropTestsCallOptions : XCTestCase + +@end + +@implementation InteropTestsCallOptions { + RMTTestService *_service; +} + +- (void)setUp { + self.continueAfterFailure = NO; + _service = [RMTTestService serviceWithHost:kRemoteHost]; + _service.options = [[GRPCCallOptions alloc] init]; +} + +- (void)test4MBResponsesAreAccepted { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"MaxResponseSize"]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + const int32_t kPayloadSize = + 4 * 1024 * 1024 - kRemoteInteropServerOverhead; // 4MB - encoding overhead + request.responseSize = kPayloadSize; + + [_service unaryCallWithRequest:request + handler:^(RMTSimpleResponse *response, NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + XCTAssertEqual(response.payload.body.length, kPayloadSize); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + +- (void)testResponsesOverMaxSizeFailWithActionableMessage { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ResponseOverMaxSize"]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + const int32_t kPayloadSize = + 4 * 1024 * 1024 - kRemoteInteropServerOverhead + 1; // 1B over max size + request.responseSize = kPayloadSize; + + [_service unaryCallWithRequest:request + handler:^(RMTSimpleResponse *response, NSError *error) { + XCTAssertEqualObjects( + error.localizedDescription, + @"Received message larger than max (4194305 vs. 4194304)"); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + +- (void)testResponsesOver4MBAreAcceptedIfOptedIn { + __weak XCTestExpectation *expectation = + [self expectationWithDescription:@"HigherResponseSizeLimit"]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + const size_t kPayloadSize = 5 * 1024 * 1024; // 5MB + request.responseSize = kPayloadSize; + + GRPCProtoCall *rpc = [_service + RPCToUnaryCallWithRequest:request + handler:^(RMTSimpleResponse *response, NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + XCTAssertEqual(response.payload.body.length, kPayloadSize); + [expectation fulfill]; + }]; + GRPCCallOptions *options = rpc.options; + options.responseSizeLimit = 6 * 1024 * 1024; + + [rpc start]; + + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/src/objective-c/tests/InteropTestsLocalCleartext.m b/src/objective-c/tests/InteropTestsLocalCleartext.m index d49e875bd02..42e327a3303 100644 --- a/src/objective-c/tests/InteropTestsLocalCleartext.m +++ b/src/objective-c/tests/InteropTestsLocalCleartext.m @@ -41,6 +41,14 @@ static int32_t kLocalInteropServerOverhead = 10; return kLocalCleartextHost; } ++ (NSString *)pemRootCert { + return nil; +} + ++ (NSString *)hostNameOverride { + return nil; +} + - (int32_t)encodingOverhead { return kLocalInteropServerOverhead; // bytes } @@ -52,4 +60,8 @@ static int32_t kLocalInteropServerOverhead = 10; [GRPCCall useInsecureConnectionsForHost:kLocalCleartextHost]; } ++ (GRPCTransportType)transportType { + return GRPCTransportTypeInsecure; +} + @end diff --git a/src/objective-c/tests/InteropTestsLocalSSL.m b/src/objective-c/tests/InteropTestsLocalSSL.m index a8c4dc7dfd1..eb72dd1d311 100644 --- a/src/objective-c/tests/InteropTestsLocalSSL.m +++ b/src/objective-c/tests/InteropTestsLocalSSL.m @@ -40,10 +40,26 @@ static int32_t kLocalInteropServerOverhead = 10; return kLocalSSLHost; } ++ (NSString *)pemRootCert { + NSBundle *bundle = [NSBundle bundleForClass:self.class]; + NSString *certsPath = + [bundle pathForResource:@"TestCertificates.bundle/test-certificates" ofType:@"pem"]; + NSError *error; + return [NSString stringWithContentsOfFile:certsPath encoding:NSUTF8StringEncoding error:&error]; +} + ++ (NSString *)hostNameOverride { + return @"foo.test.google.fr"; +} + - (int32_t)encodingOverhead { return kLocalInteropServerOverhead; // bytes } ++ (GRPCTransportType)transportType { + return GRPCTransportTypeDefault; +} + - (void)setUp { [super setUp]; diff --git a/src/objective-c/tests/InteropTestsMultipleChannels/Info.plist b/src/objective-c/tests/InteropTestsMultipleChannels/Info.plist new file mode 100644 index 00000000000..6c40a6cd0c4 --- /dev/null +++ b/src/objective-c/tests/InteropTestsMultipleChannels/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m b/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m new file mode 100644 index 00000000000..eb0ba7f34b3 --- /dev/null +++ b/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m @@ -0,0 +1,259 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import + +#import +#import +#import +#import +#import + +#define NSStringize_helper(x) #x +#define NSStringize(x) @NSStringize_helper(x) +static NSString *const kRemoteSSLHost = NSStringize(HOST_PORT_REMOTE); +static NSString *const kLocalSSLHost = NSStringize(HOST_PORT_LOCALSSL); +static NSString *const kLocalCleartextHost = NSStringize(HOST_PORT_LOCAL); + +static const NSTimeInterval TEST_TIMEOUT = 8000; + +@interface RMTStreamingOutputCallRequest (Constructors) ++ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize + requestedResponseSize:(NSNumber *)responseSize; +@end + +@implementation RMTStreamingOutputCallRequest (Constructors) ++ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize + requestedResponseSize:(NSNumber *)responseSize { + RMTStreamingOutputCallRequest *request = [self message]; + RMTResponseParameters *parameters = [RMTResponseParameters message]; + parameters.size = responseSize.intValue; + [request.responseParametersArray addObject:parameters]; + request.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; + return request; +} +@end + +@interface RMTStreamingOutputCallResponse (Constructors) ++ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize; +@end + +@implementation RMTStreamingOutputCallResponse (Constructors) ++ (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize { + RMTStreamingOutputCallResponse *response = [self message]; + response.payload.type = RMTPayloadType_Compressable; + response.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue]; + return response; +} +@end + +@interface InteropTestsMultipleChannels : XCTestCase + +@end + +dispatch_once_t initCronet; + +@implementation InteropTestsMultipleChannels { + RMTTestService *_remoteService; + RMTTestService *_remoteCronetService; + RMTTestService *_localCleartextService; + RMTTestService *_localSSLService; +} + +- (void)setUp { + [super setUp]; + + self.continueAfterFailure = NO; + + // Default stack with remote host + _remoteService = [RMTTestService serviceWithHost:kRemoteSSLHost]; + + // Cronet stack with remote host + _remoteCronetService = [RMTTestService serviceWithHost:kRemoteSSLHost]; + + dispatch_once(&initCronet, ^{ + [Cronet setHttp2Enabled:YES]; + [Cronet start]; + }); + + GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; + options.transportType = GRPCTransportTypeCronet; + options.cronetEngine = [Cronet getGlobalEngine]; + _remoteCronetService.options = options; + + // Local stack with no SSL + _localCleartextService = [RMTTestService serviceWithHost:kLocalCleartextHost]; + options = [[GRPCCallOptions alloc] init]; + options.transportType = GRPCTransportTypeInsecure; + _localCleartextService.options = options; + + // Local stack with SSL + _localSSLService = [RMTTestService serviceWithHost:kLocalSSLHost]; + + NSBundle *bundle = [NSBundle bundleForClass:self.class]; + NSString *certsPath = + [bundle pathForResource:@"TestCertificates.bundle/test-certificates" ofType:@"pem"]; + NSError *error = nil; + NSString *certs = + [NSString stringWithContentsOfFile:certsPath encoding:NSUTF8StringEncoding error:&error]; + XCTAssertNil(error); + + options = [[GRPCCallOptions alloc] init]; + options.transportType = GRPCTransportTypeDefault; + options.pemRootCert = certs; + options.hostNameOverride = @"foo.test.google.fr"; + _localSSLService.options = options; +} + +- (void)testEmptyUnaryRPC { + __weak XCTestExpectation *expectRemote = [self expectationWithDescription:@"Remote RPC finish"]; + __weak XCTestExpectation *expectCronetRemote = + [self expectationWithDescription:@"Remote RPC finish"]; + __weak XCTestExpectation *expectCleartext = + [self expectationWithDescription:@"Remote RPC finish"]; + __weak XCTestExpectation *expectSSL = [self expectationWithDescription:@"Remote RPC finish"]; + + GPBEmpty *request = [GPBEmpty message]; + + void (^handler)(GPBEmpty *response, NSError *error) = ^(GPBEmpty *response, NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + + id expectedResponse = [GPBEmpty message]; + XCTAssertEqualObjects(response, expectedResponse); + }; + + [_remoteService emptyCallWithRequest:request + handler:^(GPBEmpty *response, NSError *error) { + handler(response, error); + [expectRemote fulfill]; + }]; + [_remoteCronetService emptyCallWithRequest:request + handler:^(GPBEmpty *response, NSError *error) { + handler(response, error); + [expectCronetRemote fulfill]; + }]; + [_localCleartextService emptyCallWithRequest:request + handler:^(GPBEmpty *response, NSError *error) { + handler(response, error); + [expectCleartext fulfill]; + }]; + [_localSSLService emptyCallWithRequest:request + handler:^(GPBEmpty *response, NSError *error) { + handler(response, error); + [expectSSL fulfill]; + }]; + + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + +- (void)testFullDuplexRPC { + __weak XCTestExpectation *expectRemote = [self expectationWithDescription:@"Remote RPC finish"]; + __weak XCTestExpectation *expectCronetRemote = + [self expectationWithDescription:@"Remote RPC finish"]; + __weak XCTestExpectation *expectCleartext = + [self expectationWithDescription:@"Remote RPC finish"]; + __weak XCTestExpectation *expectSSL = [self expectationWithDescription:@"Remote RPC finish"]; + + NSArray *requestSizes = @[ @100, @101, @102, @103 ]; + NSArray *responseSizes = @[ @104, @105, @106, @107 ]; + XCTAssertEqual([requestSizes count], [responseSizes count]); + NSUInteger kRounds = [requestSizes count]; + + NSMutableArray *requests = [NSMutableArray arrayWithCapacity:kRounds]; + NSMutableArray *responses = [NSMutableArray arrayWithCapacity:kRounds]; + for (int i = 0; i < kRounds; i++) { + requests[i] = [RMTStreamingOutputCallRequest messageWithPayloadSize:requestSizes[i] + requestedResponseSize:responseSizes[i]]; + responses[i] = [RMTStreamingOutputCallResponse messageWithPayloadSize:responseSizes[i]]; + } + + __block NSMutableArray *steps = [NSMutableArray arrayWithCapacity:4]; + __block NSMutableArray *requestsBuffers = [NSMutableArray arrayWithCapacity:4]; + for (int i = 0; i < 4; i++) { + steps[i] = [NSNumber numberWithUnsignedInteger:0]; + requestsBuffers[i] = [[GRXBufferedPipe alloc] init]; + [requestsBuffers[i] writeValue:requests[0]]; + } + + BOOL (^handler)(int, BOOL, RMTStreamingOutputCallResponse *, NSError *) = + ^(int index, BOOL done, RMTStreamingOutputCallResponse *response, NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", error); + XCTAssertTrue(done || response, @"Event handler called without an event."); + if (response) { + NSUInteger step = [steps[index] unsignedIntegerValue]; + XCTAssertLessThan(step, kRounds, @"More than %lu responses received.", + (unsigned long)kRounds); + XCTAssertEqualObjects(response, responses[step]); + step++; + steps[index] = [NSNumber numberWithUnsignedInteger:step]; + GRXBufferedPipe *pipe = requestsBuffers[index]; + if (step < kRounds) { + [pipe writeValue:requests[step]]; + } else { + [pipe writesFinishedWithError:nil]; + } + } + if (done) { + NSUInteger step = [steps[index] unsignedIntegerValue]; + XCTAssertEqual(step, kRounds, @"Received %lu responses instead of %lu.", step, kRounds); + return YES; + } + return NO; + }; + + [_remoteService + fullDuplexCallWithRequestsWriter:requestsBuffers[0] + eventHandler:^(BOOL done, + RMTStreamingOutputCallResponse *_Nullable response, + NSError *_Nullable error) { + if (handler(0, done, response, error)) { + [expectRemote fulfill]; + } + }]; + [_remoteCronetService + fullDuplexCallWithRequestsWriter:requestsBuffers[1] + eventHandler:^(BOOL done, + RMTStreamingOutputCallResponse *_Nullable response, + NSError *_Nullable error) { + if (handler(1, done, response, error)) { + [expectCronetRemote fulfill]; + } + }]; + [_localCleartextService + fullDuplexCallWithRequestsWriter:requestsBuffers[2] + eventHandler:^(BOOL done, + RMTStreamingOutputCallResponse *_Nullable response, + NSError *_Nullable error) { + if (handler(2, done, response, error)) { + [expectCleartext fulfill]; + } + }]; + [_localSSLService + fullDuplexCallWithRequestsWriter:requestsBuffers[3] + eventHandler:^(BOOL done, + RMTStreamingOutputCallResponse *_Nullable response, + NSError *_Nullable error) { + if (handler(3, done, response, error)) { + [expectSSL fulfill]; + } + }]; + + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + +@end diff --git a/src/objective-c/tests/InteropTestsRemote.m b/src/objective-c/tests/InteropTestsRemote.m index e5738aac73b..516a1f432a5 100644 --- a/src/objective-c/tests/InteropTestsRemote.m +++ b/src/objective-c/tests/InteropTestsRemote.m @@ -41,8 +41,26 @@ static int32_t kRemoteInteropServerOverhead = 12; return kRemoteSSLHost; } ++ (NSString *)pemRootCert { + return nil; +} + ++ (NSString *)hostNameOverride { + return nil; +} + - (int32_t)encodingOverhead { return kRemoteInteropServerOverhead; // bytes } +#ifdef GRPC_COMPILE_WITH_CRONET ++ (GRPCTransportType)transportType { + return GRPCTransportTypeCronet; +} +#else ++ (GRPCTransportType)transportType { + return GRPCTransportTypeDefault; +} +#endif + @end diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile index 5d2f1340daa..e87aba235ad 100644 --- a/src/objective-c/tests/Podfile +++ b/src/objective-c/tests/Podfile @@ -14,6 +14,8 @@ GRPC_LOCAL_SRC = '../../..' InteropTestsLocalSSL InteropTestsLocalCleartext InteropTestsRemoteWithCronet + InteropTestsMultipleChannels + InteropTestsCallOptions UnitTests ).each do |target_name| target target_name do @@ -30,7 +32,7 @@ GRPC_LOCAL_SRC = '../../..' pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC, :inhibit_warnings => true pod 'RemoteTest', :path => "RemoteTestClient", :inhibit_warnings => true - if target_name == 'InteropTestsRemoteWithCronet' + if target_name == 'InteropTestsRemoteWithCronet' or target_name == 'InteropTestsMultipleChannels' pod 'gRPC-Core/Cronet-Implementation', :path => GRPC_LOCAL_SRC pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" end @@ -72,6 +74,12 @@ end end end +target 'ChannelTests' do + pod 'gRPC', :path => GRPC_LOCAL_SRC + pod 'gRPC-Core', :path => GRPC_LOCAL_SRC + pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true +end + # gRPC-Core.podspec needs to be modified to be successfully used for local development. A Podfile's # pre_install hook lets us do that. The block passed to it runs after the podspecs are downloaded # and before they are installed in the user project. diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj index f0d81232635..104fd0a4ea0 100644 --- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj +++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj @@ -11,14 +11,23 @@ 09B76D9585ACE7403804D9DC /* libPods-InteropTestsRemoteWithCronet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9E9444C764F0FFF64A7EB58E /* libPods-InteropTestsRemoteWithCronet.a */; }; 0F9232F984C08643FD40C34F /* libPods-InteropTestsRemote.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DBE059B4AC7A51919467EEC0 /* libPods-InteropTestsRemote.a */; }; 16A9E77B6E336B3C0B9BA6E0 /* libPods-InteropTestsLocalSSL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DBEDE45BDA60DF1E1C8950C0 /* libPods-InteropTestsLocalSSL.a */; }; + 1A0FB7F8C95A2F82538BC950 /* libPods-ChannelTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 48F1841C9A920626995DC28C /* libPods-ChannelTests.a */; }; 20DFDF829DD993A4A00D5662 /* libPods-RxLibraryUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */; }; 333E8FC01C8285B7C547D799 /* libPods-InteropTestsLocalCleartext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD346DB2C23F676C4842F3FF /* libPods-InteropTestsLocalCleartext.a */; }; 5E0282E9215AA697007AC99D /* UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E0282E8215AA697007AC99D /* UnitTests.m */; }; 5E0282EB215AA697007AC99D /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; + 5E7D71AD210954A8001EA6BA /* TestCertificates.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */; }; + 5E7D71B5210B9EC9001EA6BA /* InteropTestsCallOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E7D71B4210B9EC9001EA6BA /* InteropTestsCallOptions.m */; }; + 5E7D71B7210B9EC9001EA6BA /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; 5E8A5DA71D3840B4000F8BC4 /* CoreCronetEnd2EndTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.mm */; }; 5E8A5DA91D3840B4000F8BC4 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; 5EAD6D271E27047400002378 /* CronetUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EAD6D261E27047400002378 /* CronetUnitTests.m */; }; 5EAD6D291E27047400002378 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; + 5EB2A2E72107DED300EB4B69 /* ChannelTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EB2A2E62107DED300EB4B69 /* ChannelTests.m */; }; + 5EB2A2E92107DED300EB4B69 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; + 5EB2A2F82109284500EB4B69 /* InteropTestsMultipleChannels.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EB2A2F72109284500EB4B69 /* InteropTestsMultipleChannels.m */; }; + 5EB2A2FA2109284500EB4B69 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; + 5EB5C3AA21656CEA00ADC300 /* ChannelPoolTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EB5C3A921656CEA00ADC300 /* ChannelPoolTest.m */; }; 5EC5E42B2081782C000EF4AD /* InteropTestsRemote.m in Sources */ = {isa = PBXBuildFile; fileRef = 6379CC4F1BE16703001BC0A1 /* InteropTestsRemote.m */; }; 5EC5E42C20817832000EF4AD /* InteropTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */; }; 5EC5E43B208185A7000EF4AD /* InteropTestsLocalCleartext.m in Sources */ = {isa = PBXBuildFile; fileRef = 63715F551B780C020029CB0B /* InteropTestsLocalCleartext.m */; }; @@ -53,6 +62,8 @@ 63DC84501BE153AA000708E8 /* GRPCClientTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */; }; 63E240CE1B6C4E2B005F3B0E /* InteropTestsLocalSSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 63E240CD1B6C4E2B005F3B0E /* InteropTestsLocalSSL.m */; }; 63E240D01B6C63DC005F3B0E /* TestCertificates.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */; }; + 6C1A3F81CCF7C998B4813EFD /* libPods-InteropTestsCallOptions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF3FC2CFFE7B0961823BC740 /* libPods-InteropTestsCallOptions.a */; }; + 886717A79EFF774F356798E6 /* libPods-InteropTestsMultipleChannels.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 355D0E30AD224763BC9519F4 /* libPods-InteropTestsMultipleChannels.a */; }; 91D4B3C85B6D8562F409CB48 /* libPods-InteropTestsLocalSSLCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F3AB031E0E26AC8EF30A2A2A /* libPods-InteropTestsLocalSSLCFStream.a */; }; BC111C80CBF7068B62869352 /* libPods-InteropTestsRemoteCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F44AC3F44E3491A8C0D890FE /* libPods-InteropTestsRemoteCFStream.a */; }; C3D6F4270A2FFF634D8849ED /* libPods-InteropTestsLocalCleartextCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BDA4BA011779D5D25B5618C /* libPods-InteropTestsLocalCleartextCFStream.a */; }; @@ -68,6 +79,13 @@ remoteGlobalIDString = 635697C61B14FC11007A7283; remoteInfo = Tests; }; + 5E7D71B8210B9EC9001EA6BA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 635697BF1B14FC11007A7283 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 635697C61B14FC11007A7283; + remoteInfo = Tests; + }; 5E8A5DAA1D3840B4000F8BC4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 635697BF1B14FC11007A7283 /* Project object */; @@ -82,6 +100,20 @@ remoteGlobalIDString = 635697C61B14FC11007A7283; remoteInfo = Tests; }; + 5EB2A2EA2107DED300EB4B69 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 635697BF1B14FC11007A7283 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 635697C61B14FC11007A7283; + remoteInfo = Tests; + }; + 5EB2A2FB2109284500EB4B69 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 635697BF1B14FC11007A7283 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 635697C61B14FC11007A7283; + remoteInfo = Tests; + }; 5EE84BF71D4717E40050C6CC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 635697BF1B14FC11007A7283 /* Project object */; @@ -144,20 +176,26 @@ 0A4F89D9C90E9C30990218F0 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 0BDA4BA011779D5D25B5618C /* libPods-InteropTestsLocalCleartextCFStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalCleartextCFStream.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 0D2284C3DF7E57F0ED504E39 /* Pods-CoreCronetEnd2EndTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.debug.xcconfig"; sourceTree = ""; }; + 1295CCBD1082B4A7CFCED95F /* Pods-InteropTestsMultipleChannels.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsMultipleChannels.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsMultipleChannels/Pods-InteropTestsMultipleChannels.cronet.xcconfig"; sourceTree = ""; }; 14B09A58FEE53A7A6B838920 /* Pods-InteropTestsLocalSSL.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.cronet.xcconfig"; sourceTree = ""; }; 1588C85DEAF7FC0ACDEA4C02 /* Pods-InteropTestsLocalCleartext.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.test.xcconfig"; sourceTree = ""; }; 17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; sourceTree = ""; }; 20DFF2F3C97EF098FE5A3171 /* libPods-Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-UnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 2650FEF00956E7924772F9D9 /* Pods-InteropTestsMultipleChannels.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsMultipleChannels.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsMultipleChannels/Pods-InteropTestsMultipleChannels.release.xcconfig"; sourceTree = ""; }; 2B89F3037963E6EDDD48D8C3 /* Pods-InteropTestsRemoteWithCronet.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.test.xcconfig"; sourceTree = ""; }; 303F4A17EB1650FC44603D17 /* Pods-InteropTestsRemoteCFStream.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteCFStream.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream.release.xcconfig"; sourceTree = ""; }; 32748C4078AEB05F8F954361 /* Pods-InteropTestsRemoteCFStream.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteCFStream.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream.debug.xcconfig"; sourceTree = ""; }; + 355D0E30AD224763BC9519F4 /* libPods-InteropTestsMultipleChannels.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsMultipleChannels.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 35F2B6BF3BAE8F0DC4AFD76E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 386712AEACF7C2190C4B8B3F /* Pods-CronetUnitTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CronetUnitTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-CronetUnitTests/Pods-CronetUnitTests.cronet.xcconfig"; sourceTree = ""; }; + 3A98DF08852F60AF1D96481D /* Pods-InteropTestsCallOptions.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsCallOptions.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsCallOptions/Pods-InteropTestsCallOptions.debug.xcconfig"; sourceTree = ""; }; 3B0861FC805389C52DB260D4 /* Pods-RxLibraryUnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxLibraryUnitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests.release.xcconfig"; sourceTree = ""; }; + 3CADF86203B9D03EA96C359D /* Pods-InteropTestsMultipleChannels.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsMultipleChannels.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsMultipleChannels/Pods-InteropTestsMultipleChannels.debug.xcconfig"; sourceTree = ""; }; 3EB55EF291706E3DDE23C3B7 /* Pods-InteropTestsLocalSSLCFStream.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSLCFStream.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSLCFStream/Pods-InteropTestsLocalSSLCFStream.debug.xcconfig"; sourceTree = ""; }; 3F27B2E744482771EB93C394 /* Pods-InteropTestsRemoteWithCronet.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.cronet.xcconfig"; sourceTree = ""; }; 41AA59529240A6BBBD3DB904 /* Pods-InteropTestsLocalSSLCFStream.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSLCFStream.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSLCFStream/Pods-InteropTestsLocalSSLCFStream.test.xcconfig"; sourceTree = ""; }; + 48F1841C9A920626995DC28C /* libPods-ChannelTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ChannelTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 4A1A42B2E941CCD453489E5B /* Pods-InteropTestsRemoteCFStream.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteCFStream.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream.cronet.xcconfig"; sourceTree = ""; }; 4AD97096D13D7416DC91A72A /* Pods-CoreCronetEnd2EndTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.release.xcconfig"; sourceTree = ""; }; 4ADEA1C8BBE10D90940AC68E /* Pods-InteropTestsRemote.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.cronet.xcconfig"; sourceTree = ""; }; @@ -169,6 +207,9 @@ 5E0282E6215AA697007AC99D /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5E0282E8215AA697007AC99D /* UnitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UnitTests.m; sourceTree = ""; }; 5E0282EA215AA697007AC99D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5E7D71B2210B9EC8001EA6BA /* InteropTestsCallOptions.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsCallOptions.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 5E7D71B4210B9EC9001EA6BA /* InteropTestsCallOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InteropTestsCallOptions.m; sourceTree = ""; }; + 5E7D71B6210B9EC9001EA6BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 5E8A5DA41D3840B4000F8BC4 /* CoreCronetEnd2EndTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreCronetEnd2EndTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CoreCronetEnd2EndTests.mm; sourceTree = ""; }; 5EA908CF4CDA4CE218352A06 /* Pods-InteropTestsLocalSSLCFStream.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSLCFStream.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSLCFStream/Pods-InteropTestsLocalSSLCFStream.release.xcconfig"; sourceTree = ""; }; @@ -176,6 +217,13 @@ 5EAD6D261E27047400002378 /* CronetUnitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CronetUnitTests.m; sourceTree = ""; }; 5EAD6D281E27047400002378 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 5EAFE8271F8EFB87007F2189 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; + 5EB2A2E42107DED300EB4B69 /* ChannelTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ChannelTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 5EB2A2E62107DED300EB4B69 /* ChannelTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ChannelTests.m; sourceTree = ""; }; + 5EB2A2E82107DED300EB4B69 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5EB2A2F52109284500EB4B69 /* InteropTestsMultipleChannels.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsMultipleChannels.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 5EB2A2F72109284500EB4B69 /* InteropTestsMultipleChannels.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InteropTestsMultipleChannels.m; sourceTree = ""; }; + 5EB2A2F92109284500EB4B69 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5EB5C3A921656CEA00ADC300 /* ChannelPoolTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ChannelPoolTest.m; sourceTree = ""; }; 5EC5E421208177CC000EF4AD /* InteropTestsRemoteCFStream.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsRemoteCFStream.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5EC5E4312081856B000EF4AD /* InteropTestsLocalCleartextCFStream.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsLocalCleartextCFStream.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5EC5E442208185CE000EF4AD /* InteropTestsLocalSSLCFStream.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsLocalSSLCFStream.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -200,25 +248,32 @@ 63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = TestCertificates.bundle; sourceTree = ""; }; 64F68A9A6A63CC930DD30A6E /* Pods-CronetUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CronetUnitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CronetUnitTests/Pods-CronetUnitTests.debug.xcconfig"; sourceTree = ""; }; 6793C9D019CB268C5BB491A2 /* Pods-CoreCronetEnd2EndTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.test.xcconfig"; sourceTree = ""; }; + 73D2DF07027835BA0FB0B1C0 /* Pods-InteropTestsCallOptions.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsCallOptions.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsCallOptions/Pods-InteropTestsCallOptions.cronet.xcconfig"; sourceTree = ""; }; 781089FAE980F51F88A3BE0B /* Pods-RxLibraryUnitTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxLibraryUnitTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests.test.xcconfig"; sourceTree = ""; }; 79C68EFFCB5533475D810B79 /* Pods-RxLibraryUnitTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxLibraryUnitTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests.cronet.xcconfig"; sourceTree = ""; }; 7A2E97E3F469CC2A758D77DE /* Pods-InteropTestsLocalSSL.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.release.xcconfig"; sourceTree = ""; }; 7BA53C6D224288D5870FE6F3 /* Pods-InteropTestsLocalCleartextCFStream.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.release.xcconfig"; sourceTree = ""; }; 8B498B05C6DA0818B2FA91D4 /* Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig"; sourceTree = ""; }; + 90E63AD3C4A1E3E6BC745096 /* Pods-ChannelTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChannelTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-ChannelTests/Pods-ChannelTests.cronet.xcconfig"; sourceTree = ""; }; 943138072A9605B5B8DC1FC0 /* Pods-InteropTestsLocalCleartextCFStream.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.debug.xcconfig"; sourceTree = ""; }; 94D7A5FAA13480E9A5166D7A /* Pods-UnitTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.test.xcconfig"; sourceTree = ""; }; 9E9444C764F0FFF64A7EB58E /* libPods-InteropTestsRemoteWithCronet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemoteWithCronet.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + A25967A0D40ED14B3287AD81 /* Pods-InteropTestsCallOptions.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsCallOptions.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsCallOptions/Pods-InteropTestsCallOptions.test.xcconfig"; sourceTree = ""; }; A2DCF2570BE515B62CB924CA /* Pods-UnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.debug.xcconfig"; sourceTree = ""; }; A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RxLibraryUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A6F832FCEFA6F6881E620F12 /* Pods-InteropTestsRemote.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.test.xcconfig"; sourceTree = ""; }; AA7CB64B4DD9915AE7C03163 /* Pods-InteropTestsLocalCleartext.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.cronet.xcconfig"; sourceTree = ""; }; AC414EF7A6BF76ED02B6E480 /* Pods-InteropTestsRemoteWithCronet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.release.xcconfig"; sourceTree = ""; }; + AF3FC2CFFE7B0961823BC740 /* libPods-InteropTestsCallOptions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsCallOptions.a"; sourceTree = BUILT_PRODUCTS_DIR; }; B226619DC4E709E0FFFF94B8 /* Pods-CronetUnitTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CronetUnitTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-CronetUnitTests/Pods-CronetUnitTests.test.xcconfig"; sourceTree = ""; }; B94C27C06733CF98CE1B2757 /* Pods-AllTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.debug.xcconfig"; sourceTree = ""; }; + BED74BC8ABF9917C66175879 /* Pods-ChannelTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChannelTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-ChannelTests/Pods-ChannelTests.test.xcconfig"; sourceTree = ""; }; C17F57E5BCB989AB1C2F1F25 /* Pods-InteropTestsRemoteCFStream.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteCFStream.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream.test.xcconfig"; sourceTree = ""; }; C6134277D2EB8B380862A03F /* libPods-CronetUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CronetUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + C9172F9020E8C97A470D7250 /* Pods-InteropTestsCallOptions.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsCallOptions.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsCallOptions/Pods-InteropTestsCallOptions.release.xcconfig"; sourceTree = ""; }; CAE086D5B470DA367D415AB0 /* libPods-AllTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AllTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; D13BEC8181B8E678A1B52F54 /* Pods-InteropTestsLocalSSL.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.test.xcconfig"; sourceTree = ""; }; + D52B92A7108602F170DA8091 /* Pods-ChannelTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChannelTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ChannelTests/Pods-ChannelTests.release.xcconfig"; sourceTree = ""; }; DB1F4391AF69D20D38D74B67 /* Pods-AllTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.test.xcconfig"; sourceTree = ""; }; DBE059B4AC7A51919467EEC0 /* libPods-InteropTestsRemote.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemote.a"; sourceTree = BUILT_PRODUCTS_DIR; }; DBEDE45BDA60DF1E1C8950C0 /* libPods-InteropTestsLocalSSL.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalSSL.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -228,9 +283,11 @@ E4275A759BDBDF143B9B438F /* Pods-InteropTestsRemote.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.release.xcconfig"; sourceTree = ""; }; E4FD4606D4AB8D5A314D72F0 /* Pods-InteropTestsLocalCleartextCFStream.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.test.xcconfig"; sourceTree = ""; }; E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.cronet.xcconfig"; sourceTree = ""; }; + EA8B122ACDE73E3AAA0E4A19 /* Pods-InteropTestsMultipleChannels.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsMultipleChannels.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsMultipleChannels/Pods-InteropTestsMultipleChannels.test.xcconfig"; sourceTree = ""; }; EBFFEC04B514CB0D4922DC40 /* Pods-UnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.release.xcconfig"; sourceTree = ""; }; F3AB031E0E26AC8EF30A2A2A /* libPods-InteropTestsLocalSSLCFStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalSSLCFStream.a"; sourceTree = BUILT_PRODUCTS_DIR; }; F44AC3F44E3491A8C0D890FE /* libPods-InteropTestsRemoteCFStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemoteCFStream.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + F9E48EF5ACB1F38825171C5F /* Pods-ChannelTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChannelTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ChannelTests/Pods-ChannelTests.debug.xcconfig"; sourceTree = ""; }; FBD98AC417B9882D32B19F28 /* libPods-CoreCronetEnd2EndTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CoreCronetEnd2EndTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FD346DB2C23F676C4842F3FF /* libPods-InteropTestsLocalCleartext.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalCleartext.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FF7B5489BCFE40111D768DD0 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; @@ -246,6 +303,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5E7D71AF210B9EC8001EA6BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5E7D71B7210B9EC9001EA6BA /* libTests.a in Frameworks */, + 6C1A3F81CCF7C998B4813EFD /* libPods-InteropTestsCallOptions.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5E8A5DA11D3840B4000F8BC4 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -264,6 +330,24 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5EB2A2E12107DED300EB4B69 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5EB2A2E92107DED300EB4B69 /* libTests.a in Frameworks */, + 1A0FB7F8C95A2F82538BC950 /* libPods-ChannelTests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5EB2A2F22109284500EB4B69 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5EB2A2FA2109284500EB4B69 /* libTests.a in Frameworks */, + 886717A79EFF774F356798E6 /* libPods-InteropTestsMultipleChannels.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5EC5E41E208177CC000EF4AD /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -368,6 +452,9 @@ F44AC3F44E3491A8C0D890FE /* libPods-InteropTestsRemoteCFStream.a */, 0BDA4BA011779D5D25B5618C /* libPods-InteropTestsLocalCleartextCFStream.a */, F3AB031E0E26AC8EF30A2A2A /* libPods-InteropTestsLocalSSLCFStream.a */, + 48F1841C9A920626995DC28C /* libPods-ChannelTests.a */, + 355D0E30AD224763BC9519F4 /* libPods-InteropTestsMultipleChannels.a */, + AF3FC2CFFE7B0961823BC740 /* libPods-InteropTestsCallOptions.a */, 22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */, ); name = Frameworks; @@ -422,6 +509,18 @@ 41AA59529240A6BBBD3DB904 /* Pods-InteropTestsLocalSSLCFStream.test.xcconfig */, 55B630C1FF8C36D1EFC4E0A4 /* Pods-InteropTestsLocalSSLCFStream.cronet.xcconfig */, 5EA908CF4CDA4CE218352A06 /* Pods-InteropTestsLocalSSLCFStream.release.xcconfig */, + F9E48EF5ACB1F38825171C5F /* Pods-ChannelTests.debug.xcconfig */, + BED74BC8ABF9917C66175879 /* Pods-ChannelTests.test.xcconfig */, + 90E63AD3C4A1E3E6BC745096 /* Pods-ChannelTests.cronet.xcconfig */, + D52B92A7108602F170DA8091 /* Pods-ChannelTests.release.xcconfig */, + 3CADF86203B9D03EA96C359D /* Pods-InteropTestsMultipleChannels.debug.xcconfig */, + EA8B122ACDE73E3AAA0E4A19 /* Pods-InteropTestsMultipleChannels.test.xcconfig */, + 1295CCBD1082B4A7CFCED95F /* Pods-InteropTestsMultipleChannels.cronet.xcconfig */, + 2650FEF00956E7924772F9D9 /* Pods-InteropTestsMultipleChannels.release.xcconfig */, + 3A98DF08852F60AF1D96481D /* Pods-InteropTestsCallOptions.debug.xcconfig */, + A25967A0D40ED14B3287AD81 /* Pods-InteropTestsCallOptions.test.xcconfig */, + 73D2DF07027835BA0FB0B1C0 /* Pods-InteropTestsCallOptions.cronet.xcconfig */, + C9172F9020E8C97A470D7250 /* Pods-InteropTestsCallOptions.release.xcconfig */, A2DCF2570BE515B62CB924CA /* Pods-UnitTests.debug.xcconfig */, 94D7A5FAA13480E9A5166D7A /* Pods-UnitTests.test.xcconfig */, E1E7660656D902104F728892 /* Pods-UnitTests.cronet.xcconfig */, @@ -439,6 +538,15 @@ path = UnitTests; sourceTree = ""; }; + 5E7D71B3210B9EC9001EA6BA /* InteropTestsCallOptions */ = { + isa = PBXGroup; + children = ( + 5E7D71B4210B9EC9001EA6BA /* InteropTestsCallOptions.m */, + 5E7D71B6210B9EC9001EA6BA /* Info.plist */, + ); + path = InteropTestsCallOptions; + sourceTree = ""; + }; 5E8A5DA51D3840B4000F8BC4 /* CoreCronetEnd2EndTests */ = { isa = PBXGroup; children = ( @@ -456,6 +564,25 @@ path = CronetUnitTests; sourceTree = ""; }; + 5EB2A2E52107DED300EB4B69 /* ChannelTests */ = { + isa = PBXGroup; + children = ( + 5EB5C3A921656CEA00ADC300 /* ChannelPoolTest.m */, + 5EB2A2E62107DED300EB4B69 /* ChannelTests.m */, + 5EB2A2E82107DED300EB4B69 /* Info.plist */, + ); + path = ChannelTests; + sourceTree = ""; + }; + 5EB2A2F62109284500EB4B69 /* InteropTestsMultipleChannels */ = { + isa = PBXGroup; + children = ( + 5EB2A2F72109284500EB4B69 /* InteropTestsMultipleChannels.m */, + 5EB2A2F92109284500EB4B69 /* Info.plist */, + ); + path = InteropTestsMultipleChannels; + sourceTree = ""; + }; 5EE84BF21D4717E40050C6CC /* InteropTestsRemoteWithCronet */ = { isa = PBXGroup; children = ( @@ -473,6 +600,9 @@ 5E8A5DA51D3840B4000F8BC4 /* CoreCronetEnd2EndTests */, 5EE84BF21D4717E40050C6CC /* InteropTestsRemoteWithCronet */, 5EAD6D251E27047400002378 /* CronetUnitTests */, + 5EB2A2E52107DED300EB4B69 /* ChannelTests */, + 5EB2A2F62109284500EB4B69 /* InteropTestsMultipleChannels */, + 5E7D71B3210B9EC9001EA6BA /* InteropTestsCallOptions */, 5E0282E7215AA697007AC99D /* UnitTests */, 635697C81B14FC11007A7283 /* Products */, 51E4650F34F854F41FF053B3 /* Pods */, @@ -495,6 +625,9 @@ 5EC5E421208177CC000EF4AD /* InteropTestsRemoteCFStream.xctest */, 5EC5E4312081856B000EF4AD /* InteropTestsLocalCleartextCFStream.xctest */, 5EC5E442208185CE000EF4AD /* InteropTestsLocalSSLCFStream.xctest */, + 5EB2A2E42107DED300EB4B69 /* ChannelTests.xctest */, + 5EB2A2F52109284500EB4B69 /* InteropTestsMultipleChannels.xctest */, + 5E7D71B2210B9EC8001EA6BA /* InteropTestsCallOptions.xctest */, 5E0282E6215AA697007AC99D /* UnitTests.xctest */, ); name = Products; @@ -548,6 +681,26 @@ productReference = 5E0282E6215AA697007AC99D /* UnitTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 5E7D71B1210B9EC8001EA6BA /* InteropTestsCallOptions */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5E7D71BA210B9EC9001EA6BA /* Build configuration list for PBXNativeTarget "InteropTestsCallOptions" */; + buildPhases = ( + 2865C6386D677998F861E183 /* [CP] Check Pods Manifest.lock */, + 5E7D71AE210B9EC8001EA6BA /* Sources */, + 5E7D71AF210B9EC8001EA6BA /* Frameworks */, + 5E7D71B0210B9EC8001EA6BA /* Resources */, + 6BA6D00B1816306453BF82D4 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 5E7D71B9210B9EC9001EA6BA /* PBXTargetDependency */, + ); + name = InteropTestsCallOptions; + productName = InteropTestsCallOptions; + productReference = 5E7D71B2210B9EC8001EA6BA /* InteropTestsCallOptions.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 5E8A5DA31D3840B4000F8BC4 /* CoreCronetEnd2EndTests */ = { isa = PBXNativeTarget; buildConfigurationList = 5E8A5DAE1D3840B4000F8BC4 /* Build configuration list for PBXNativeTarget "CoreCronetEnd2EndTests" */; @@ -588,6 +741,47 @@ productReference = 5EAD6D241E27047400002378 /* CronetUnitTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 5EB2A2E32107DED300EB4B69 /* ChannelTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5EB2A2F02107DED300EB4B69 /* Build configuration list for PBXNativeTarget "ChannelTests" */; + buildPhases = ( + 021B3B1F545989843EBC9A4B /* [CP] Check Pods Manifest.lock */, + 5EB2A2E02107DED300EB4B69 /* Sources */, + 5EB2A2E12107DED300EB4B69 /* Frameworks */, + 5EB2A2E22107DED300EB4B69 /* Resources */, + 1EAF0CBDBFAB18D4DA64535D /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 5EB2A2EB2107DED300EB4B69 /* PBXTargetDependency */, + ); + name = ChannelTests; + productName = ChannelTests; + productReference = 5EB2A2E42107DED300EB4B69 /* ChannelTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 5EB2A2F42109284500EB4B69 /* InteropTestsMultipleChannels */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5EB2A3012109284500EB4B69 /* Build configuration list for PBXNativeTarget "InteropTestsMultipleChannels" */; + buildPhases = ( + 8C1ED025E07C4D457C355336 /* [CP] Check Pods Manifest.lock */, + 5EB2A2F12109284500EB4B69 /* Sources */, + 5EB2A2F22109284500EB4B69 /* Frameworks */, + 5EB2A2F32109284500EB4B69 /* Resources */, + 8D685CB612835DB3F7A6F14A /* [CP] Embed Pods Frameworks */, + 0617B5294978A95BEBBFF733 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 5EB2A2FC2109284500EB4B69 /* PBXTargetDependency */, + ); + name = InteropTestsMultipleChannels; + productName = InteropTestsMultipleChannels; + productReference = 5EB2A2F52109284500EB4B69 /* InteropTestsMultipleChannels.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 5EC5E420208177CC000EF4AD /* InteropTestsRemoteCFStream */ = { isa = PBXNativeTarget; buildConfigurationList = 5EC5E42A208177CD000EF4AD /* Build configuration list for PBXNativeTarget "InteropTestsRemoteCFStream" */; @@ -796,12 +990,24 @@ CreatedOnToolsVersion = 9.2; ProvisioningStyle = Automatic; }; + 5E7D71B1210B9EC8001EA6BA = { + CreatedOnToolsVersion = 9.3; + ProvisioningStyle = Automatic; + }; 5E8A5DA31D3840B4000F8BC4 = { CreatedOnToolsVersion = 7.3.1; }; 5EAD6D231E27047400002378 = { CreatedOnToolsVersion = 7.3.1; }; + 5EB2A2E32107DED300EB4B69 = { + CreatedOnToolsVersion = 9.3; + ProvisioningStyle = Automatic; + }; + 5EB2A2F42109284500EB4B69 = { + CreatedOnToolsVersion = 9.3; + ProvisioningStyle = Automatic; + }; 5EC5E420208177CC000EF4AD = { CreatedOnToolsVersion = 9.2; ProvisioningStyle = Automatic; @@ -861,6 +1067,9 @@ 5EC5E420208177CC000EF4AD /* InteropTestsRemoteCFStream */, 5EC5E4302081856B000EF4AD /* InteropTestsLocalCleartextCFStream */, 5EC5E441208185CE000EF4AD /* InteropTestsLocalSSLCFStream */, + 5EB2A2E32107DED300EB4B69 /* ChannelTests */, + 5EB2A2F42109284500EB4B69 /* InteropTestsMultipleChannels */, + 5E7D71B1210B9EC8001EA6BA /* InteropTestsCallOptions */, 5E0282E5215AA697007AC99D /* UnitTests */, ); }; @@ -874,6 +1083,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5E7D71B0210B9EC8001EA6BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5E8A5DA21D3840B4000F8BC4 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -888,6 +1104,21 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5EB2A2E22107DED300EB4B69 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5EB2A2F32109284500EB4B69 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5E7D71AD210954A8001EA6BA /* TestCertificates.bundle in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5EC5E41F208177CC000EF4AD /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -957,6 +1188,60 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 021B3B1F545989843EBC9A4B /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-ChannelTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 0617B5294978A95BEBBFF733 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsMultipleChannels/Pods-InteropTestsMultipleChannels-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsMultipleChannels/Pods-InteropTestsMultipleChannels-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 1EAF0CBDBFAB18D4DA64535D /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-ChannelTests/Pods-ChannelTests-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ChannelTests/Pods-ChannelTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 252A376345E38FD452A89C3D /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -975,6 +1260,24 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 2865C6386D677998F861E183 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-InteropTestsCallOptions-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 31F8D1C407195CBF0C02929B /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1083,6 +1386,24 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL-resources.sh\"\n"; showEnvVarsInLog = 0; }; + 6BA6D00B1816306453BF82D4 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsCallOptions/Pods-InteropTestsCallOptions-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsCallOptions/Pods-InteropTestsCallOptions-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 7418AC7B3844B29E48D24FC7 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1137,6 +1458,42 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext-resources.sh\"\n"; showEnvVarsInLog = 0; }; + 8C1ED025E07C4D457C355336 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-InteropTestsMultipleChannels-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 8D685CB612835DB3F7A6F14A /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsMultipleChannels/Pods-InteropTestsMultipleChannels-frameworks.sh", + "${PODS_ROOT}/CronetFramework/Cronet.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Cronet.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsMultipleChannels/Pods-InteropTestsMultipleChannels-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 914ADDD7106BA9BB8A7E569F /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1418,6 +1775,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5E7D71AE210B9EC8001EA6BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5E7D71B5210B9EC9001EA6BA /* InteropTestsCallOptions.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5E8A5DA01D3840B4000F8BC4 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1434,6 +1799,23 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5EB2A2E02107DED300EB4B69 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5EB2A2E72107DED300EB4B69 /* ChannelTests.m in Sources */, + 5EB5C3AA21656CEA00ADC300 /* ChannelPoolTest.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5EB2A2F12109284500EB4B69 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5EB2A2F82109284500EB4B69 /* InteropTestsMultipleChannels.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5EC5E41D208177CC000EF4AD /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1536,6 +1918,11 @@ target = 635697C61B14FC11007A7283 /* Tests */; targetProxy = 5E0282EC215AA697007AC99D /* PBXContainerItemProxy */; }; + 5E7D71B9210B9EC9001EA6BA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 635697C61B14FC11007A7283 /* Tests */; + targetProxy = 5E7D71B8210B9EC9001EA6BA /* PBXContainerItemProxy */; + }; 5E8A5DAB1D3840B4000F8BC4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 635697C61B14FC11007A7283 /* Tests */; @@ -1546,6 +1933,16 @@ target = 635697C61B14FC11007A7283 /* Tests */; targetProxy = 5EAD6D2A1E27047400002378 /* PBXContainerItemProxy */; }; + 5EB2A2EB2107DED300EB4B69 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 635697C61B14FC11007A7283 /* Tests */; + targetProxy = 5EB2A2EA2107DED300EB4B69 /* PBXContainerItemProxy */; + }; + 5EB2A2FC2109284500EB4B69 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 635697C61B14FC11007A7283 /* Tests */; + targetProxy = 5EB2A2FB2109284500EB4B69 /* PBXContainerItemProxy */; + }; 5EE84BF81D4717E40050C6CC /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 635697C61B14FC11007A7283 /* Tests */; @@ -1909,16 +2306,146 @@ }; name = Test; }; - 5E8A5DAC1D3840B4000F8BC4 /* Debug */ = { + 5E7D71BB210B9EC9001EA6BA /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0D2284C3DF7E57F0ED504E39 /* Pods-CoreCronetEnd2EndTests.debug.xcconfig */; + baseConfigurationReference = 3A98DF08852F60AF1D96481D /* Pods-InteropTestsCallOptions.debug.xcconfig */; buildSettings = { CLANG_ANALYZER_NONNULL = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; - INFOPLIST_FILE = CoreCronetEnd2EndTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.3; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = InteropTestsCallOptions/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsCallOptions; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 5E7D71BC210B9EC9001EA6BA /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A25967A0D40ED14B3287AD81 /* Pods-InteropTestsCallOptions.test.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = InteropTestsCallOptions/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsCallOptions; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Test; + }; + 5E7D71BD210B9EC9001EA6BA /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 73D2DF07027835BA0FB0B1C0 /* Pods-InteropTestsCallOptions.cronet.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = InteropTestsCallOptions/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsCallOptions; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Cronet; + }; + 5E7D71BE210B9EC9001EA6BA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C9172F9020E8C97A470D7250 /* Pods-InteropTestsCallOptions.release.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = InteropTestsCallOptions/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsCallOptions; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 5E8A5DAC1D3840B4000F8BC4 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0D2284C3DF7E57F0ED504E39 /* Pods-CoreCronetEnd2EndTests.debug.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + INFOPLIST_FILE = CoreCronetEnd2EndTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -2011,6 +2538,266 @@ }; name = Release; }; + 5EB2A2EC2107DED300EB4B69 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F9E48EF5ACB1F38825171C5F /* Pods-ChannelTests.debug.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = ChannelTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.ChannelTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 5EB2A2ED2107DED300EB4B69 /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BED74BC8ABF9917C66175879 /* Pods-ChannelTests.test.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = ChannelTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.ChannelTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Test; + }; + 5EB2A2EE2107DED300EB4B69 /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 90E63AD3C4A1E3E6BC745096 /* Pods-ChannelTests.cronet.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = ChannelTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.ChannelTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Cronet; + }; + 5EB2A2EF2107DED300EB4B69 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D52B92A7108602F170DA8091 /* Pods-ChannelTests.release.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = ChannelTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.ChannelTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 5EB2A2FD2109284500EB4B69 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3CADF86203B9D03EA96C359D /* Pods-InteropTestsMultipleChannels.debug.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = InteropTestsMultipleChannels/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsMultipleChannels; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 5EB2A2FE2109284500EB4B69 /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EA8B122ACDE73E3AAA0E4A19 /* Pods-InteropTestsMultipleChannels.test.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = InteropTestsMultipleChannels/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsMultipleChannels; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Test; + }; + 5EB2A2FF2109284500EB4B69 /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1295CCBD1082B4A7CFCED95F /* Pods-InteropTestsMultipleChannels.cronet.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = InteropTestsMultipleChannels/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsMultipleChannels; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Cronet; + }; + 5EB2A3002109284500EB4B69 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2650FEF00956E7924772F9D9 /* Pods-InteropTestsMultipleChannels.release.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = InteropTestsMultipleChannels/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.InteropTestsMultipleChannels; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; 5EC3C7A01D4FC18C000330E2 /* Cronet */ = { isa = XCBuildConfiguration; buildSettings = { @@ -2039,6 +2826,8 @@ "DEBUG=1", "$(inherited)", "HOST_PORT_REMOTE=$(HOST_PORT_REMOTE)", + "HOST_PORT_LOCALSSL=$(HOST_PORT_LOCALSSL)", + "HOST_PORT_LOCAL=$(HOST_PORT_LOCAL)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_TREAT_WARNINGS_AS_ERRORS = YES; @@ -2859,6 +3648,17 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 5E7D71BA210B9EC9001EA6BA /* Build configuration list for PBXNativeTarget "InteropTestsCallOptions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5E7D71BB210B9EC9001EA6BA /* Debug */, + 5E7D71BC210B9EC9001EA6BA /* Test */, + 5E7D71BD210B9EC9001EA6BA /* Cronet */, + 5E7D71BE210B9EC9001EA6BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 5E8A5DAE1D3840B4000F8BC4 /* Build configuration list for PBXNativeTarget "CoreCronetEnd2EndTests" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -2881,6 +3681,28 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 5EB2A2F02107DED300EB4B69 /* Build configuration list for PBXNativeTarget "ChannelTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5EB2A2EC2107DED300EB4B69 /* Debug */, + 5EB2A2ED2107DED300EB4B69 /* Test */, + 5EB2A2EE2107DED300EB4B69 /* Cronet */, + 5EB2A2EF2107DED300EB4B69 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5EB2A3012109284500EB4B69 /* Build configuration list for PBXNativeTarget "InteropTestsMultipleChannels" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5EB2A2FD2109284500EB4B69 /* Debug */, + 5EB2A2FE2109284500EB4B69 /* Test */, + 5EB2A2FF2109284500EB4B69 /* Cronet */, + 5EB2A3002109284500EB4B69 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 5EC5E42A208177CD000EF4AD /* Build configuration list for PBXNativeTarget "InteropTestsRemoteCFStream" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/ChannelTests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/ChannelTests.xcscheme new file mode 100644 index 00000000000..16ae481123b --- /dev/null +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/ChannelTests.xcscheme @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsCallOptions.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsCallOptions.xcscheme new file mode 100644 index 00000000000..dd83282190f --- /dev/null +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsCallOptions.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsLocalCleartext.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsLocalCleartext.xcscheme index 510115fc757..11b41c92140 100644 --- a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsLocalCleartext.xcscheme +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsLocalCleartext.xcscheme @@ -26,7 +26,6 @@ buildConfiguration = "Test" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" shouldUseLaunchSchemeArgsEnv = "YES"> - - - - @@ -58,7 +51,6 @@ buildConfiguration = "Test" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsMultipleChannels.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsMultipleChannels.xcscheme new file mode 100644 index 00000000000..1b4c1f5e51c --- /dev/null +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsMultipleChannels.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemote.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemote.xcscheme index 48837e57f9a..412bf6a0143 100644 --- a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemote.xcscheme +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/InteropTestsRemote.xcscheme @@ -26,7 +26,6 @@ buildConfiguration = "Test" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" shouldUseLaunchSchemeArgsEnv = "YES"> Date: Mon, 8 Oct 2018 15:49:17 -0700 Subject: [PATCH 002/375] Proto-related changes --- src/compiler/objective_c_generator.cc | 103 +++++++++++++++- src/compiler/objective_c_generator.h | 7 +- src/compiler/objective_c_plugin.cc | 21 +++- src/objective-c/ProtoRPC/ProtoRPC.h | 49 ++++++++ src/objective-c/ProtoRPC/ProtoRPC.m | 157 ++++++++++++++++++++++++ src/objective-c/ProtoRPC/ProtoService.h | 28 ++++- src/objective-c/ProtoRPC/ProtoService.m | 47 ++++++- 7 files changed, 399 insertions(+), 13 deletions(-) diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc index 39f68cb9565..eb67e9bb88f 100644 --- a/src/compiler/objective_c_generator.cc +++ b/src/compiler/objective_c_generator.cc @@ -113,6 +113,29 @@ void PrintAdvancedSignature(Printer* printer, const MethodDescriptor* method, PrintMethodSignature(printer, method, vars); } +void PrintV2Signature(Printer* printer, const MethodDescriptor* method, + map< ::grpc::string, ::grpc::string> vars) { + if (method->client_streaming()) { + vars["return_type"] = "GRPCStreamingProtoCall *"; + } else { + vars["return_type"] = "GRPCUnaryProtoCall *"; + } + vars["method_name"] = + grpc_generator::LowercaseFirstLetter(vars["method_name"]); + + PrintAllComments(method, printer); + + printer->Print(vars, "- ($return_type$)$method_name$With"); + if (method->client_streaming()) { + printer->Print("ResponseHandler:(id)handler"); + } else { + printer->Print(vars, + "Message:($request_class$ *)message " + "responseHandler:(id)handler"); + } + printer->Print(" callOptions:(GRPCCallOptions *_Nullable)callOptions"); +} + inline map< ::grpc::string, ::grpc::string> GetMethodVars( const MethodDescriptor* method) { map< ::grpc::string, ::grpc::string> res; @@ -135,6 +158,16 @@ void PrintMethodDeclarations(Printer* printer, const MethodDescriptor* method) { printer->Print(";\n\n\n"); } +void PrintV2MethodDeclarations(Printer* printer, + const MethodDescriptor* method) { + map< ::grpc::string, ::grpc::string> vars = GetMethodVars(method); + + PrintProtoRpcDeclarationAsPragma(printer, method, vars); + + PrintV2Signature(printer, method, vars); + printer->Print(";\n\n"); +} + void PrintSimpleImplementation(Printer* printer, const MethodDescriptor* method, map< ::grpc::string, ::grpc::string> vars) { printer->Print("{\n"); @@ -177,6 +210,25 @@ void PrintAdvancedImplementation(Printer* printer, printer->Print("}\n"); } +void PrintV2Implementation(Printer* printer, const MethodDescriptor* method, + map< ::grpc::string, ::grpc::string> vars) { + printer->Print(" {\n"); + if (method->client_streaming()) { + printer->Print(vars, " return [self RPCToMethod:@\"$method_name$\"\n"); + printer->Print(" responseHandler:handler\n"); + printer->Print(" callOptions:callOptions\n"); + printer->Print( + vars, " responseClass:[$response_class$ class]];\n}\n\n"); + } else { + printer->Print(vars, " return [self RPCToMethod:@\"$method_name$\"\n"); + printer->Print(" message:message\n"); + printer->Print(" responseHandler:handler\n"); + printer->Print(" callOptions:callOptions\n"); + printer->Print( + vars, " responseClass:[$response_class$ class]];\n}\n\n"); + } +} + void PrintMethodImplementations(Printer* printer, const MethodDescriptor* method) { map< ::grpc::string, ::grpc::string> vars = GetMethodVars(method); @@ -184,12 +236,16 @@ void PrintMethodImplementations(Printer* printer, PrintProtoRpcDeclarationAsPragma(printer, method, vars); // TODO(jcanizales): Print documentation from the method. + printer->Print("// Deprecated methods.\n"); PrintSimpleSignature(printer, method, vars); PrintSimpleImplementation(printer, method, vars); printer->Print("// Returns a not-yet-started RPC object.\n"); PrintAdvancedSignature(printer, method, vars); PrintAdvancedImplementation(printer, method, vars); + + PrintV2Signature(printer, method, vars); + PrintV2Implementation(printer, method, vars); } } // namespace @@ -231,6 +287,25 @@ void PrintMethodImplementations(Printer* printer, return output; } +::grpc::string GetV2Protocol(const ServiceDescriptor* service) { + ::grpc::string output; + + // Scope the output stream so it closes and finalizes output to the string. + grpc::protobuf::io::StringOutputStream output_stream(&output); + Printer printer(&output_stream, '$'); + + map< ::grpc::string, ::grpc::string> vars = { + {"service_class", ServiceClassName(service) + "2"}}; + + printer.Print(vars, "@protocol $service_class$ \n\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintV2MethodDeclarations(&printer, service->method(i)); + } + printer.Print("@end\n\n"); + + return output; +} + ::grpc::string GetInterface(const ServiceDescriptor* service) { ::grpc::string output; @@ -248,10 +323,16 @@ void PrintMethodImplementations(Printer* printer, " */\n"); printer.Print(vars, "@interface $service_class$ :" - " GRPCProtoService<$service_class$>\n"); + " GRPCProtoService<$service_class$, $service_class$2>\n"); printer.Print( - "- (instancetype)initWithHost:(NSString *)host" + "- (instancetype)initWithHost:(NSString *)host " + "callOptions:(GRPCCallOptions " + "*_Nullable)callOptions" " NS_DESIGNATED_INITIALIZER;\n"); + printer.Print("- (instancetype)initWithHost:(NSString *)host;\n"); + printer.Print( + "+ (instancetype)serviceWithHost:(NSString *)host " + "callOptions:(GRPCCallOptions *_Nullable)callOptions;\n"); printer.Print("+ (instancetype)serviceWithHost:(NSString *)host;\n"); printer.Print("@end\n"); @@ -273,11 +354,19 @@ void PrintMethodImplementations(Printer* printer, printer.Print(vars, "@implementation $service_class$\n\n" "// Designated initializer\n" - "- (instancetype)initWithHost:(NSString *)host {\n" + "- (instancetype)initWithHost:(NSString *)host " + "callOptions:(GRPCCallOptions *_Nullable)callOptions{\n" " self = [super initWithHost:host\n" " packageName:@\"$package$\"\n" - " serviceName:@\"$service_name$\"];\n" + " serviceName:@\"$service_name$\"\n" + " callOptions:callOptions];\n" " return self;\n" + "}\n\n" + "- (instancetype)initWithHost:(NSString *)host {\n" + " return [self initWithHost:host\n" + " packageName:@\"$package$\"\n" + " serviceName:@\"$service_name$\"\n" + " callOptions:nil];\n" "}\n\n"); printer.Print( @@ -292,7 +381,11 @@ void PrintMethodImplementations(Printer* printer, printer.Print( "#pragma mark - Class Methods\n\n" "+ (instancetype)serviceWithHost:(NSString *)host {\n" - " return [[self alloc] initWithHost:host];\n" + " return [self serviceWithHost:host callOptions:nil];\n" + "}\n\n" + "+ (instancetype)serviceWithHost:(NSString *)host " + "callOptions:(GRPCCallOptions *_Nullable)callOptions {\n" + " return [[self alloc] initWithHost:host callOptions:callOptions];\n" "}\n\n"); printer.Print("#pragma mark - Method Implementations\n\n"); diff --git a/src/compiler/objective_c_generator.h b/src/compiler/objective_c_generator.h index eb1c7ff005a..c171e5bf772 100644 --- a/src/compiler/objective_c_generator.h +++ b/src/compiler/objective_c_generator.h @@ -32,9 +32,14 @@ using ::grpc::string; string GetAllMessageClasses(const FileDescriptor* file); // Returns the content to be included defining the @protocol segment at the -// insertion point of the generated implementation file. +// insertion point of the generated implementation file. This interface is +// legacy and for backwards compatibility. string GetProtocol(const ServiceDescriptor* service); +// Returns the content to be included defining the @protocol segment at the +// insertion point of the generated implementation file. +string GetV2Protocol(const ServiceDescriptor* service); + // Returns the content to be included defining the @interface segment at the // insertion point of the generated implementation file. string GetInterface(const ServiceDescriptor* service); diff --git a/src/compiler/objective_c_plugin.cc b/src/compiler/objective_c_plugin.cc index f0fe3688cca..d0ef9ed0d62 100644 --- a/src/compiler/objective_c_plugin.cc +++ b/src/compiler/objective_c_plugin.cc @@ -93,7 +93,13 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { SystemImport("RxLibrary/GRXWriteable.h") + SystemImport("RxLibrary/GRXWriter.h"); - ::grpc::string forward_declarations = "@class GRPCProtoCall;\n\n"; + ::grpc::string forward_declarations = + "@class GRPCProtoCall;\n" + "@class GRPCUnaryProtoCall;\n" + "@class GRPCStreamingProtoCall;\n" + "@class GRPCCallOptions;\n" + "@protocol GRPCResponseHandler;\n" + "\n"; ::grpc::string class_declarations = grpc_objective_c_generator::GetAllMessageClasses(file); @@ -103,6 +109,12 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { class_imports += ImportProtoHeaders(file->dependency(i), " "); } + ::grpc::string ng_protocols; + for (int i = 0; i < file->service_count(); i++) { + const grpc::protobuf::ServiceDescriptor* service = file->service(i); + ng_protocols += grpc_objective_c_generator::GetV2Protocol(service); + } + ::grpc::string protocols; for (int i = 0; i < file->service_count(); i++) { const grpc::protobuf::ServiceDescriptor* service = file->service(i); @@ -120,9 +132,10 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { PreprocIfNot(kProtocolOnly, system_imports) + "\n" + class_declarations + "\n" + PreprocIfNot(kForwardDeclare, class_imports) + "\n" + - forward_declarations + "\n" + kNonNullBegin + "\n" + protocols + - "\n" + PreprocIfNot(kProtocolOnly, interfaces) + "\n" + - kNonNullEnd + "\n"); + forward_declarations + "\n" + kNonNullBegin + "\n" + + ng_protocols + protocols + "\n" + + PreprocIfNot(kProtocolOnly, interfaces) + "\n" + kNonNullEnd + + "\n"); } { diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 45d35260921..1a27cac2a32 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -21,6 +21,55 @@ #import "ProtoMethod.h" +@class GPBMessage; + +/** A unary-request RPC call with Protobuf. */ +@interface GRPCUnaryProtoCall : NSObject + +/** + * Users should not use this initializer directly. Call objects will be created, initialized, and + * returned to users by methods of the generated service. + */ +- (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions + message:(GPBMessage *)message + responseHandler:(id)handler + callOptions:(GRPCCallOptions *)callOptions + responseClass:(Class)responseClass; + +/** Cancel the call at best effort. */ +- (void)cancel; + +@end + +/** A client-streaming RPC call with Protobuf. */ +@interface GRPCStreamingProtoCall : NSObject + +/** + * Users should not use this initializer directly. Call objects will be created, initialized, and + * returned to users by methods of the generated service. + */ +- (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions + responseHandler:(id)handler + callOptions:(GRPCCallOptions *)callOptions + responseClass:(Class)responseClass; + +/** Cancel the call at best effort. */ +- (void)cancel; + +/** + * Send a message to the server. The message should be a Protobuf message which will be serialized + * internally. + */ +- (void)writeWithMessage:(GPBMessage *)message; + +/** + * Finish the RPC request and half-close the call. The server may still send messages and/or + * trailers to the client. + */ +- (void)finish; + +@end + __attribute__((deprecated("Please use GRPCProtoCall."))) @interface ProtoRPC : GRPCCall diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 5dca971b08a..f89c1606507 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -23,9 +23,166 @@ #else #import #endif +#import #import #import +@implementation GRPCUnaryProtoCall { + GRPCStreamingProtoCall *_call; +} + +- (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions + message:(GPBMessage *)message + responseHandler:(id)handler + callOptions:(GRPCCallOptions *)callOptions + responseClass:(Class)responseClass { + if ((self = [super init])) { + _call = [[GRPCStreamingProtoCall alloc] initWithRequestOptions:requestOptions + responseHandler:handler + callOptions:callOptions + responseClass:responseClass]; + [_call writeWithMessage:message]; + [_call finish]; + } + return self; +} + +- (void)cancel { + [_call cancel]; + _call = nil; +} + +@end + +@interface GRPCStreamingProtoCall () + +@end + +@implementation GRPCStreamingProtoCall { + GRPCRequestOptions *_requestOptions; + id _handler; + GRPCCallOptions *_callOptions; + Class _responseClass; + + GRPCCall2 *_call; + dispatch_queue_t _dispatchQueue; +} + +- (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions + responseHandler:(id)handler + callOptions:(GRPCCallOptions *)callOptions + responseClass:(Class)responseClass { + if ((self = [super init])) { + _requestOptions = [requestOptions copy]; + _handler = handler; + _callOptions = [callOptions copy]; + _responseClass = responseClass; + _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); + + [self start]; + } + return self; +} + +- (void)start { + _call = [[GRPCCall2 alloc] initWithRequestOptions:_requestOptions + handler:self + callOptions:_callOptions]; + [_call start]; +} + +- (void)cancel { + dispatch_async(_dispatchQueue, ^{ + if (_call) { + [_call cancel]; + _call = nil; + } + if (_handler) { + id handler = _handler; + dispatch_async(handler.dispatchQueue, ^{ + [handler closedWithTrailingMetadata:nil + error:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeCancelled + userInfo:@{ + NSLocalizedDescriptionKey : + @"Canceled by app" + }]]; + }); + _handler = nil; + } + }); +} + +- (void)writeWithMessage:(GPBMessage *)message { + if (![message isKindOfClass:[GPBMessage class]]) { + [NSException raise:NSInvalidArgumentException format:@"Data must be a valid protobuf type."]; + } + + dispatch_async(_dispatchQueue, ^{ + if (_call) { + [_call writeWithData:[message data]]; + } + }); +} + +- (void)finish { + dispatch_async(_dispatchQueue, ^{ + if (_call) { + [_call finish]; + _call = nil; + } + }); +} + +- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { + if (_handler) { + id handler = _handler; + dispatch_async(handler.dispatchQueue, ^{ + [handler receivedInitialMetadata:initialMetadata]; + }); + } +} + +- (void)receivedMessage:(NSData *)message { + if (_handler) { + id handler = _handler; + NSError *error = nil; + id parsed = [_responseClass parseFromData:message error:&error]; + if (parsed) { + dispatch_async(handler.dispatchQueue, ^{ + [handler receivedMessage:parsed]; + }); + } else { + dispatch_async(handler.dispatchQueue, ^{ + [handler closedWithTrailingMetadata:nil error:error]; + }); + handler = nil; + [_call cancel]; + _call = nil; + } + } +} + +- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { + if (_handler) { + id handler = _handler; + dispatch_async(handler.dispatchQueue, ^{ + [handler closedWithTrailingMetadata:trailingMetadata error:error]; + }); + _handler = nil; + } + if (_call) { + [_call cancel]; + _call = nil; + } +} + +- (dispatch_queue_t)dispatchQueue { + return _dispatchQueue; +} + +@end + static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsingError) { NSDictionary *info = @{ NSLocalizedDescriptionKey : @"Unable to parse response from the server", diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h index 29c4e9be360..2105de78a38 100644 --- a/src/objective-c/ProtoRPC/ProtoService.h +++ b/src/objective-c/ProtoRPC/ProtoService.h @@ -21,16 +21,40 @@ @class GRPCProtoCall; @protocol GRXWriteable; @class GRXWriter; +@class GRPCCallOptions; +@class GRPCProtoCall; +@class GRPCUnaryProtoCall; +@class GRPCStreamingProtoCall; +@protocol GRPCProtoResponseCallbacks; __attribute__((deprecated("Please use GRPCProtoService."))) @interface ProtoService - : NSObject - + : NSObject + + - (instancetype)initWithHost : (NSString *)host packageName - : (NSString *)packageName serviceName : (NSString *)serviceName NS_DESIGNATED_INITIALIZER; + : (NSString *)packageName serviceName : (NSString *)serviceName callOptions + : (GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithHost:(NSString *)host + packageName:(NSString *)packageName + serviceName:(NSString *)serviceName; - (GRPCProtoCall *)RPCToMethod:(NSString *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass responsesWriteable:(id)responsesWriteable; + +- (GRPCUnaryProtoCall *)RPCToMethod:(NSString *)method + message:(id)message + responseHandler:(id)handler + callOptions:(GRPCCallOptions *)callOptions + responseClass:(Class)responseClass; + +- (GRPCStreamingProtoCall *)RPCToMethod:(NSString *)method + responseHandler:(id)handler + callOptions:(GRPCCallOptions *)callOptions + responseClass:(Class)responseClass; + @end /** diff --git a/src/objective-c/ProtoRPC/ProtoService.m b/src/objective-c/ProtoRPC/ProtoService.m index 3e9cc5c0b2d..6df502fb0c0 100644 --- a/src/objective-c/ProtoRPC/ProtoService.m +++ b/src/objective-c/ProtoRPC/ProtoService.m @@ -18,6 +18,7 @@ #import "ProtoService.h" +#import #import #import @@ -31,6 +32,7 @@ NSString *_host; NSString *_packageName; NSString *_serviceName; + GRPCCallOptions *_callOptions; } - (instancetype)init { @@ -40,7 +42,8 @@ // Designated initializer - (instancetype)initWithHost:(NSString *)host packageName:(NSString *)packageName - serviceName:(NSString *)serviceName { + serviceName:(NSString *)serviceName + callOptions:(GRPCCallOptions *)callOptions { if (!host || !serviceName) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor serviceName can be nil."]; @@ -49,10 +52,17 @@ _host = [host copy]; _packageName = [packageName copy]; _serviceName = [serviceName copy]; + _callOptions = [callOptions copy]; } return self; } +- (instancetype)initWithHost:(NSString *)host + packageName:(NSString *)packageName + serviceName:(NSString *)serviceName { + return [self initWithHost:host packageName:packageName serviceName:serviceName callOptions:nil]; +} + - (GRPCProtoCall *)RPCToMethod:(NSString *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass @@ -65,6 +75,41 @@ responseClass:responseClass responsesWriteable:responsesWriteable]; } + +- (GRPCUnaryProtoCall *)RPCToMethod:(NSString *)method + message:(id)message + responseHandler:(id)handler + callOptions:(GRPCCallOptions *)callOptions + responseClass:(Class)responseClass { + GRPCProtoMethod *methodName = + [[GRPCProtoMethod alloc] initWithPackage:_packageName service:_serviceName method:method]; + GRPCRequestOptions *requestOptions = + [[GRPCRequestOptions alloc] initWithHost:_host + path:methodName.HTTPPath + safety:GRPCCallSafetyDefault]; + return [[GRPCUnaryProtoCall alloc] initWithRequestOptions:requestOptions + message:message + responseHandler:handler + callOptions:callOptions ?: _callOptions + responseClass:responseClass]; +} + +- (GRPCStreamingProtoCall *)RPCToMethod:(NSString *)method + responseHandler:(id)handler + callOptions:(GRPCCallOptions *)callOptions + responseClass:(Class)responseClass { + GRPCProtoMethod *methodName = + [[GRPCProtoMethod alloc] initWithPackage:_packageName service:_serviceName method:method]; + GRPCRequestOptions *requestOptions = + [[GRPCRequestOptions alloc] initWithHost:_host + path:methodName.HTTPPath + safety:GRPCCallSafetyDefault]; + return [[GRPCStreamingProtoCall alloc] initWithRequestOptions:requestOptions + responseHandler:handler + callOptions:callOptions ?: _callOptions + responseClass:responseClass]; +} + @end @implementation GRPCProtoService From e2e5c8189310841f7edd5ae8a51a616c9d93b309 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 8 Oct 2018 15:50:55 -0700 Subject: [PATCH 003/375] New API for GRPCCall --- include/grpc/impl/codegen/grpc_types.h | 4 + src/objective-c/GRPCClient/GRPCCall.h | 145 +++++-- src/objective-c/GRPCClient/GRPCCall.m | 253 ++++++++++- src/objective-c/GRPCClient/GRPCCallOptions.h | 317 ++++++++++++++ src/objective-c/GRPCClient/GRPCCallOptions.m | 431 +++++++++++++++++++ 5 files changed, 1105 insertions(+), 45 deletions(-) create mode 100644 src/objective-c/GRPCClient/GRPCCallOptions.h create mode 100644 src/objective-c/GRPCClient/GRPCCallOptions.m diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index 3ce88a82645..4cf13edca93 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -347,6 +347,10 @@ typedef struct { /** If set to non zero, surfaces the user agent string to the server. User agent is surfaced by default. */ #define GRPC_ARG_SURFACE_USER_AGENT "grpc.surface_user_agent" +/** gRPC Objective-C channel pooling domain string. */ +#define GRPC_ARG_CHANNEL_POOL_DOMAIN "grpc.channel_pooling_domain" +/** gRPC Objective-C channel pooling id. */ +#define GRPC_ARG_CHANNEL_ID "grpc.channel_id" /** \} */ /** Result of a grpc call. If the caller satisfies the prerequisites of a diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index e0ef8b1391f..3f6ec75c04e 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -37,6 +37,10 @@ #include +#include "GRPCCallOptions.h" + +@class GRPCCallOptions; + #pragma mark gRPC errors /** Domain of NSError objects produced by gRPC. */ @@ -139,19 +143,6 @@ typedef NS_ENUM(NSUInteger, GRPCErrorCode) { GRPCErrorCodeDataLoss = 15, }; -/** - * 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. */ - 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. */ - GRPCCallSafetyCacheableRequest = 2, -}; - /** * Keys used in |NSError|'s |userInfo| dictionary to store the response headers and trailers sent by * the server. @@ -159,23 +150,117 @@ typedef NS_ENUM(NSUInteger, GRPCCallSafety) { extern id const kGRPCHeadersKey; extern id const kGRPCTrailersKey; +/** An object can implement this protocol to receive responses from server from a call. */ +@protocol GRPCResponseHandler +@optional +/** Issued when initial metadata is received from the server. */ +- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata; +/** + * Issued when a message is received from the server. The message may be raw data from the server + * (when using \a GRPCCall2 directly) or deserialized proto object (when using \a ProtoRPC). + */ +- (void)receivedMessage:(id)message; +/** + * Issued when a call finished. If the call finished successfully, \a error is nil and \a + * trainingMetadata consists any trailing metadata received from the server. Otherwise, \a error + * is non-nil and contains the corresponding error information, including gRPC error codes and + * error descriptions. + */ +- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error; + +/** + * All the responses must be issued to a user-provided dispatch queue. This property specifies the + * dispatch queue to be used for issuing the notifications. + */ +@property(atomic, readonly) dispatch_queue_t dispatchQueue; + +@end + +/** + * Call related parameters. These parameters are automatically specified by Protobuf. If directly + * using the \a GRPCCall2 class, users should specify these parameters manually. + */ +@interface GRPCRequestOptions : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** Initialize with all properties. */ +- (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety; + +/** The host serving the RPC service. */ +@property(copy, readonly) NSString *host; +/** The path to the RPC call. */ +@property(copy, readonly) NSString *path; +/** + * Specify whether the call is idempotent or cachable. gRPC may select different HTTP verbs for the + * call based on this information. + */ +@property(readonly) GRPCCallSafety safety; + +@end + #pragma mark GRPCCall -/** Represents a single gRPC remote call. */ -@interface GRPCCall : GRXWriter +/** + * A \a GRPCCall2 object represents an RPC call. + */ +@interface GRPCCall2 : NSObject + +- (instancetype)init NS_UNAVAILABLE; /** - * The authority for the RPC. If nil, the default authority will be used. This property must be nil - * when Cronet transport is enabled. + * Designated initializer for a call. + * \param requestOptions Protobuf generated parameters for the call. + * \param handler The object to which responses should be issed. + * \param callOptions Options for the call. */ -@property(atomic, copy, readwrite) NSString *serverName; +- (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions + handler:(id)handler + callOptions:(GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; +/** + * Convevience initializer for a call that uses default call options. + */ +- (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions + handler:(id)handler; /** - * The timeout for the RPC call in seconds. If set to 0, the call will not timeout. If set to - * positive, the gRPC call returns with status GRPCErrorCodeDeadlineExceeded if it is not completed - * within \a timeout seconds. A negative value is not allowed. + * Starts the call. Can only be called once. */ -@property NSTimeInterval timeout; +- (void)start; + +/** + * Cancel the request of this call at best effort; notifies the server that the RPC should be + * cancelled, and issue callback to the user with an error code CANCELED if the call is not + * finished. + */ +- (void)cancel; + +/** + * Send a message to the server. Data are sent as raw bytes in gRPC message frames. + */ +- (void)writeWithData:(NSData *)data; + +/** + * Finish the RPC request and half-close the call. The server may still send messages and/or + * trailers to the client. + */ -(void)finish; + +/** + * Get a copy of the original call options. + */ +@property(readonly, copy) GRPCCallOptions *callOptions; + +/** Get a copy of the original request options. */ +@property(readonly, copy) GRPCRequestOptions *requestOptions; + +@end + +/** + * This interface is deprecated. Please use \a GRPCcall2. + * + * Represents a single gRPC remote call. + */ +@interface GRPCCall : GRXWriter /** * The container of the request headers of an RPC conforms to this protocol, which is a subset of @@ -236,7 +321,7 @@ extern id const kGRPCTrailersKey; */ - (instancetype)initWithHost:(NSString *)host path:(NSString *)path - requestsWriter:(GRXWriter *)requestsWriter NS_DESIGNATED_INITIALIZER; + requestsWriter:(GRXWriter *)requestWriter; /** * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and @@ -245,21 +330,13 @@ extern id const kGRPCTrailersKey; - (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". + * The following methods are deprecated. */ + (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString *)host path:(NSString *)path; - -/** - * Set the dispatch queue to be used for callbacks. - * - * This configuration is only effective before the call starts. - */ +@property(atomic, copy, readwrite) NSString *serverName; +@property NSTimeInterval timeout; - (void)setResponseDispatchQueue:(dispatch_queue_t)queue; -// TODO(jcanizales): Let specify a deadline. As a category of GRXWriter? @end #pragma mark Backwards compatibiity diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 084fbdeb491..519f91e5229 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -20,13 +20,16 @@ #import "GRPCCall+OAuth2.h" +#import #import #import +#import #include #include -#import "private/GRPCConnectivityMonitor.h" +#import "GRPCCallOptions.h" #import "private/GRPCHost.h" +#import "private/GRPCConnectivityMonitor.h" #import "private/GRPCRequestHeaders.h" #import "private/GRPCWrappedCall.h" #import "private/NSData+GRPC.h" @@ -52,6 +55,165 @@ const char *kCFStreamVarName = "grpc_cfstream"; @property(atomic, strong) NSDictionary *responseHeaders; @property(atomic, strong) NSDictionary *responseTrailers; @property(atomic) BOOL isWaitingForToken; + +- (instancetype)initWithHost:(NSString *)host + path:(NSString *)path + callSafety:(GRPCCallSafety)safety + requestsWriter:(GRXWriter *)requestsWriter + callOptions:(GRPCCallOptions *)callOptions; + +@end + +@implementation GRPCRequestOptions + +- (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety { + if ((self = [super init])) { + _host = host; + _path = path; + _safety = safety; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + GRPCRequestOptions *request = + [[GRPCRequestOptions alloc] initWithHost:[_host copy] path:[_path copy] safety:_safety]; + + return request; +} + +@end + +@implementation GRPCCall2 { + GRPCCallOptions *_callOptions; + id _handler; + + GRPCCall *_call; + BOOL _initialMetadataPublished; + GRXBufferedPipe *_pipe; + dispatch_queue_t _dispatchQueue; +} + +- (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions + handler:(id)handler + callOptions:(GRPCCallOptions *)callOptions { + if (!requestOptions || !requestOptions.host || !requestOptions.path) { + [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; + } + + if ((self = [super init])) { + _requestOptions = [requestOptions copy]; + _callOptions = [callOptions copy]; + _handler = handler; + _initialMetadataPublished = NO; + _pipe = [GRXBufferedPipe pipe]; + _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + } + + return self; +} + +- (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions + handler:(id)handler { + return [self initWithRequestOptions:requestOptions handler:handler callOptions:nil]; +} + +- (void)start { + dispatch_async(_dispatchQueue, ^{ + if (!self->_callOptions) { + self->_callOptions = [[GRPCCallOptions alloc] init]; + } + + self->_call = [[GRPCCall alloc] initWithHost:self->_requestOptions.host + path:self->_requestOptions.path + callSafety:self->_requestOptions.safety + requestsWriter:self->_pipe + callOptions:self->_callOptions]; + if (self->_callOptions.initialMetadata) { + [self->_call.requestHeaders addEntriesFromDictionary:self->_callOptions.initialMetadata]; + } + id responseWriteable = [[GRXWriteable alloc] initWithValueHandler:^(id value) { + dispatch_async(self->_dispatchQueue, ^{ + if (self->_handler) { + id handler = self->_handler; + NSDictionary *headers = nil; + if (!self->_initialMetadataPublished) { + headers = self->_call.responseHeaders; + self->_initialMetadataPublished = YES; + } + if (headers) { + dispatch_async(handler.dispatchQueue, ^{ + [handler receivedInitialMetadata:headers]; + }); + } + if (value) { + dispatch_async(handler.dispatchQueue, ^{ + [handler receivedMessage:value]; + }); + } + } + }); + } + completionHandler:^(NSError *errorOrNil) { + dispatch_async(self->_dispatchQueue, ^{ + if (self->_handler) { + id handler = self->_handler; + NSDictionary *headers = nil; + if (!self->_initialMetadataPublished) { + headers = self->_call.responseHeaders; + self->_initialMetadataPublished = YES; + } + if (headers) { + dispatch_async(handler.dispatchQueue, ^{ + [handler receivedInitialMetadata:headers]; + }); + } + dispatch_async(handler.dispatchQueue, ^{ + [handler closedWithTrailingMetadata:self->_call.responseTrailers error:errorOrNil]; + }); + } + }); + }]; + [self->_call startWithWriteable:responseWriteable]; + }); +} + +- (void)cancel { + dispatch_async(_dispatchQueue, ^{ + if (self->_call) { + [self->_call cancel]; + self->_call = nil; + } + if (self->_handler) { + id handler = self->_handler; + dispatch_async(handler.dispatchQueue, ^{ + [handler closedWithTrailingMetadata:nil + error:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeCancelled + userInfo:@{ + NSLocalizedDescriptionKey : + @"Canceled by app" + }]]; + }); + self->_handler = nil; + } + }); +} + +- (void)writeWithData:(NSData *)data { + dispatch_async(_dispatchQueue, ^{ + [self->_pipe writeValue:data]; + }); +} + +- (void)finish { + dispatch_async(_dispatchQueue, ^{ + if (self->_call) { + [self->_pipe writesFinishedWithError:nil]; + } + }); +} + @end // The following methods of a C gRPC call object aren't reentrant, and thus @@ -75,6 +237,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; NSString *_host; NSString *_path; + GRPCCallSafety _callSafety; + GRPCCallOptions *_callOptions; GRPCWrappedCall *_wrappedCall; GRPCConnectivityMonitor *_connectivityMonitor; @@ -113,6 +277,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Whether the call is finished. If it is, should not call finishWithError again. BOOL _finished; + + // The OAuth2 token fetched from a token provider. + NSString *_fetchedOauth2AccessToken; } @synthesize state = _state; @@ -156,6 +323,18 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (instancetype)initWithHost:(NSString *)host path:(NSString *)path requestsWriter:(GRXWriter *)requestWriter { + return [self initWithHost:host + path:path + callSafety:GRPCCallSafetyDefault + requestsWriter:requestWriter + callOptions:nil]; +} + +- (instancetype)initWithHost:(NSString *)host + path:(NSString *)path + callSafety:(GRPCCallSafety)safety + requestsWriter:(GRXWriter *)requestWriter + callOptions:(GRPCCallOptions *)callOptions { if (!host || !path) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; } @@ -166,6 +345,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; if ((self = [super init])) { _host = [host copy]; _path = [path copy]; + _callSafety = safety; + _callOptions = [callOptions copy]; // Serial queue to invoke the non-reentrant methods of the grpc_call object. _callQueue = dispatch_queue_create("io.grpc.call", NULL); @@ -317,11 +498,36 @@ const char *kCFStreamVarName = "grpc_cfstream"; #pragma mark Send headers -- (void)sendHeaders:(NSDictionary *)headers { +- (void)sendHeaders { + // TODO (mxyan): Remove after deprecated methods are removed + uint32_t callSafetyFlags; + switch (_callSafety) { + case GRPCCallSafetyDefault: + callSafetyFlags = 0; + break; + case GRPCCallSafetyIdempotentRequest: + callSafetyFlags = GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; + break; + case GRPCCallSafetyCacheableRequest: + callSafetyFlags = GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; + break; + default: + [NSException raise:NSInvalidArgumentException format:@"Invalid call safety value."]; + } + uint32_t callFlag = callSafetyFlags; + + NSMutableDictionary *headers = _requestHeaders; + if (_fetchedOauth2AccessToken != nil) { + headers[@"authorization"] = [kBearerPrefix stringByAppendingString:_fetchedOauth2AccessToken]; + } else if (_callOptions.oauth2AccessToken != nil) { + headers[@"authorization"] = + [kBearerPrefix stringByAppendingString:_callOptions.oauth2AccessToken]; + } + // TODO(jcanizales): Add error handlers for async failures GRPCOpSendMetadata *op = [[GRPCOpSendMetadata alloc] initWithMetadata:headers - flags:[GRPCCall callFlagsForHost:_host path:_path] + flags:callFlag handler:nil]; // No clean-up needed after SEND_INITIAL_METADATA if (!_unaryCall) { [_wrappedCall startBatchWithOperations:@[ op ]]; @@ -458,13 +664,10 @@ const char *kCFStreamVarName = "grpc_cfstream"; _responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable dispatchQueue:_responseQueue]; - _wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host - serverName:_serverName - path:_path - timeout:_timeout]; + _wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host path:_path callOptions:_callOptions]; NSAssert(_wrappedCall, @"Error allocating RPC objects. Low memory?"); - [self sendHeaders:_requestHeaders]; + [self sendHeaders]; [self invokeCall]; // Connectivity monitor is not required for CFStream @@ -486,15 +689,43 @@ const char *kCFStreamVarName = "grpc_cfstream"; // that the life of the instance is determined by this retain cycle. _retainSelf = self; - if (self.tokenProvider != nil) { + if (_callOptions == nil) { + GRPCMutableCallOptions *callOptions; + if ([GRPCHost isHostConfigured:_host]) { + GRPCHost *hostConfig = [GRPCHost hostWithAddress:_host]; + callOptions = hostConfig.callOptions; + } else { + callOptions = [[GRPCMutableCallOptions alloc] init]; + } + if (_serverName != nil) { + callOptions.serverAuthority = _serverName; + } + if (_timeout != 0) { + callOptions.timeout = _timeout; + } + uint32_t callFlags = [GRPCCall callFlagsForHost:_host path:_path]; + if (callFlags != 0) { + if (callFlags == GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) { + _callSafety = GRPCCallSafetyIdempotentRequest; + } else if (callFlags == GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) { + _callSafety = GRPCCallSafetyCacheableRequest; + } + } + + id tokenProvider = self.tokenProvider; + if (tokenProvider != nil) { + callOptions.authTokenProvider = tokenProvider; + } + _callOptions = callOptions; + } + if (_callOptions.authTokenProvider != nil) { self.isWaitingForToken = YES; __weak typeof(self) weakSelf = self; [self.tokenProvider getTokenWithHandler:^(NSString *token) { typeof(self) strongSelf = weakSelf; if (strongSelf && strongSelf.isWaitingForToken) { if (token) { - NSString *t = [kBearerPrefix stringByAppendingString:token]; - strongSelf.requestHeaders[kAuthorizationHeader] = t; + strongSelf->_fetchedOauth2AccessToken = token; } [strongSelf startCallWithWriteable:writeable]; strongSelf.isWaitingForToken = NO; diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h new file mode 100644 index 00000000000..75b320ca6d6 --- /dev/null +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -0,0 +1,317 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import + +/** + * 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. */ + 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. */ + GRPCCallSafetyCacheableRequest = 2, +}; + +// Compression algorithm to be used by a gRPC call +typedef NS_ENUM(NSInteger, GRPCCompressAlgorithm) { + GRPCCompressNone = 0, + GRPCCompressDeflate, + GRPCCompressGzip, + GRPCStreamCompressGzip, +}; + +// The transport to be used by a gRPC call +typedef NS_ENUM(NSInteger, GRPCTransportType) { + // gRPC internal HTTP/2 stack with BoringSSL + GRPCTransportTypeDefault = 0, + // Cronet stack + GRPCTransportTypeCronet, + // Insecure channel. FOR TEST ONLY! + GRPCTransportTypeInsecure, +}; + +@protocol GRPCAuthorizationProtocol +- (void)getTokenWithHandler:(void (^)(NSString *token))hander; +@end + +@interface GRPCCallOptions : NSObject + +// Call parameters +/** + * The authority for the RPC. If nil, the default authority will be used. + * + * Note: This property must be nil when Cronet transport is enabled. + * Note: This property cannot be used to validate a self-signed server certificate. It control the + * :authority header field of the call and performs an extra check that server's certificate + * matches the :authority header. + */ +@property(readonly) NSString *serverAuthority; + +/** + * The timeout for the RPC call in seconds. If set to 0, the call will not timeout. If set to + * positive, the gRPC call returns with status GRPCErrorCodeDeadlineExceeded if it is not completed + * within \a timeout seconds. A negative value is not allowed. + */ +@property(readonly) NSTimeInterval timeout; + +// OAuth2 parameters. Users of gRPC may specify one of the following two parameters. + +/** + * The OAuth2 access token string. The string is prefixed with "Bearer " then used as value of the + * request's "authorization" header field. This parameter should not be used simultaneously with + * \a authTokenProvider. + */ +@property(copy, readonly) NSString *oauth2AccessToken; + +/** + * The interface to get the OAuth2 access token string. gRPC will attempt to acquire token when + * initiating the call. This parameter should not be used simultaneously with \a oauth2AccessToken. + */ +@property(readonly) id authTokenProvider; + +/** + * Initial metadata key-value pairs that should be included in the request. + */ +@property(copy, readwrite) NSDictionary *initialMetadata; + +// Channel parameters; take into account of channel signature. + +/** + * Custom string that is prefixed to a request's user-agent header field before gRPC's internal + * user-agent string. + */ +@property(copy, readonly) NSString *userAgentPrefix; + +/** + * The size limit for the response received from server. If it is exceeded, an error with status + * code GRPCErrorCodeResourceExhausted is returned. + */ +@property(readonly) NSUInteger responseSizeLimit; + +/** + * The compression algorithm to be used by the gRPC call. For more details refer to + * https://github.com/grpc/grpc/blob/master/doc/compression.md + */ +@property(readonly) GRPCCompressAlgorithm compressAlgorithm; + +/** + * Enable/Disable gRPC call's retry feature. The default is enabled. For details of this feature + * refer to + * https://github.com/grpc/proposal/blob/master/A6-client-retries.md + */ +@property(readonly) BOOL enableRetry; + +/** + * HTTP/2 keep-alive feature. The parameter \a keepaliveInterval specifies the interval between two + * PING frames. The parameter \a keepaliveTimeout specifies the length of the period for which the + * call should wait for PING ACK. If PING ACK is not received after this period, the call fails. + */ +@property(readonly) NSTimeInterval keepaliveInterval; +@property(readonly) NSTimeInterval keepaliveTimeout; + +// Parameters for connection backoff. For details of gRPC's backoff behavior, refer to +// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md +@property(readonly) NSTimeInterval connectMinTimeout; +@property(readonly) NSTimeInterval connectInitialBackoff; +@property(readonly) NSTimeInterval connectMaxBackoff; + +/** + * Specify channel args to be used for this call. For a list of channel args available, see + * grpc/grpc_types.h + */ +@property(copy, readonly) NSDictionary *additionalChannelArgs; + +// Parameters for SSL authentication. + +/** + * PEM format root certifications that is trusted. If set to nil, gRPC uses a list of default + * root certificates. + */ +@property(copy, readonly) NSString *pemRootCert; + +/** + * PEM format private key for client authentication, if required by the server. + */ +@property(copy, readonly) NSString *pemPrivateKey; + +/** + * PEM format certificate chain for client authentication, if required by the server. + */ +@property(copy, readonly) NSString *pemCertChain; + +/** + * Select the transport type to be used for this call. + */ +@property(readonly) GRPCTransportType transportType; + +/** + * Override the hostname during the TLS hostname validation process. + */ +@property(copy, readonly) NSString *hostNameOverride; + +/** + * Parameter used for internal logging. + */ +@property(readonly) id logContext; + +/** + * A string that specify the domain where channel is being cached. Channels with different domains + * will not get cached to the same connection. + */ +@property(copy, readonly) NSString *channelPoolDomain; + +/** + * Channel id allows a call to force creating a new channel (connection) rather than using a cached + * channel. Calls using distinct channelId will not get cached to the same connection. + */ +@property(readonly) NSUInteger channelId; + +@end + +@interface GRPCMutableCallOptions : GRPCCallOptions + +// Call parameters +/** + * The authority for the RPC. If nil, the default authority will be used. + * + * Note: This property must be nil when Cronet transport is enabled. + * Note: This property cannot be used to validate a self-signed server certificate. It control the + * :authority header field of the call and performs an extra check that server's certificate + * matches the :authority header. + */ +@property(readwrite) NSString *serverAuthority; + +/** + * The timeout for the RPC call in seconds. If set to 0, the call will not timeout. If set to + * positive, the gRPC call returns with status GRPCErrorCodeDeadlineExceeded if it is not completed + * within \a timeout seconds. A negative value is not allowed. + */ +@property(readwrite) NSTimeInterval timeout; + +// OAuth2 parameters. Users of gRPC may specify one of the following two parameters. + +/** + * The OAuth2 access token string. The string is prefixed with "Bearer " then used as value of the + * request's "authorization" header field. This parameter should not be used simultaneously with + * \a authTokenProvider. + */ +@property(copy, readwrite) NSString *oauth2AccessToken; + +/** + * The interface to get the OAuth2 access token string. gRPC will attempt to acquire token when + * initiating the call. This parameter should not be used simultaneously with \a oauth2AccessToken. + */ +@property(readwrite) id authTokenProvider; + +// Channel parameters; take into account of channel signature. + +/** + * Custom string that is prefixed to a request's user-agent header field before gRPC's internal + * user-agent string. + */ +@property(copy, readwrite) NSString *userAgentPrefix; + +/** + * The size limit for the response received from server. If it is exceeded, an error with status + * code GRPCErrorCodeResourceExhausted is returned. + */ +@property(readwrite) NSUInteger responseSizeLimit; + +/** + * The compression algorithm to be used by the gRPC call. For more details refer to + * https://github.com/grpc/grpc/blob/master/doc/compression.md + */ +@property(readwrite) GRPCCompressAlgorithm compressAlgorithm; + +/** + * Enable/Disable gRPC call's retry feature. The default is enabled. For details of this feature + * refer to + * https://github.com/grpc/proposal/blob/master/A6-client-retries.md + */ +@property(readwrite) BOOL enableRetry; + +/** + * HTTP/2 keep-alive feature. The parameter \a keepaliveInterval specifies the interval between two + * PING frames. The parameter \a keepaliveTimeout specifies the length of the period for which the + * call should wait for PING ACK. If PING ACK is not received after this period, the call fails. + */ +@property(readwrite) NSTimeInterval keepaliveInterval; +@property(readwrite) NSTimeInterval keepaliveTimeout; + +// Parameters for connection backoff. For details of gRPC's backoff behavior, refer to +// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md +@property(readwrite) NSTimeInterval connectMinTimeout; +@property(readwrite) NSTimeInterval connectInitialBackoff; +@property(readwrite) NSTimeInterval connectMaxBackoff; + +/** + * Specify channel args to be used for this call. For a list of channel args available, see + * grpc/grpc_types.h + */ +@property(copy, readwrite) NSDictionary *additionalChannelArgs; + +// Parameters for SSL authentication. + +/** + * PEM format root certifications that is trusted. If set to nil, gRPC uses a list of default + * root certificates. + */ +@property(copy, readwrite) NSString *pemRootCert; + +/** + * PEM format private key for client authentication, if required by the server. + */ +@property(copy, readwrite) NSString *pemPrivateKey; + +/** + * PEM format certificate chain for client authentication, if required by the server. + */ +@property(copy, readwrite) NSString *pemCertChain; + +/** + * Select the transport type to be used for this call. + */ +@property(readwrite) GRPCTransportType transportType; + +/** + * Override the hostname during the TLS hostname validation process. + */ +@property(copy, readwrite) NSString *hostNameOverride; + +/** + * Parameter used for internal logging. + */ +@property(copy, readwrite) id logContext; + +/** + * A string that specify the domain where channel is being cached. Channels with different domains + * will not get cached to the same connection. + */ +@property(copy, readwrite) NSString *channelPoolDomain; + +/** + * Channel id allows a call to force creating a new channel (connection) rather than using a cached + * channel. Calls using distinct channelId will not get cached to the same connection. + */ +@property(readwrite) NSUInteger channelId; + +@end diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m new file mode 100644 index 00000000000..ee76c2a6420 --- /dev/null +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -0,0 +1,431 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import "GRPCCallOptions.h" + +static NSString *const kDefaultServerAuthority = nil; +static const NSTimeInterval kDefaultTimeout = 0; +static NSDictionary *const kDefaultInitialMetadata = nil; +static NSString *const kDefaultUserAgentPrefix = nil; +static const NSUInteger kDefaultResponseSizeLimit = 0; +static const GRPCCompressAlgorithm kDefaultCompressAlgorithm = GRPCCompressNone; +static const BOOL kDefaultEnableRetry = YES; +static const NSTimeInterval kDefaultKeepaliveInterval = 0; +static const NSTimeInterval kDefaultKeepaliveTimeout = 0; +static const NSTimeInterval kDefaultConnectMinTimeout = 0; +static const NSTimeInterval kDefaultConnectInitialBackoff = 0; +static const NSTimeInterval kDefaultConnectMaxBackoff = 0; +static NSDictionary *const kDefaultAdditionalChannelArgs = nil; +static NSString *const kDefaultPemRootCert = nil; +static NSString *const kDefaultPemPrivateKey = nil; +static NSString *const kDefaultPemCertChain = nil; +static NSString *const kDefaultOauth2AccessToken = nil; +static const id kDefaultAuthTokenProvider = nil; +static const GRPCTransportType kDefaultTransportType = GRPCTransportTypeDefault; +static NSString *const kDefaultHostNameOverride = nil; +static const id kDefaultLogContext = nil; +static NSString *kDefaultChannelPoolDomain = nil; +static NSUInteger kDefaultChannelId = 0; + +@implementation GRPCCallOptions { + @protected + NSString *_serverAuthority; + NSTimeInterval _timeout; + NSString *_oauth2AccessToken; + id _authTokenProvider; + NSDictionary *_initialMetadata; + NSString *_userAgentPrefix; + NSUInteger _responseSizeLimit; + GRPCCompressAlgorithm _compressAlgorithm; + BOOL _enableRetry; + NSTimeInterval _keepaliveInterval; + NSTimeInterval _keepaliveTimeout; + NSTimeInterval _connectMinTimeout; + NSTimeInterval _connectInitialBackoff; + NSTimeInterval _connectMaxBackoff; + NSDictionary *_additionalChannelArgs; + NSString *_pemRootCert; + NSString *_pemPrivateKey; + NSString *_pemCertChain; + GRPCTransportType _transportType; + NSString *_hostNameOverride; + id _logContext; + NSString *_channelPoolDomain; + NSUInteger _channelId; +} + +@synthesize serverAuthority = _serverAuthority; +@synthesize timeout = _timeout; +@synthesize oauth2AccessToken = _oauth2AccessToken; +@synthesize authTokenProvider = _authTokenProvider; +@synthesize initialMetadata = _initialMetadata; +@synthesize userAgentPrefix = _userAgentPrefix; +@synthesize responseSizeLimit = _responseSizeLimit; +@synthesize compressAlgorithm = _compressAlgorithm; +@synthesize enableRetry = _enableRetry; +@synthesize keepaliveInterval = _keepaliveInterval; +@synthesize keepaliveTimeout = _keepaliveTimeout; +@synthesize connectMinTimeout = _connectMinTimeout; +@synthesize connectInitialBackoff = _connectInitialBackoff; +@synthesize connectMaxBackoff = _connectMaxBackoff; +@synthesize additionalChannelArgs = _additionalChannelArgs; +@synthesize pemRootCert = _pemRootCert; +@synthesize pemPrivateKey = _pemPrivateKey; +@synthesize pemCertChain = _pemCertChain; +@synthesize transportType = _transportType; +@synthesize hostNameOverride = _hostNameOverride; +@synthesize logContext = _logContext; +@synthesize channelPoolDomain = _channelPoolDomain; +@synthesize channelId = _channelId; + +- (instancetype)init { + return [self initWithServerAuthority:kDefaultServerAuthority + timeout:kDefaultTimeout + oauth2AccessToken:kDefaultOauth2AccessToken + authTokenProvider:kDefaultAuthTokenProvider + initialMetadata:kDefaultInitialMetadata + userAgentPrefix:kDefaultUserAgentPrefix + responseSizeLimit:kDefaultResponseSizeLimit + compressAlgorithm:kDefaultCompressAlgorithm + enableRetry:kDefaultEnableRetry + keepaliveInterval:kDefaultKeepaliveInterval + keepaliveTimeout:kDefaultKeepaliveTimeout + connectMinTimeout:kDefaultConnectMinTimeout + connectInitialBackoff:kDefaultConnectInitialBackoff + connectMaxBackoff:kDefaultConnectMaxBackoff + additionalChannelArgs:kDefaultAdditionalChannelArgs + pemRootCert:kDefaultPemRootCert + pemPrivateKey:kDefaultPemPrivateKey + pemCertChain:kDefaultPemCertChain + transportType:kDefaultTransportType + hostNameOverride:kDefaultHostNameOverride + logContext:kDefaultLogContext + channelPoolDomain:kDefaultChannelPoolDomain + channelId:kDefaultChannelId]; +} + +- (instancetype)initWithServerAuthority:(NSString *)serverAuthority + timeout:(NSTimeInterval)timeout + oauth2AccessToken:(NSString *)oauth2AccessToken + authTokenProvider:(id)authTokenProvider + initialMetadata:(NSDictionary *)initialMetadata + userAgentPrefix:(NSString *)userAgentPrefix + responseSizeLimit:(NSUInteger)responseSizeLimit + compressAlgorithm:(GRPCCompressAlgorithm)compressAlgorithm + enableRetry:(BOOL)enableRetry + keepaliveInterval:(NSTimeInterval)keepaliveInterval + keepaliveTimeout:(NSTimeInterval)keepaliveTimeout + connectMinTimeout:(NSTimeInterval)connectMinTimeout + connectInitialBackoff:(NSTimeInterval)connectInitialBackoff + connectMaxBackoff:(NSTimeInterval)connectMaxBackoff + additionalChannelArgs:(NSDictionary *)additionalChannelArgs + pemRootCert:(NSString *)pemRootCert + pemPrivateKey:(NSString *)pemPrivateKey + pemCertChain:(NSString *)pemCertChain + transportType:(GRPCTransportType)transportType + hostNameOverride:(NSString *)hostNameOverride + logContext:(id)logContext + channelPoolDomain:(NSString *)channelPoolDomain + channelId:(NSUInteger)channelId { + if ((self = [super init])) { + _serverAuthority = serverAuthority; + _timeout = timeout; + _oauth2AccessToken = oauth2AccessToken; + _authTokenProvider = authTokenProvider; + _initialMetadata = initialMetadata; + _userAgentPrefix = userAgentPrefix; + _responseSizeLimit = responseSizeLimit; + _compressAlgorithm = compressAlgorithm; + _enableRetry = enableRetry; + _keepaliveInterval = keepaliveInterval; + _keepaliveTimeout = keepaliveTimeout; + _connectMinTimeout = connectMinTimeout; + _connectInitialBackoff = connectInitialBackoff; + _connectMaxBackoff = connectMaxBackoff; + _additionalChannelArgs = additionalChannelArgs; + _pemRootCert = pemRootCert; + _pemPrivateKey = pemPrivateKey; + _pemCertChain = pemCertChain; + _transportType = transportType; + _hostNameOverride = hostNameOverride; + _logContext = logContext; + _channelPoolDomain = channelPoolDomain; + _channelId = channelId; + } + return self; +} + +- (nonnull id)copyWithZone:(NSZone *)zone { + GRPCCallOptions *newOptions = + [[GRPCCallOptions allocWithZone:zone] initWithServerAuthority:_serverAuthority + timeout:_timeout + oauth2AccessToken:_oauth2AccessToken + authTokenProvider:_authTokenProvider + initialMetadata:_initialMetadata + userAgentPrefix:_userAgentPrefix + responseSizeLimit:_responseSizeLimit + compressAlgorithm:_compressAlgorithm + enableRetry:_enableRetry + keepaliveInterval:_keepaliveInterval + keepaliveTimeout:_keepaliveTimeout + connectMinTimeout:_connectMinTimeout + connectInitialBackoff:_connectInitialBackoff + connectMaxBackoff:_connectMaxBackoff + additionalChannelArgs:[_additionalChannelArgs copy] + pemRootCert:_pemRootCert + pemPrivateKey:_pemPrivateKey + pemCertChain:_pemCertChain + transportType:_transportType + hostNameOverride:_hostNameOverride + logContext:_logContext + channelPoolDomain:_channelPoolDomain + channelId:_channelId]; + return newOptions; +} + +- (nonnull id)mutableCopyWithZone:(NSZone *)zone { + GRPCMutableCallOptions *newOptions = [[GRPCMutableCallOptions allocWithZone:zone] + initWithServerAuthority:_serverAuthority + timeout:_timeout + oauth2AccessToken:_oauth2AccessToken + authTokenProvider:_authTokenProvider + initialMetadata:_initialMetadata + userAgentPrefix:_userAgentPrefix + responseSizeLimit:_responseSizeLimit + compressAlgorithm:_compressAlgorithm + enableRetry:_enableRetry + keepaliveInterval:_keepaliveInterval + keepaliveTimeout:_keepaliveTimeout + connectMinTimeout:_connectMinTimeout + connectInitialBackoff:_connectInitialBackoff + connectMaxBackoff:_connectMaxBackoff + additionalChannelArgs:[_additionalChannelArgs copy] + pemRootCert:_pemRootCert + pemPrivateKey:_pemPrivateKey + pemCertChain:_pemCertChain + transportType:_transportType + hostNameOverride:_hostNameOverride + logContext:_logContext + channelPoolDomain:_channelPoolDomain + channelId:_channelId]; + return newOptions; +} + +@end + +@implementation GRPCMutableCallOptions + +@dynamic serverAuthority; +@dynamic timeout; +@dynamic oauth2AccessToken; +@dynamic authTokenProvider; +@dynamic initialMetadata; +@dynamic userAgentPrefix; +@dynamic responseSizeLimit; +@dynamic compressAlgorithm; +@dynamic enableRetry; +@dynamic keepaliveInterval; +@dynamic keepaliveTimeout; +@dynamic connectMinTimeout; +@dynamic connectInitialBackoff; +@dynamic connectMaxBackoff; +@dynamic additionalChannelArgs; +@dynamic pemRootCert; +@dynamic pemPrivateKey; +@dynamic pemCertChain; +@dynamic transportType; +@dynamic hostNameOverride; +@dynamic logContext; +@dynamic channelPoolDomain; +@dynamic channelId; + +- (instancetype)init { + return [self initWithServerAuthority:kDefaultServerAuthority + timeout:kDefaultTimeout + oauth2AccessToken:kDefaultOauth2AccessToken + authTokenProvider:kDefaultAuthTokenProvider + initialMetadata:kDefaultInitialMetadata + userAgentPrefix:kDefaultUserAgentPrefix + responseSizeLimit:kDefaultResponseSizeLimit + compressAlgorithm:kDefaultCompressAlgorithm + enableRetry:kDefaultEnableRetry + keepaliveInterval:kDefaultKeepaliveInterval + keepaliveTimeout:kDefaultKeepaliveTimeout + connectMinTimeout:kDefaultConnectMinTimeout + connectInitialBackoff:kDefaultConnectInitialBackoff + connectMaxBackoff:kDefaultConnectMaxBackoff + additionalChannelArgs:kDefaultAdditionalChannelArgs + pemRootCert:kDefaultPemRootCert + pemPrivateKey:kDefaultPemPrivateKey + pemCertChain:kDefaultPemCertChain + transportType:kDefaultTransportType + hostNameOverride:kDefaultHostNameOverride + logContext:kDefaultLogContext + channelPoolDomain:kDefaultChannelPoolDomain + channelId:kDefaultChannelId]; +} + +- (nonnull id)copyWithZone:(NSZone *)zone { + GRPCCallOptions *newOptions = + [[GRPCCallOptions allocWithZone:zone] initWithServerAuthority:_serverAuthority + timeout:_timeout + oauth2AccessToken:_oauth2AccessToken + authTokenProvider:_authTokenProvider + initialMetadata:_initialMetadata + userAgentPrefix:_userAgentPrefix + responseSizeLimit:_responseSizeLimit + compressAlgorithm:_compressAlgorithm + enableRetry:_enableRetry + keepaliveInterval:_keepaliveInterval + keepaliveTimeout:_keepaliveTimeout + connectMinTimeout:_connectMinTimeout + connectInitialBackoff:_connectInitialBackoff + connectMaxBackoff:_connectMaxBackoff + additionalChannelArgs:[_additionalChannelArgs copy] + pemRootCert:_pemRootCert + pemPrivateKey:_pemPrivateKey + pemCertChain:_pemCertChain + transportType:_transportType + hostNameOverride:_hostNameOverride + logContext:_logContext + channelPoolDomain:_channelPoolDomain + channelId:_channelId]; + return newOptions; +} + +- (nonnull id)mutableCopyWithZone:(NSZone *)zone { + GRPCMutableCallOptions *newOptions = [[GRPCMutableCallOptions allocWithZone:zone] + initWithServerAuthority:_serverAuthority + timeout:_timeout + oauth2AccessToken:_oauth2AccessToken + authTokenProvider:_authTokenProvider + initialMetadata:_initialMetadata + userAgentPrefix:_userAgentPrefix + responseSizeLimit:_responseSizeLimit + compressAlgorithm:_compressAlgorithm + enableRetry:_enableRetry + keepaliveInterval:_keepaliveInterval + keepaliveTimeout:_keepaliveTimeout + connectMinTimeout:_connectMinTimeout + connectInitialBackoff:_connectInitialBackoff + connectMaxBackoff:_connectMaxBackoff + additionalChannelArgs:[_additionalChannelArgs copy] + pemRootCert:_pemRootCert + pemPrivateKey:_pemPrivateKey + pemCertChain:_pemCertChain + transportType:_transportType + hostNameOverride:_hostNameOverride + logContext:_logContext + channelPoolDomain:_channelPoolDomain + channelId:_channelId]; + return newOptions; +} + +- (void)setServerAuthority:(NSString *)serverAuthority { + _serverAuthority = serverAuthority; +} + +- (void)setTimeout:(NSTimeInterval)timeout { + _timeout = timeout; +} + +- (void)setOauth2AccessToken:(NSString *)oauth2AccessToken { + _oauth2AccessToken = oauth2AccessToken; +} + +- (void)setAuthTokenProvider:(id)authTokenProvider { + _authTokenProvider = authTokenProvider; +} + +- (void)setInitialMetadata:(NSDictionary *)initialMetadata { + _initialMetadata = initialMetadata; +} + +- (void)setUserAgentPrefix:(NSString *)userAgentPrefix { + _userAgentPrefix = userAgentPrefix; +} + +- (void)setResponseSizeLimit:(NSUInteger)responseSizeLimit { + _responseSizeLimit = responseSizeLimit; +} + +- (void)setCompressAlgorithm:(GRPCCompressAlgorithm)compressAlgorithm { + _compressAlgorithm = compressAlgorithm; +} + +- (void)setEnableRetry:(BOOL)enableRetry { + _enableRetry = enableRetry; +} + +- (void)setKeepaliveInterval:(NSTimeInterval)keepaliveInterval { + _keepaliveInterval = keepaliveInterval; +} + +- (void)setKeepaliveTimeout:(NSTimeInterval)keepaliveTimeout { + _keepaliveTimeout = keepaliveTimeout; +} + +- (void)setConnectMinTimeout:(NSTimeInterval)connectMinTimeout { + _connectMinTimeout = connectMinTimeout; +} + +- (void)setConnectInitialBackoff:(NSTimeInterval)connectInitialBackoff { + _connectInitialBackoff = connectInitialBackoff; +} + +- (void)setConnectMaxBackoff:(NSTimeInterval)connectMaxBackoff { + _connectMaxBackoff = connectMaxBackoff; +} + +- (void)setAdditionalChannelArgs:(NSDictionary *)additionalChannelArgs { + _additionalChannelArgs = additionalChannelArgs; +} + +- (void)setPemRootCert:(NSString *)pemRootCert { + _pemRootCert = pemRootCert; +} + +- (void)setPemPrivateKey:(NSString *)pemPrivateKey { + _pemPrivateKey = pemPrivateKey; +} + +- (void)setPemCertChain:(NSString *)pemCertChain { + _pemCertChain = pemCertChain; +} + +- (void)setTransportType:(GRPCTransportType)transportType { + _transportType = transportType; +} + +- (void)setHostNameOverride:(NSString *)hostNameOverride { + _hostNameOverride = hostNameOverride; +} + +- (void)setLogContext:(id)logContext { + _logContext = logContext; +} + +- (void)setChannelPoolDomain:(NSString *)channelPoolDomain { + _channelPoolDomain = channelPoolDomain; +} + +- (void)setChannelId:(NSUInteger)channelId { + _channelId = channelId; +} + +@end From 0fd4727defda5f8bef106a1f3b59263886b9b6c6 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 8 Oct 2018 15:51:39 -0700 Subject: [PATCH 004/375] deprecated old API --- .../GRPCClient/GRPCCall+ChannelArg.h | 34 +------------------ .../GRPCClient/GRPCCall+ChannelArg.m | 5 +-- .../GRPCClient/GRPCCall+ChannelCredentials.h | 10 +----- src/objective-c/GRPCClient/GRPCCall+Cronet.h | 13 +------ src/objective-c/GRPCClient/GRPCCall+OAuth2.h | 29 +++------------- src/objective-c/GRPCClient/GRPCCall+Tests.h | 25 ++------------ src/objective-c/GRPCClient/GRPCCall+Tests.m | 4 ++- 7 files changed, 15 insertions(+), 105 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h index 803f19dedfe..2ddd53a5c66 100644 --- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h +++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h @@ -19,52 +19,20 @@ #include -typedef NS_ENUM(NSInteger, GRPCCompressAlgorithm) { - GRPCCompressNone, - GRPCCompressDeflate, - GRPCCompressGzip, -}; - -/** - * Methods to configure GRPC channel options. - */ +// Deprecated interface. Please use GRPCCallOptions instead. @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. - */ + (void)setUserAgentPrefix:(nonnull NSString *)userAgentPrefix forHost:(nonnull NSString *)host; - -/** 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)setDefaultCompressMethod:(GRPCCompressAlgorithm)algorithm forhost:(nonnull NSString *)host; - -/** Enable keepalive and configure keepalive parameters. A user should call this function once to - * enable keepalive for a particular host. gRPC client sends a ping after every \a interval ms to - * check if the transport is still alive. After waiting for \a timeout ms, if the client does not - * receive the ping ack, it closes the transport; all pending calls to this host will fail with - * error GRPC_STATUS_INTERNAL with error information "keepalive watchdog timeout". */ + (void)setKeepaliveWithInterval:(int)interval timeout:(int)timeout forHost:(nonnull NSString *)host; - -/** Enable/Disable automatic retry of gRPC calls on the channel. If automatic retry is enabled, the - * retry is controlled by server's service config. If automatic retry is disabled, failed calls are - * immediately returned to the application layer. */ + (void)enableRetry:(BOOL)enabled forHost:(nonnull NSString *)host; - -/** Set channel connection timeout and backoff parameters. All parameters are positive integers in - * milliseconds. Set a parameter to 0 to make gRPC use default value for that parameter. - * - * Refer to gRPC's doc at https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md for the - * details of each parameter. */ + (void)setMinConnectTimeout:(unsigned int)timeout initialBackoff:(unsigned int)initialBackoff maxBackoff:(unsigned int)maxBackoff diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m index 0e631fb3adf..d01d0c0d4fd 100644 --- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m +++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m @@ -18,6 +18,7 @@ #import "GRPCCall+ChannelArg.h" +#import "private/GRPCChannel.h" #import "private/GRPCHost.h" #import @@ -31,11 +32,11 @@ + (void)setResponseSizeLimit:(NSUInteger)limit forHost:(nonnull NSString *)host { GRPCHost *hostConfig = [GRPCHost hostWithAddress:host]; - hostConfig.responseSizeLimitOverride = @(limit); + hostConfig.responseSizeLimitOverride = limit; } + (void)closeOpenConnections { - [GRPCHost flushChannelCache]; + [GRPCChannel closeOpenConnections]; } + (void)setDefaultCompressMethod:(GRPCCompressAlgorithm)algorithm forhost:(nonnull NSString *)host { diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h b/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h index d7d15c4ee38..7d6f79b7655 100644 --- a/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h +++ b/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h @@ -18,20 +18,12 @@ #import "GRPCCall.h" -/** Helpers for setting TLS Trusted Roots, Client Certificates, and Private Key */ +// Deprecated interface. Please use GRPCCallOptions instead. @interface GRPCCall (ChannelCredentials) -/** - * 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; -/** - * 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 diff --git a/src/objective-c/GRPCClient/GRPCCall+Cronet.h b/src/objective-c/GRPCClient/GRPCCall+Cronet.h index 2a5f6e9cf0e..3059c6f1860 100644 --- a/src/objective-c/GRPCClient/GRPCCall+Cronet.h +++ b/src/objective-c/GRPCClient/GRPCCall+Cronet.h @@ -20,22 +20,11 @@ #import "GRPCCall.h" -/** - * Methods for using cronet transport. - */ +// Deprecated interface. Please use GRPCCallOptions instead. @interface GRPCCall (Cronet) -/** - * This method should be called before issuing the first RPC. It should be - * called only once. Create an instance of Cronet engine in your app elsewhere - * and pass the instance pointer in the stream_engine parameter. Once set, - * all subsequent RPCs will use Cronet transport. The method is not thread - * safe. - */ + (void)useCronetWithEngine:(stream_engine*)engine; - + (stream_engine*)cronetEngine; - + (BOOL)isUsingCronet; @end diff --git a/src/objective-c/GRPCClient/GRPCCall+OAuth2.h b/src/objective-c/GRPCClient/GRPCCall+OAuth2.h index adb1042aa0e..3054bfc5a7a 100644 --- a/src/objective-c/GRPCClient/GRPCCall+OAuth2.h +++ b/src/objective-c/GRPCClient/GRPCCall+OAuth2.h @@ -18,34 +18,13 @@ #import "GRPCCall.h" -/** - * The protocol of an OAuth2 token object from which GRPCCall can acquire a token. - */ -@protocol GRPCAuthorizationProtocol -- (void)getTokenWithHandler:(void (^)(NSString *token))hander; -@end +#import "GRPCCallOptions.h" -/** Helpers for setting and reading headers compatible with OAuth2. */ +// Deprecated interface. Please use GRPCCallOptions instead. @interface GRPCCall (OAuth2) -/** - * Setting this property is equivalent to setting "Bearer " 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 ", or nil otherwise. - */ -@property(atomic, copy) NSString *oauth2AccessToken; - -/** Returns the value (if any) of the "www-authenticate" response header (the challenge header). */ -@property(atomic, readonly) NSString *oauth2ChallengeHeader; - -/** - * The authorization token object to be used when starting the call. If the value is set to nil, no - * oauth authentication will be used. - * - * If tokenProvider exists, it takes precedence over the token set by oauth2AccessToken. - */ +@property(atomic, copy) NSString* oauth2AccessToken; +@property(atomic, readonly) NSString* oauth2ChallengeHeader; @property(atomic, strong) id tokenProvider; @end diff --git a/src/objective-c/GRPCClient/GRPCCall+Tests.h b/src/objective-c/GRPCClient/GRPCCall+Tests.h index 5d35182ae52..edaa5ed582c 100644 --- a/src/objective-c/GRPCClient/GRPCCall+Tests.h +++ b/src/objective-c/GRPCClient/GRPCCall+Tests.h @@ -18,34 +18,13 @@ #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. - */ +// Deprecated interface. Please use GRPCCallOptions instead. @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. 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; - -/** - * 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+Tests.m b/src/objective-c/GRPCClient/GRPCCall+Tests.m index 0db3ad6b399..ac3b6a658f9 100644 --- a/src/objective-c/GRPCClient/GRPCCall+Tests.m +++ b/src/objective-c/GRPCClient/GRPCCall+Tests.m @@ -20,6 +20,8 @@ #import "private/GRPCHost.h" +#import "GRPCCallOptions.h" + @implementation GRPCCall (Tests) + (void)useTestCertsPath:(NSString *)certsPath @@ -42,7 +44,7 @@ + (void)useInsecureConnectionsForHost:(NSString *)host { GRPCHost *hostConfig = [GRPCHost hostWithAddress:host]; - hostConfig.secure = NO; + hostConfig.transportType = GRPCTransportTypeInsecure; } + (void)resetHostSettings { From 309ba191525a96c5314e5762ecaa2fffbc9eccbb Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 8 Oct 2018 15:52:27 -0700 Subject: [PATCH 005/375] Channel pool --- .../GRPCClient/private/ChannelArgsUtil.h | 25 ++ .../GRPCClient/private/ChannelArgsUtil.m | 95 +++++ .../GRPCClient/private/GRPCChannel.h | 43 +- .../GRPCClient/private/GRPCChannel.m | 242 ++++------- .../GRPCClient/private/GRPCChannelFactory.h | 32 ++ .../GRPCClient/private/GRPCChannelPool.h | 69 ++++ .../GRPCClient/private/GRPCChannelPool.m | 387 ++++++++++++++++++ .../private/GRPCCronetChannelFactory.h | 36 ++ .../private/GRPCCronetChannelFactory.m | 94 +++++ src/objective-c/GRPCClient/private/GRPCHost.h | 31 +- src/objective-c/GRPCClient/private/GRPCHost.m | 261 ++---------- .../private/GRPCInsecureChannelFactory.h | 35 ++ .../private/GRPCInsecureChannelFactory.m | 48 +++ .../private/GRPCSecureChannelFactory.h | 38 ++ .../private/GRPCSecureChannelFactory.m | 129 ++++++ .../GRPCClient/private/GRPCWrappedCall.h | 3 +- .../GRPCClient/private/GRPCWrappedCall.m | 18 +- 17 files changed, 1138 insertions(+), 448 deletions(-) create mode 100644 src/objective-c/GRPCClient/private/ChannelArgsUtil.h create mode 100644 src/objective-c/GRPCClient/private/ChannelArgsUtil.m create mode 100644 src/objective-c/GRPCClient/private/GRPCChannelFactory.h create mode 100644 src/objective-c/GRPCClient/private/GRPCChannelPool.h create mode 100644 src/objective-c/GRPCClient/private/GRPCChannelPool.m create mode 100644 src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h create mode 100644 src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m create mode 100644 src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h create mode 100644 src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m create mode 100644 src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h create mode 100644 src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m diff --git a/src/objective-c/GRPCClient/private/ChannelArgsUtil.h b/src/objective-c/GRPCClient/private/ChannelArgsUtil.h new file mode 100644 index 00000000000..d9d6933c6bb --- /dev/null +++ b/src/objective-c/GRPCClient/private/ChannelArgsUtil.h @@ -0,0 +1,25 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import + +#include + +void FreeChannelArgs(grpc_channel_args* channel_args); + +grpc_channel_args* BuildChannelArgs(NSDictionary* dictionary); diff --git a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m new file mode 100644 index 00000000000..8ebf3a26593 --- /dev/null +++ b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m @@ -0,0 +1,95 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import "ChannelArgsUtil.h" + +#include +#include + +static void *copy_pointer_arg(void *p) { + // Add ref count to the object when making copy + id obj = (__bridge id)p; + return (__bridge_retained void *)obj; +} + +static void destroy_pointer_arg(void *p) { + // Decrease ref count to the object when destroying + CFRelease((CFTreeRef)p); +} + +static int cmp_pointer_arg(void *p, void *q) { return p == q; } + +static const grpc_arg_pointer_vtable objc_arg_vtable = {copy_pointer_arg, destroy_pointer_arg, + cmp_pointer_arg}; + +void FreeChannelArgs(grpc_channel_args *channel_args) { + for (size_t i = 0; i < channel_args->num_args; ++i) { + grpc_arg *arg = &channel_args->args[i]; + gpr_free(arg->key); + if (arg->type == GRPC_ARG_STRING) { + gpr_free(arg->value.string); + } + } + gpr_free(channel_args->args); + gpr_free(channel_args); +} + +/** + * Allocates a @c grpc_channel_args and populates it with the options specified in the + * @c dictionary. Keys must be @c NSString. If the value responds to @c @selector(UTF8String) then + * it will be mapped to @c GRPC_ARG_STRING. If not, it will be mapped to @c GRPC_ARG_INTEGER if the + * value responds to @c @selector(intValue). Otherwise, an exception will be raised. The caller of + * this function is responsible for calling @c freeChannelArgs on a non-NULL returned value. + */ +grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) { + if (!dictionary) { + return NULL; + } + + NSArray *keys = [dictionary allKeys]; + NSUInteger argCount = [keys count]; + + grpc_channel_args *channelArgs = gpr_malloc(sizeof(grpc_channel_args)); + channelArgs->num_args = argCount; + channelArgs->args = gpr_malloc(argCount * sizeof(grpc_arg)); + + // TODO(kriswuollett) Check that keys adhere to GRPC core library requirements + + for (NSUInteger i = 0; i < argCount; ++i) { + grpc_arg *arg = &channelArgs->args[i]; + arg->key = gpr_strdup([keys[i] UTF8String]); + + id value = dictionary[keys[i]]; + if ([value respondsToSelector:@selector(UTF8String)]) { + arg->type = GRPC_ARG_STRING; + arg->value.string = gpr_strdup([value UTF8String]); + } else if ([value respondsToSelector:@selector(intValue)]) { + arg->type = GRPC_ARG_INTEGER; + arg->value.integer = [value intValue]; + } else if (value != nil) { + arg->type = GRPC_ARG_POINTER; + arg->value.pointer.p = (__bridge_retained void *)value; + arg->value.pointer.vtable = &objc_arg_vtable; + } else { + [NSException raise:NSInvalidArgumentException + format:@"Invalid value type: %@", [value class]]; + } + } + + return channelArgs; +} diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index 6499d4398c8..7d5039a8a20 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -21,6 +21,8 @@ #include @class GRPCCompletionQueue; +@class GRPCCallOptions; +@class GRPCChannelConfiguration; struct grpc_channel_credentials; /** @@ -28,41 +30,30 @@ struct grpc_channel_credentials; */ @interface GRPCChannel : NSObject -@property(nonatomic, readonly, nonnull) struct grpc_channel *unmanagedChannel; - - (nullable instancetype)init NS_UNAVAILABLE; /** - * Creates a secure channel to the specified @c host using default credentials and channel - * arguments. If certificates could not be found to create a secure channel, then @c nil is - * returned. + * Returns a channel connecting to \a host with options as \a callOptions. The channel may be new + * or a cached channel that is already connected. */ -+ (nullable GRPCChannel *)secureChannelWithHost:(nonnull NSString *)host; ++ (nullable instancetype)channelWithHost:(nonnull NSString *)host + callOptions:(nullable GRPCCallOptions *)callOptions; /** - * Creates a secure channel to the specified @c host using Cronet as a transport mechanism. - */ -#ifdef GRPC_COMPILE_WITH_CRONET -+ (nullable GRPCChannel *)secureCronetChannelWithHost:(nonnull NSString *)host - channelArgs:(nonnull NSDictionary *)channelArgs; -#endif -/** - * Creates a secure channel to the specified @c host using the specified @c credentials and - * @c channelArgs. Only in tests should @c GRPC_SSL_TARGET_NAME_OVERRIDE_ARG channel arg be set. + * Get a grpc core call object from this channel. */ -+ (nonnull GRPCChannel *)secureChannelWithHost:(nonnull NSString *)host - credentials: - (nonnull struct grpc_channel_credentials *)credentials - channelArgs:(nullable NSDictionary *)channelArgs; +- (nullable grpc_call *)unmanagedCallWithPath:(nonnull NSString *)path + completionQueue:(nonnull GRPCCompletionQueue *)queue + callOptions:(nonnull GRPCCallOptions *)callOptions; + +- (void)unmanagedCallUnref; /** - * Creates an insecure channel to the specified @c host using the specified @c channelArgs. + * Create a channel object with the signature \a config. This function is used for testing only. Use + * channelWithHost:callOptions: in production. */ -+ (nonnull GRPCChannel *)insecureChannelWithHost:(nonnull NSString *)host - channelArgs:(nullable NSDictionary *)channelArgs; ++ (nullable instancetype)createChannelWithConfiguration:(nonnull GRPCChannelConfiguration *)config; -- (nullable grpc_call *)unmanagedCallWithPath:(nonnull NSString *)path - serverName:(nonnull NSString *)serverName - timeout:(NSTimeInterval)timeout - completionQueue:(nonnull GRPCCompletionQueue *)queue; +// TODO (mxyan): deprecate with GRPCCall:closeOpenConnections ++ (void)closeOpenConnections; @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index b1f6ea270ef..cf44b96e220 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -18,206 +18,106 @@ #import "GRPCChannel.h" -#include -#ifdef GRPC_COMPILE_WITH_CRONET -#include -#endif -#include #include -#include -#ifdef GRPC_COMPILE_WITH_CRONET -#import -#import -#endif +#import "ChannelArgsUtil.h" +#import "GRPCChannelFactory.h" +#import "GRPCChannelPool.h" #import "GRPCCompletionQueue.h" +#import "GRPCConnectivityMonitor.h" +#import "GRPCCronetChannelFactory.h" +#import "GRPCInsecureChannelFactory.h" +#import "GRPCSecureChannelFactory.h" +#import "version.h" -static void *copy_pointer_arg(void *p) { - // Add ref count to the object when making copy - id obj = (__bridge id)p; - return (__bridge_retained void *)obj; -} - -static void destroy_pointer_arg(void *p) { - // Decrease ref count to the object when destroying - CFRelease((CFTreeRef)p); -} - -static int cmp_pointer_arg(void *p, void *q) { return p == q; } - -static const grpc_arg_pointer_vtable objc_arg_vtable = {copy_pointer_arg, destroy_pointer_arg, - cmp_pointer_arg}; - -static void FreeChannelArgs(grpc_channel_args *channel_args) { - for (size_t i = 0; i < channel_args->num_args; ++i) { - grpc_arg *arg = &channel_args->args[i]; - gpr_free(arg->key); - if (arg->type == GRPC_ARG_STRING) { - gpr_free(arg->value.string); - } - } - gpr_free(channel_args->args); - gpr_free(channel_args); -} - -/** - * Allocates a @c grpc_channel_args and populates it with the options specified in the - * @c dictionary. Keys must be @c NSString. If the value responds to @c @selector(UTF8String) then - * it will be mapped to @c GRPC_ARG_STRING. If not, it will be mapped to @c GRPC_ARG_INTEGER if the - * value responds to @c @selector(intValue). Otherwise, an exception will be raised. The caller of - * this function is responsible for calling @c freeChannelArgs on a non-NULL returned value. - */ -static grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) { - if (!dictionary) { - return NULL; - } - - NSArray *keys = [dictionary allKeys]; - NSUInteger argCount = [keys count]; - - grpc_channel_args *channelArgs = gpr_malloc(sizeof(grpc_channel_args)); - channelArgs->num_args = argCount; - channelArgs->args = gpr_malloc(argCount * sizeof(grpc_arg)); - - // TODO(kriswuollett) Check that keys adhere to GRPC core library requirements - - for (NSUInteger i = 0; i < argCount; ++i) { - grpc_arg *arg = &channelArgs->args[i]; - arg->key = gpr_strdup([keys[i] UTF8String]); - - id value = dictionary[keys[i]]; - if ([value respondsToSelector:@selector(UTF8String)]) { - arg->type = GRPC_ARG_STRING; - arg->value.string = gpr_strdup([value UTF8String]); - } else if ([value respondsToSelector:@selector(intValue)]) { - arg->type = GRPC_ARG_INTEGER; - arg->value.integer = [value intValue]; - } else if (value != nil) { - arg->type = GRPC_ARG_POINTER; - arg->value.pointer.p = (__bridge_retained void *)value; - arg->value.pointer.vtable = &objc_arg_vtable; - } else { - [NSException raise:NSInvalidArgumentException - format:@"Invalid value type: %@", [value class]]; - } - } - - return channelArgs; -} +#import +#import @implementation GRPCChannel { - // Retain arguments to channel_create because they may not be used on the thread that invoked - // the channel_create function. - NSString *_host; - grpc_channel_args *_channelArgs; + GRPCChannelConfiguration *_configuration; + grpc_channel *_unmanagedChannel; } -#ifdef GRPC_COMPILE_WITH_CRONET -- (instancetype)initWithHost:(NSString *)host - cronetEngine:(stream_engine *)cronetEngine - channelArgs:(NSDictionary *)channelArgs { - if (!host) { - [NSException raise:NSInvalidArgumentException format:@"host argument missing"]; +- (grpc_call *)unmanagedCallWithPath:(NSString *)path + completionQueue:(nonnull GRPCCompletionQueue *)queue + callOptions:(GRPCCallOptions *)callOptions { + NSString *serverAuthority = callOptions.serverAuthority; + NSTimeInterval timeout = callOptions.timeout; + GPR_ASSERT(timeout >= 0); + grpc_slice host_slice = grpc_empty_slice(); + if (serverAuthority) { + host_slice = grpc_slice_from_copied_string(serverAuthority.UTF8String); } - - if (self = [super init]) { - _channelArgs = BuildChannelArgs(channelArgs); - _host = [host copy]; - _unmanagedChannel = - grpc_cronet_secure_channel_create(cronetEngine, _host.UTF8String, _channelArgs, NULL); + grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); + gpr_timespec deadline_ms = + timeout == 0 ? gpr_inf_future(GPR_CLOCK_REALTIME) + : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); + grpc_call *call = grpc_channel_create_call( + _unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, queue.unmanagedQueue, path_slice, + serverAuthority ? &host_slice : NULL, deadline_ms, NULL); + if (serverAuthority) { + grpc_slice_unref(host_slice); } - - return self; + grpc_slice_unref(path_slice); + return call; } -#endif - -- (instancetype)initWithHost:(NSString *)host - secure:(BOOL)secure - credentials:(struct grpc_channel_credentials *)credentials - channelArgs:(NSDictionary *)channelArgs { - if (!host) { - [NSException raise:NSInvalidArgumentException format:@"host argument missing"]; - } - if (secure && !credentials) { - return nil; - } +- (void)unmanagedCallUnref { + [kChannelPool unrefChannelWithConfiguration:_configuration]; +} - if (self = [super init]) { - _channelArgs = BuildChannelArgs(channelArgs); - _host = [host copy]; - if (secure) { - _unmanagedChannel = - grpc_secure_channel_create(credentials, _host.UTF8String, _channelArgs, NULL); - } else { - _unmanagedChannel = grpc_insecure_channel_create(_host.UTF8String, _channelArgs, NULL); - } +- (nullable instancetype)initWithUnmanagedChannel:(nullable grpc_channel *)unmanagedChannel + configuration:(GRPCChannelConfiguration *)configuration { + if ((self = [super init])) { + _unmanagedChannel = unmanagedChannel; + _configuration = configuration; } - return self; } - (void)dealloc { - // TODO(jcanizales): Be sure to add a test with a server that closes the connection prematurely, - // as in the past that made this call to crash. grpc_channel_destroy(_unmanagedChannel); - FreeChannelArgs(_channelArgs); } -#ifdef GRPC_COMPILE_WITH_CRONET -+ (GRPCChannel *)secureCronetChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *)channelArgs { - stream_engine *engine = [GRPCCall cronetEngine]; - if (!engine) { - [NSException raise:NSInvalidArgumentException format:@"cronet_engine is NULL. Set it first."]; ++ (nullable instancetype)createChannelWithConfiguration:(GRPCChannelConfiguration *)config { + NSString *host = config.host; + if (host == nil || [host length] == 0) { return nil; } - return [[GRPCChannel alloc] initWithHost:host cronetEngine:engine channelArgs:channelArgs]; -} -#endif -+ (GRPCChannel *)secureChannelWithHost:(NSString *)host { - return [[GRPCChannel alloc] initWithHost:host secure:YES credentials:NULL channelArgs:NULL]; + NSMutableDictionary *channelArgs = config.channelArgs; + [channelArgs addEntriesFromDictionary:config.callOptions.additionalChannelArgs]; + id factory = config.channelFactory; + grpc_channel *unmanaged_channel = [factory createChannelWithHost:host channelArgs:channelArgs]; + return [[GRPCChannel alloc] initWithUnmanagedChannel:unmanaged_channel configuration:config]; } -+ (GRPCChannel *)secureChannelWithHost:(NSString *)host - credentials:(struct grpc_channel_credentials *)credentials - channelArgs:(NSDictionary *)channelArgs { - return [[GRPCChannel alloc] initWithHost:host - secure:YES - credentials:credentials - channelArgs:channelArgs]; -} +static dispatch_once_t initChannelPool; +static GRPCChannelPool *kChannelPool; -+ (GRPCChannel *)insecureChannelWithHost:(NSString *)host channelArgs:(NSDictionary *)channelArgs { - return [[GRPCChannel alloc] initWithHost:host secure:NO credentials:NULL channelArgs:channelArgs]; -} ++ (nullable instancetype)channelWithHost:(NSString *)host + callOptions:(GRPCCallOptions *)callOptions { + dispatch_once(&initChannelPool, ^{ + kChannelPool = [[GRPCChannelPool alloc] init]; + }); -- (grpc_call *)unmanagedCallWithPath:(NSString *)path - serverName:(NSString *)serverName - timeout:(NSTimeInterval)timeout - completionQueue:(GRPCCompletionQueue *)queue { - GPR_ASSERT(timeout >= 0); - if (timeout < 0) { - timeout = 0; + NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:host]]; + if (hostURL.host && !hostURL.port) { + host = [hostURL.host stringByAppendingString:@":443"]; } - grpc_slice host_slice = grpc_empty_slice(); - if (serverName) { - host_slice = grpc_slice_from_copied_string(serverName.UTF8String); - } - grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); - gpr_timespec deadline_ms = - timeout == 0 ? gpr_inf_future(GPR_CLOCK_REALTIME) - : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); - grpc_call *call = grpc_channel_create_call(_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, - queue.unmanagedQueue, path_slice, - serverName ? &host_slice : NULL, deadline_ms, NULL); - if (serverName) { - grpc_slice_unref(host_slice); - } - grpc_slice_unref(path_slice); - return call; + + GRPCChannelConfiguration *channelConfig = + [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; + return [kChannelPool channelWithConfiguration:channelConfig + createChannel:^{ + return + [GRPCChannel createChannelWithConfiguration:channelConfig]; + }]; +} + ++ (void)closeOpenConnections { + [kChannelPool clear]; } @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h new file mode 100644 index 00000000000..e44f8260dfd --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h @@ -0,0 +1,32 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import + +#include + +NS_ASSUME_NONNULL_BEGIN + +@protocol GRPCChannelFactory + +- (nullable grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(nullable NSMutableDictionary *)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h new file mode 100644 index 00000000000..1145039549c --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -0,0 +1,69 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/** + * Signature for the channel. If two channel's signatures are the same, they share the same + * underlying \a GRPCChannel object. + */ + +#import + +#import "GRPCChannelFactory.h" + +NS_ASSUME_NONNULL_BEGIN + +@class GRPCChannel; + +@interface GRPCChannelConfiguration : NSObject + +@property(atomic, strong, readwrite) NSString *host; +@property(atomic, strong, readwrite) GRPCCallOptions *callOptions; + +@property(readonly) id channelFactory; +@property(readonly) NSMutableDictionary *channelArgs; + +- (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; + +@end + +/** + * Manage the pool of connected channels. When a channel is no longer referenced by any call, + * destroy the channel after a certain period of time elapsed. + */ +@interface GRPCChannelPool : NSObject + +- (instancetype)init; + +- (instancetype)initWithChannelDestroyDelay:(NSTimeInterval)channelDestroyDelay; + +/** + * Return a channel with a particular configuration. If the channel does not exist, execute \a + * createChannel then add it in the pool. If the channel exists, increase its reference count. + */ +- (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration + createChannel:(GRPCChannel * (^)(void))createChannel; + +/** Decrease a channel's refcount. */ +- (void)unrefChannelWithConfiguration:configuration; + +/** Clear all channels in the pool. */ +- (void)clear; + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m new file mode 100644 index 00000000000..b5f0949ef73 --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -0,0 +1,387 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import + +#import "GRPCChannelFactory.h" +#import "GRPCChannelPool.h" +#import "GRPCConnectivityMonitor.h" +#import "GRPCCronetChannelFactory.h" +#import "GRPCInsecureChannelFactory.h" +#import "GRPCSecureChannelFactory.h" +#import "version.h" + +#import +#include + +extern const char *kCFStreamVarName; + +// When all calls of a channel are destroyed, destroy the channel after this much seconds. +const NSTimeInterval kChannelDestroyDelay = 30; + +@implementation GRPCChannelConfiguration + +- (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { + if ((self = [super init])) { + _host = host; + _callOptions = callOptions; + } + return self; +} + +- (id)channelFactory { + NSError *error; + id factory; + GRPCTransportType type = _callOptions.transportType; + switch (type) { + case GRPCTransportTypeDefault: + // TODO (mxyan): Remove when the API is deprecated +#ifdef GRPC_COMPILE_WITH_CRONET + if (![GRPCCall isUsingCronet]) { +#endif + factory = [GRPCSecureChannelFactory factoryWithPEMRootCerts:_callOptions.pemRootCert + privateKey:_callOptions.pemPrivateKey + certChain:_callOptions.pemCertChain + error:&error]; + if (error) { + NSLog(@"Error creating secure channel factory: %@", error); + return nil; + } + return factory; +#ifdef GRPC_COMPILE_WITH_CRONET + } +#endif + // fallthrough + case GRPCTransportTypeCronet: + return [GRPCCronetChannelFactory sharedInstance]; + case GRPCTransportTypeInsecure: + return [GRPCInsecureChannelFactory sharedInstance]; + default: + GPR_UNREACHABLE_CODE(return nil); + } +} + +- (NSMutableDictionary *)channelArgs { + NSMutableDictionary *args = [NSMutableDictionary new]; + + NSString *userAgent = @"grpc-objc/" GRPC_OBJC_VERSION_STRING; + NSString *userAgentPrefix = _callOptions.userAgentPrefix; + if (userAgentPrefix) { + args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = + [_callOptions.userAgentPrefix stringByAppendingFormat:@" %@", userAgent]; + } else { + args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = userAgent; + } + + NSString *hostNameOverride = _callOptions.hostNameOverride; + if (hostNameOverride) { + args[@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG] = hostNameOverride; + } + + if (_callOptions.responseSizeLimit) { + args[@GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH] = + [NSNumber numberWithUnsignedInteger:_callOptions.responseSizeLimit]; + } + + if (_callOptions.compressAlgorithm != GRPC_COMPRESS_NONE) { + args[@GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM] = + [NSNumber numberWithInt:_callOptions.compressAlgorithm]; + } + + if (_callOptions.keepaliveInterval != 0) { + args[@GRPC_ARG_KEEPALIVE_TIME_MS] = + [NSNumber numberWithUnsignedInteger:(unsigned int)(_callOptions.keepaliveInterval * 1000)]; + args[@GRPC_ARG_KEEPALIVE_TIMEOUT_MS] = + [NSNumber numberWithUnsignedInteger:(unsigned int)(_callOptions.keepaliveTimeout * 1000)]; + } + + if (_callOptions.enableRetry == NO) { + args[@GRPC_ARG_ENABLE_RETRIES] = [NSNumber numberWithInt:_callOptions.enableRetry]; + } + + if (_callOptions.connectMinTimeout > 0) { + args[@GRPC_ARG_MIN_RECONNECT_BACKOFF_MS] = + [NSNumber numberWithUnsignedInteger:(unsigned int)(_callOptions.connectMinTimeout * 1000)]; + } + if (_callOptions.connectInitialBackoff > 0) { + args[@GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS] = [NSNumber + numberWithUnsignedInteger:(unsigned int)(_callOptions.connectInitialBackoff * 1000)]; + } + if (_callOptions.connectMaxBackoff > 0) { + args[@GRPC_ARG_MAX_RECONNECT_BACKOFF_MS] = + [NSNumber numberWithUnsignedInteger:(unsigned int)(_callOptions.connectMaxBackoff * 1000)]; + } + + if (_callOptions.logContext != nil) { + args[@GRPC_ARG_MOBILE_LOG_CONTEXT] = _callOptions.logContext; + } + + if (_callOptions.channelPoolDomain != nil) { + args[@GRPC_ARG_CHANNEL_POOL_DOMAIN] = _callOptions.channelPoolDomain; + } + + [args addEntriesFromDictionary:_callOptions.additionalChannelArgs]; + + return args; +} + +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + GRPCChannelConfiguration *newConfig = [[GRPCChannelConfiguration alloc] init]; + newConfig.host = _host; + newConfig.callOptions = _callOptions; + + return newConfig; +} + +- (BOOL)isEqual:(id)object { + NSAssert([object isKindOfClass:[GRPCChannelConfiguration class]], @"Illegal :isEqual"); + GRPCChannelConfiguration *obj = (GRPCChannelConfiguration *)object; + if (!(obj.host == _host || [obj.host isEqualToString:_host])) return NO; + if (!(obj.callOptions.userAgentPrefix == _callOptions.userAgentPrefix || + [obj.callOptions.userAgentPrefix isEqualToString:_callOptions.userAgentPrefix])) + return NO; + if (!(obj.callOptions.responseSizeLimit == _callOptions.responseSizeLimit)) return NO; + if (!(obj.callOptions.compressAlgorithm == _callOptions.compressAlgorithm)) return NO; + if (!(obj.callOptions.enableRetry == _callOptions.enableRetry)) return NO; + if (!(obj.callOptions.keepaliveInterval == _callOptions.keepaliveInterval)) return NO; + if (!(obj.callOptions.keepaliveTimeout == _callOptions.keepaliveTimeout)) return NO; + if (!(obj.callOptions.connectMinTimeout == _callOptions.connectMinTimeout)) return NO; + if (!(obj.callOptions.connectInitialBackoff == _callOptions.connectInitialBackoff)) return NO; + if (!(obj.callOptions.connectMaxBackoff == _callOptions.connectMaxBackoff)) return NO; + if (!(obj.callOptions.additionalChannelArgs == _callOptions.additionalChannelArgs || + [obj.callOptions.additionalChannelArgs + isEqualToDictionary:_callOptions.additionalChannelArgs])) + return NO; + if (!(obj.callOptions.pemRootCert == _callOptions.pemRootCert || + [obj.callOptions.pemRootCert isEqualToString:_callOptions.pemRootCert])) + return NO; + if (!(obj.callOptions.pemPrivateKey == _callOptions.pemPrivateKey || + [obj.callOptions.pemPrivateKey isEqualToString:_callOptions.pemPrivateKey])) + return NO; + if (!(obj.callOptions.pemCertChain == _callOptions.pemCertChain || + [obj.callOptions.pemCertChain isEqualToString:_callOptions.pemCertChain])) + return NO; + if (!(obj.callOptions.hostNameOverride == _callOptions.hostNameOverride || + [obj.callOptions.hostNameOverride isEqualToString:_callOptions.hostNameOverride])) + return NO; + if (!(obj.callOptions.transportType == _callOptions.transportType)) return NO; + if (!(obj.callOptions.logContext == _callOptions.logContext || + [obj.callOptions.logContext isEqual:_callOptions.logContext])) + return NO; + if (!(obj.callOptions.channelPoolDomain == _callOptions.channelPoolDomain || + [obj.callOptions.channelPoolDomain isEqualToString:_callOptions.channelPoolDomain])) + return NO; + if (!(obj.callOptions.channelId == _callOptions.channelId)) return NO; + + return YES; +} + +- (NSUInteger)hash { + NSUInteger result = 0; + result ^= _host.hash; + result ^= _callOptions.userAgentPrefix.hash; + result ^= _callOptions.responseSizeLimit; + result ^= _callOptions.compressAlgorithm; + result ^= _callOptions.enableRetry; + result ^= (unsigned int)(_callOptions.keepaliveInterval * 1000); + result ^= (unsigned int)(_callOptions.keepaliveTimeout * 1000); + result ^= (unsigned int)(_callOptions.connectMinTimeout * 1000); + result ^= (unsigned int)(_callOptions.connectInitialBackoff * 1000); + result ^= (unsigned int)(_callOptions.connectMaxBackoff * 1000); + result ^= _callOptions.additionalChannelArgs.hash; + result ^= _callOptions.pemRootCert.hash; + result ^= _callOptions.pemPrivateKey.hash; + result ^= _callOptions.pemCertChain.hash; + result ^= _callOptions.hostNameOverride.hash; + result ^= _callOptions.transportType; + result ^= [_callOptions.logContext hash]; + result ^= _callOptions.channelPoolDomain.hash; + result ^= _callOptions.channelId; + + return result; +} + +@end + +/** + * Time the channel destroy when the channel's calls are unreffed. If there's new call, reset the + * timer. + */ +@interface GRPCChannelCallRef : NSObject + +- (instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)configuration + destroyDelay:(NSTimeInterval)destroyDelay + dispatchQueue:(dispatch_queue_t)dispatchQueue + destroyChannel:(void (^)())destroyChannel; + +/** Add call ref count to the channel and maybe reset the timer. */ +- (void)refChannel; + +/** Reduce call ref count to the channel and maybe set the timer. */ +- (void)unrefChannel; + +@end + +@implementation GRPCChannelCallRef { + GRPCChannelConfiguration *_configuration; + NSTimeInterval _destroyDelay; + // We use dispatch queue for this purpose since timer invalidation must happen on the same + // thread which issued the timer. + dispatch_queue_t _dispatchQueue; + void (^_destroyChannel)(); + + NSUInteger _refCount; + NSTimer *_timer; +} + +- (instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)configuration + destroyDelay:(NSTimeInterval)destroyDelay + dispatchQueue:(dispatch_queue_t)dispatchQueue + destroyChannel:(void (^)())destroyChannel { + if ((self = [super init])) { + _configuration = configuration; + _destroyDelay = destroyDelay; + _dispatchQueue = dispatchQueue; + _destroyChannel = destroyChannel; + + _refCount = 0; + _timer = nil; + } + return self; +} + +// This function is protected by channel pool dispatch queue. +- (void)refChannel { + _refCount++; + if (_timer) { + [_timer invalidate]; + } + _timer = nil; +} + +// This function is protected by channel spool dispatch queue. +- (void)unrefChannel { + self->_refCount--; + if (self->_refCount == 0) { + if (self->_timer) { + [self->_timer invalidate]; + } + self->_timer = [NSTimer scheduledTimerWithTimeInterval:self->_destroyDelay + target:self + selector:@selector(timerFire:) + userInfo:nil + repeats:NO]; + } +} + +- (void)timerFire:(NSTimer *)timer { + dispatch_sync(_dispatchQueue, ^{ + if (self->_timer == nil || self->_timer != timer) { + return; + } + self->_timer = nil; + self->_destroyChannel(self->_configuration); + }); +} + +@end + +#pragma mark GRPCChannelPool + +@implementation GRPCChannelPool { + NSTimeInterval _channelDestroyDelay; + NSMutableDictionary *_channelPool; + NSMutableDictionary *_callRefs; + // Dedicated queue for timer + dispatch_queue_t _dispatchQueue; +} + +- (instancetype)init { + return [self initWithChannelDestroyDelay:kChannelDestroyDelay]; +} + +- (instancetype)initWithChannelDestroyDelay:(NSTimeInterval)channelDestroyDelay { + if ((self = [super init])) { + _channelDestroyDelay = channelDestroyDelay; + _channelPool = [NSMutableDictionary dictionary]; + _callRefs = [NSMutableDictionary dictionary]; + _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + + // Connectivity monitor is not required for CFStream + char *enableCFStream = getenv(kCFStreamVarName); + if (enableCFStream == nil || enableCFStream[0] != '1') { + [GRPCConnectivityMonitor registerObserver:self selector:@selector(connectivityChange:)]; + } + } + return self; +} + +- (void)dealloc { + // Connectivity monitor is not required for CFStream + char *enableCFStream = getenv(kCFStreamVarName); + if (enableCFStream == nil || enableCFStream[0] != '1') { + [GRPCConnectivityMonitor unregisterObserver:self]; + } +} + +- (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration + createChannel:(GRPCChannel * (^)(void))createChannel { + __block GRPCChannel *channel; + dispatch_sync(_dispatchQueue, ^{ + if ([self->_channelPool objectForKey:configuration]) { + [self->_callRefs[configuration] refChannel]; + channel = self->_channelPool[configuration]; + } else { + channel = createChannel(); + self->_channelPool[configuration] = channel; + + GRPCChannelCallRef *callRef = [[GRPCChannelCallRef alloc] + initWithChannelConfiguration:configuration + destroyDelay:self->_channelDestroyDelay + dispatchQueue:self->_dispatchQueue + destroyChannel:^(GRPCChannelConfiguration *configuration) { + [self->_channelPool removeObjectForKey:configuration]; + [self->_callRefs removeObjectForKey:configuration]; + }]; + [callRef refChannel]; + self->_callRefs[configuration] = callRef; + } + }); + return channel; +} + +- (void)unrefChannelWithConfiguration:configuration { + dispatch_sync(_dispatchQueue, ^{ + if ([self->_channelPool objectForKey:configuration]) { + [self->_callRefs[configuration] unrefChannel]; + } + }); +} + +- (void)clear { + dispatch_sync(_dispatchQueue, ^{ + self->_channelPool = [NSMutableDictionary dictionary]; + self->_callRefs = [NSMutableDictionary dictionary]; + }); +} + +- (void)connectivityChange:(NSNotification *)note { + [self clear]; +} + +@end diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h new file mode 100644 index 00000000000..97e1ae920a0 --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h @@ -0,0 +1,36 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#import "GRPCChannelFactory.h" + +@class GRPCChannel; +typedef struct stream_engine stream_engine; + +NS_ASSUME_NONNULL_BEGIN + +@interface GRPCCronetChannelFactory : NSObject + ++ (nullable instancetype)sharedInstance; + +- (nullable grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(nullable NSMutableDictionary *)args; + +- (nullable instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m new file mode 100644 index 00000000000..5c0fe16d39b --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m @@ -0,0 +1,94 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import "GRPCCronetChannelFactory.h" + +#import "ChannelArgsUtil.h" +#import "GRPCChannel.h" + +#ifdef GRPC_COMPILE_WITH_CRONET + +#import +#include + +NS_ASSUME_NONNULL_BEGIN + +@implementation GRPCCronetChannelFactory { + stream_engine *_cronetEngine; +} + ++ (nullable instancetype)sharedInstance { + static GRPCCronetChannelFactory *instance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] initWithEngine:[Cronet getGlobalEngine]]; + }); + return instance; +} + +- (nullable instancetype)initWithEngine:(stream_engine *)engine { + if (!engine) { + [NSException raise:NSInvalidArgumentException format:@"Cronet engine is NULL. Set it first."]; + return nil; + } + if ((self = [super init])) { + _cronetEngine = engine; + } + return self; +} + +- (nullable grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(nullable NSMutableDictionary *)args { + // Remove client authority filter since that is not supported + args[@GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER] = [NSNumber numberWithInt:1]; + + grpc_channel_args *channelArgs = BuildChannelArgs(args); + grpc_channel *unmanagedChannel = + grpc_cronet_secure_channel_create(_cronetEngine, host.UTF8String, channelArgs, NULL); + FreeChannelArgs(channelArgs); + return unmanagedChannel; +} + +@end + +NS_ASSUME_NONNULL_END + +#else + +NS_ASSUME_NONNULL_BEGIN + +@implementation GRPCCronetChannelFactory + ++ (nullable instancetype)sharedInstance { + [NSException raise:NSInvalidArgumentException + format:@"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."]; + return nil; +} + +- (nullable grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(nullable NSMutableArray *)args { + [NSException raise:NSInvalidArgumentException + format:@"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."]; + return nil; +} + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/src/objective-c/GRPCClient/private/GRPCHost.h b/src/objective-c/GRPCClient/private/GRPCHost.h index 291b07df377..32d3585351e 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.h +++ b/src/objective-c/GRPCClient/private/GRPCHost.h @@ -20,6 +20,10 @@ #import +#import "GRPCChannelFactory.h" + +#import + NS_ASSUME_NONNULL_BEGIN @class GRPCCompletionQueue; @@ -28,12 +32,10 @@ struct grpc_channel_credentials; @interface GRPCHost : NSObject -+ (void)flushChannelCache; + (void)resetAllHostSettings; @property(nonatomic, readonly) NSString *address; @property(nonatomic, copy, nullable) NSString *userAgentPrefix; -@property(nonatomic, nullable) struct grpc_channel_credentials *channelCreds; @property(nonatomic) grpc_compression_algorithm compressAlgorithm; @property(nonatomic) int keepaliveInterval; @property(nonatomic) int keepaliveTimeout; @@ -44,14 +46,14 @@ struct grpc_channel_credentials; @property(nonatomic) unsigned int initialConnectBackoff; @property(nonatomic) unsigned int maxConnectBackoff; -/** The following properties should only be modified for testing: */ +@property(nonatomic) id channelFactory; -@property(nonatomic, getter=isSecure) BOOL secure; +/** The following properties should only be modified for testing: */ @property(nonatomic, copy, nullable) NSString *hostNameOverride; /** The default response size limit is 4MB. Set this to override that default. */ -@property(nonatomic, strong, nullable) NSNumber *responseSizeLimitOverride; +@property(nonatomic) NSUInteger responseSizeLimitOverride; - (nullable instancetype)init NS_UNAVAILABLE; /** Host objects initialized with the same address are the same. */ @@ -62,19 +64,12 @@ struct grpc_channel_credentials; withCertChain:(nullable NSString *)pemCertChain error:(NSError **)errorPtr; -/** Create a grpc_call object to the provided path on this host. */ -- (nullable struct grpc_call *)unmanagedCallWithPath:(NSString *)path - serverName:(NSString *)serverName - timeout:(NSTimeInterval)timeout - completionQueue:(GRPCCompletionQueue *)queue; - -// TODO: There's a race when a new RPC is coming through just as an existing one is getting -// notified that there's no connectivity. If connectivity comes back at that moment, the new RPC -// will have its channel destroyed by the other RPC, and will never get notified of a problem, so -// it'll hang (the C layer logs a timeout, with exponential back off). One solution could be to pass -// the GRPCChannel to the GRPCCall, renaming this as "disconnectChannel:channel", which would only -// act on that specific channel. -- (void)disconnect; +@property(atomic, readwrite) GRPCTransportType transportType; + +@property(readonly) GRPCMutableCallOptions *callOptions; + ++ (BOOL)isHostConfigured:(NSString *)address; + @end NS_ASSUME_NONNULL_END diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 862909f2384..0e3fa610f9e 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -18,46 +18,35 @@ #import "GRPCHost.h" +#import #import + #include #include -#ifdef GRPC_COMPILE_WITH_CRONET -#import -#import -#endif -#import "GRPCChannel.h" +#import +#import "GRPCChannelFactory.h" #import "GRPCCompletionQueue.h" #import "GRPCConnectivityMonitor.h" +#import "GRPCCronetChannelFactory.h" +#import "GRPCSecureChannelFactory.h" #import "NSDictionary+GRPC.h" #import "version.h" NS_ASSUME_NONNULL_BEGIN -extern const char *kCFStreamVarName; - static NSMutableDictionary *kHostCache; @implementation GRPCHost { - // TODO(mlumish): Investigate whether caching channels with strong links is a good idea. - GRPCChannel *_channel; + NSString *_pemRootCerts; + NSString *_pemPrivateKey; + NSString *_pemCertChain; } + (nullable instancetype)hostWithAddress:(NSString *)address { return [[self alloc] initWithAddress:address]; } -- (void)dealloc { - if (_channelCreds != nil) { - grpc_channel_credentials_release(_channelCreds); - } - // Connectivity monitor is not required for CFStream - char *enableCFStream = getenv(kCFStreamVarName); - if (enableCFStream == nil || enableCFStream[0] != '1') { - [GRPCConnectivityMonitor unregisterObserver:self]; - } -} - // Default initializer. - (nullable instancetype)initWithAddress:(NSString *)address { if (!address) { @@ -86,230 +75,58 @@ static NSMutableDictionary *kHostCache; if ((self = [super init])) { _address = address; - _secure = YES; - kHostCache[address] = self; - _compressAlgorithm = GRPC_COMPRESS_NONE; _retryEnabled = YES; - } - - // Connectivity monitor is not required for CFStream - char *enableCFStream = getenv(kCFStreamVarName); - if (enableCFStream == nil || enableCFStream[0] != '1') { - [GRPCConnectivityMonitor registerObserver:self selector:@selector(connectivityChange:)]; + kHostCache[address] = self; } } return self; } -+ (void)flushChannelCache { - @synchronized(kHostCache) { - [kHostCache enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, GRPCHost *_Nonnull host, - BOOL *_Nonnull stop) { - [host disconnect]; - }]; - } -} - + (void)resetAllHostSettings { @synchronized(kHostCache) { kHostCache = [NSMutableDictionary dictionary]; } } -- (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path - serverName:(NSString *)serverName - timeout:(NSTimeInterval)timeout - completionQueue:(GRPCCompletionQueue *)queue { - // The __block attribute is to allow channel take refcount inside @synchronized block. Without - // this attribute, retain of channel object happens after objc_sync_exit in release builds, which - // may result in channel released before used. See grpc/#15033. - __block GRPCChannel *channel; - // This is racing -[GRPCHost disconnect]. - @synchronized(self) { - if (!_channel) { - _channel = [self newChannel]; - } - channel = _channel; - } - return [channel unmanagedCallWithPath:path - serverName:serverName - timeout:timeout - completionQueue:queue]; -} - -- (NSData *)nullTerminatedDataWithString:(NSString *)string { - // dataUsingEncoding: does not return a null-terminated string. - NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; - NSMutableData *nullTerminated = [NSMutableData dataWithData:data]; - [nullTerminated appendBytes:"\0" length:1]; - return nullTerminated; -} - - (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts withPrivateKey:(nullable NSString *)pemPrivateKey withCertChain:(nullable NSString *)pemCertChain error:(NSError **)errorPtr { - static NSData *kDefaultRootsASCII; - 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. - 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]; - if (contentInUTF8 == nil) { - kDefaultRootsError = error; - return; - } - kDefaultRootsASCII = [self nullTerminatedDataWithString:contentInUTF8]; - }); - - NSData *rootsASCII; - if (pemRootCerts != nil) { - rootsASCII = [self nullTerminatedDataWithString:pemRootCerts]; - } else { - if (kDefaultRootsASCII == 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); - return NO; - } - rootsASCII = kDefaultRootsASCII; - } - - grpc_channel_credentials *creds; - if (pemPrivateKey == nil && pemCertChain == nil) { - creds = grpc_ssl_credentials_create(rootsASCII.bytes, NULL, NULL, NULL); - } else { - grpc_ssl_pem_key_cert_pair key_cert_pair; - NSData *privateKeyASCII = [self nullTerminatedDataWithString:pemPrivateKey]; - NSData *certChainASCII = [self nullTerminatedDataWithString:pemCertChain]; - 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, NULL); - } - - @synchronized(self) { - if (_channelCreds != nil) { - grpc_channel_credentials_release(_channelCreds); - } - _channelCreds = creds; - } - + _pemRootCerts = pemRootCerts; + _pemPrivateKey = pemPrivateKey; + _pemCertChain = pemCertChain; return YES; } -- (NSDictionary *)channelArgsUsingCronet:(BOOL)useCronet { - 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 ). - NSString *userAgent = @"grpc-objc/" GRPC_OBJC_VERSION_STRING; - if (_userAgentPrefix) { - userAgent = [_userAgentPrefix stringByAppendingFormat:@" %@", userAgent]; - } - args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = userAgent; - - if (_secure && _hostNameOverride) { - args[@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG] = _hostNameOverride; - } - - if (_responseSizeLimitOverride) { - args[@GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH] = _responseSizeLimitOverride; - } - - if (_compressAlgorithm != GRPC_COMPRESS_NONE) { - args[@GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM] = [NSNumber numberWithInt:_compressAlgorithm]; - } - - if (_keepaliveInterval != 0) { - args[@GRPC_ARG_KEEPALIVE_TIME_MS] = [NSNumber numberWithInt:_keepaliveInterval]; - args[@GRPC_ARG_KEEPALIVE_TIMEOUT_MS] = [NSNumber numberWithInt:_keepaliveTimeout]; - } - - id logContext = self.logContext; - if (logContext != nil) { - args[@GRPC_ARG_MOBILE_LOG_CONTEXT] = logContext; - } - - if (useCronet) { - args[@GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER] = [NSNumber numberWithInt:1]; - } - - if (_retryEnabled == NO) { - args[@GRPC_ARG_ENABLE_RETRIES] = [NSNumber numberWithInt:0]; - } - - if (_minConnectTimeout > 0) { - args[@GRPC_ARG_MIN_RECONNECT_BACKOFF_MS] = [NSNumber numberWithInt:_minConnectTimeout]; - } - if (_initialConnectBackoff > 0) { - args[@GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS] = [NSNumber numberWithInt:_initialConnectBackoff]; - } - if (_maxConnectBackoff > 0) { - args[@GRPC_ARG_MAX_RECONNECT_BACKOFF_MS] = [NSNumber numberWithInt:_maxConnectBackoff]; - } - - return args; -} - -- (GRPCChannel *)newChannel { - BOOL useCronet = NO; -#ifdef GRPC_COMPILE_WITH_CRONET - useCronet = [GRPCCall isUsingCronet]; -#endif - NSDictionary *args = [self channelArgsUsingCronet:useCronet]; - if (_secure) { - GRPCChannel *channel; - @synchronized(self) { - if (_channelCreds == nil) { - [self setTLSPEMRootCerts:nil withPrivateKey:nil withCertChain:nil error:nil]; - } -#ifdef GRPC_COMPILE_WITH_CRONET - if (useCronet) { - channel = [GRPCChannel secureCronetChannelWithHost:_address channelArgs:args]; - } else -#endif - { - channel = - [GRPCChannel secureChannelWithHost:_address credentials:_channelCreds channelArgs:args]; - } - } - return channel; - } else { - return [GRPCChannel insecureChannelWithHost:_address channelArgs:args]; - } -} - -- (NSString *)hostName { - // TODO(jcanizales): Default to nil instead of _address when Issue #2635 is clarified. - return _hostNameOverride ?: _address; +- (GRPCCallOptions *)callOptions { + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.userAgentPrefix = _userAgentPrefix; + options.responseSizeLimit = _responseSizeLimitOverride; + options.compressAlgorithm = (GRPCCompressAlgorithm)_compressAlgorithm; + options.enableRetry = _retryEnabled; + options.keepaliveInterval = (NSTimeInterval)_keepaliveInterval / 1000; + options.keepaliveTimeout = (NSTimeInterval)_keepaliveTimeout / 1000; + options.connectMinTimeout = (NSTimeInterval)_minConnectTimeout / 1000; + options.connectInitialBackoff = (NSTimeInterval)_initialConnectBackoff / 1000; + options.connectMaxBackoff = (NSTimeInterval)_maxConnectBackoff / 1000; + options.pemRootCert = _pemRootCerts; + options.pemPrivateKey = _pemPrivateKey; + options.pemCertChain = _pemCertChain; + options.hostNameOverride = _hostNameOverride; + options.transportType = _transportType; + options.logContext = _logContext; + + return options; } -- (void)disconnect { - // This is racing -[GRPCHost unmanagedCallWithPath:completionQueue:]. - @synchronized(self) { - _channel = nil; ++ (BOOL)isHostConfigured:(NSString *)address { + // TODO (mxyan): Remove when old API is deprecated + NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:address]]; + if (hostURL.host && !hostURL.port) { + address = [hostURL.host stringByAppendingString:@":443"]; } -} - -// Flushes the host cache when connectivity status changes or when connection switch between Wifi -// and Cellular data, so that a new call will use a new channel. Otherwise, a new call will still -// use the cached channel which is no longer available and will cause gRPC to hang. -- (void)connectivityChange:(NSNotification *)note { - [self disconnect]; + GRPCHost *cachedHost = kHostCache[address]; + return (cachedHost != nil); } @end diff --git a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h new file mode 100644 index 00000000000..905a181ca78 --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h @@ -0,0 +1,35 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#import "GRPCChannelFactory.h" + +@class GRPCChannel; + +NS_ASSUME_NONNULL_BEGIN + +@interface GRPCInsecureChannelFactory : NSObject + ++ (nullable instancetype)sharedInstance; + +- (nullable grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(nullable NSMutableDictionary *)args; + +- (nullable instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m new file mode 100644 index 00000000000..41860bf6ff5 --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m @@ -0,0 +1,48 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import "GRPCInsecureChannelFactory.h" + +#import "ChannelArgsUtil.h" +#import "GRPCChannel.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation GRPCInsecureChannelFactory + ++ (nullable instancetype)sharedInstance { + static GRPCInsecureChannelFactory *instance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + }); + return instance; +} + +- (nullable grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(nullable NSMutableDictionary *)args { + grpc_channel_args *coreChannelArgs = BuildChannelArgs([args copy]); + grpc_channel *unmanagedChannel = + grpc_insecure_channel_create(host.UTF8String, coreChannelArgs, NULL); + FreeChannelArgs(coreChannelArgs); + return unmanagedChannel; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h new file mode 100644 index 00000000000..ab5eee478e1 --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h @@ -0,0 +1,38 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#import "GRPCChannelFactory.h" + +@class GRPCChannel; + +NS_ASSUME_NONNULL_BEGIN + +@interface GRPCSecureChannelFactory : NSObject + ++ (nullable instancetype)factoryWithPEMRootCerts:(nullable NSString *)rootCerts + privateKey:(nullable NSString *)privateKey + certChain:(nullable NSString *)certChain + error:(NSError **)errorPtr; + +- (nullable grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(nullable NSMutableDictionary *)args; + +- (nullable instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m new file mode 100644 index 00000000000..a0d56e4bdc7 --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -0,0 +1,129 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import "GRPCSecureChannelFactory.h" + +#include + +#import "ChannelArgsUtil.h" +#import "GRPCChannel.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation GRPCSecureChannelFactory { + grpc_channel_credentials *_channelCreds; +} + ++ (nullable instancetype)factoryWithPEMRootCerts:(nullable NSString *)rootCerts + privateKey:(nullable NSString *)privateKey + certChain:(nullable NSString *)certChain + error:(NSError **)errorPtr { + return [[self alloc] initWithPEMRootCerts:rootCerts + privateKey:privateKey + certChain:certChain + error:errorPtr]; +} + +- (NSData *)nullTerminatedDataWithString:(NSString *)string { + // dataUsingEncoding: does not return a null-terminated string. + NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; + NSMutableData *nullTerminated = [NSMutableData dataWithData:data]; + [nullTerminated appendBytes:"\0" length:1]; + return nullTerminated; +} + +- (nullable instancetype)initWithPEMRootCerts:(nullable NSString *)rootCerts + privateKey:(nullable NSString *)privateKey + certChain:(nullable NSString *)certChain + error:(NSError **)errorPtr { + static NSData *kDefaultRootsASCII; + 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. + 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]; + if (contentInUTF8 == nil) { + kDefaultRootsError = error; + return; + } + kDefaultRootsASCII = [self nullTerminatedDataWithString:contentInUTF8]; + }); + + NSData *rootsASCII; + if (rootCerts != nil) { + rootsASCII = [self nullTerminatedDataWithString:rootCerts]; + } else { + if (kDefaultRootsASCII == 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); + return nil; + } + rootsASCII = kDefaultRootsASCII; + } + + grpc_channel_credentials *creds; + if (privateKey == nil && certChain == nil) { + creds = grpc_ssl_credentials_create(rootsASCII.bytes, NULL, NULL, NULL); + } else { + grpc_ssl_pem_key_cert_pair key_cert_pair; + NSData *privateKeyASCII = [self nullTerminatedDataWithString:privateKey]; + NSData *certChainASCII = [self nullTerminatedDataWithString:certChain]; + 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, NULL); + } + + if ((self = [super init])) { + _channelCreds = creds; + } + return self; +} + +- (nullable grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(nullable NSMutableArray *)args { + grpc_channel_args *coreChannelArgs = BuildChannelArgs([args copy]); + grpc_channel *unmanagedChannel = + grpc_secure_channel_create(_channelCreds, host.UTF8String, coreChannelArgs, NULL); + FreeChannelArgs(coreChannelArgs); + return unmanagedChannel; +} + +- (void)dealloc { + if (_channelCreds != nil) { + grpc_channel_credentials_release(_channelCreds); + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h index f711850c2f0..19aa5367c77 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h @@ -74,9 +74,8 @@ @interface GRPCWrappedCall : NSObject - (instancetype)initWithHost:(NSString *)host - serverName:(NSString *)serverName path:(NSString *)path - timeout:(NSTimeInterval)timeout NS_DESIGNATED_INITIALIZER; + callOptions:(GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; - (void)startBatchWithOperations:(NSArray *)ops errorHandler:(void (^)(void))errorHandler; diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 7781d27ca4f..1c03bc9efdd 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -23,6 +23,7 @@ #include #include +#import "GRPCChannel.h" #import "GRPCCompletionQueue.h" #import "GRPCHost.h" #import "NSData+GRPC.h" @@ -235,31 +236,28 @@ @implementation GRPCWrappedCall { GRPCCompletionQueue *_queue; + GRPCChannel *_channel; grpc_call *_call; } - (instancetype)init { - return [self initWithHost:nil serverName:nil path:nil timeout:0]; + return [self initWithHost:nil path:nil callOptions:[[GRPCCallOptions alloc] init]]; } - (instancetype)initWithHost:(NSString *)host - serverName:(NSString *)serverName path:(NSString *)path - timeout:(NSTimeInterval)timeout { + callOptions:(GRPCCallOptions *)callOptions { if (!path || !host) { [NSException raise:NSInvalidArgumentException format:@"path and host cannot be nil."]; } - if (self = [super init]) { + 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. _queue = [GRPCCompletionQueue completionQueue]; - - _call = [[GRPCHost hostWithAddress:host] unmanagedCallWithPath:path - serverName:serverName - timeout:timeout - completionQueue:_queue]; + _channel = [GRPCChannel channelWithHost:host callOptions:callOptions]; + _call = [_channel unmanagedCallWithPath:path completionQueue:_queue callOptions:callOptions]; if (_call == NULL) { return nil; } @@ -313,6 +311,8 @@ - (void)dealloc { grpc_call_unref(_call); + [_channel unmanagedCallUnref]; + _channel = nil; } @end From 21c32e8f013986d6b120c852b34e058c82a4cf6d Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 10 Oct 2018 16:33:41 -0700 Subject: [PATCH 006/375] Remove redundant forward declaration --- src/objective-c/GRPCClient/GRPCCall.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 3f6ec75c04e..f396ffe599c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -39,8 +39,6 @@ #include "GRPCCallOptions.h" -@class GRPCCallOptions; - #pragma mark gRPC errors /** Domain of NSError objects produced by gRPC. */ From 553664f59bc947d48c73e6c1976e054fe35147f5 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 10 Oct 2018 16:34:21 -0700 Subject: [PATCH 007/375] Make dispatcheQueue of responseHandler required --- src/objective-c/GRPCClient/GRPCCall.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index f396ffe599c..64a6df3134c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -150,14 +150,18 @@ extern id const kGRPCTrailersKey; /** An object can implement this protocol to receive responses from server from a call. */ @protocol GRPCResponseHandler + @optional + /** Issued when initial metadata is received from the server. */ - (void)receivedInitialMetadata:(NSDictionary *)initialMetadata; + /** * Issued when a message is received from the server. The message may be raw data from the server * (when using \a GRPCCall2 directly) or deserialized proto object (when using \a ProtoRPC). */ - (void)receivedMessage:(id)message; + /** * Issued when a call finished. If the call finished successfully, \a error is nil and \a * trainingMetadata consists any trailing metadata received from the server. Otherwise, \a error @@ -166,9 +170,13 @@ extern id const kGRPCTrailersKey; */ - (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error; +@required + /** * All the responses must be issued to a user-provided dispatch queue. This property specifies the - * dispatch queue to be used for issuing the notifications. + * dispatch queue to be used for issuing the notifications. A serial queue should be provided if + * the order of responses (initial metadata, message, message, ..., message, trailing metadata) + * needs to be maintained. */ @property(atomic, readonly) dispatch_queue_t dispatchQueue; From 5715719afb061feb3c7de931cc8e7126bc9560e5 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 10 Oct 2018 16:36:09 -0700 Subject: [PATCH 008/375] Make multiple -init and +new UNAVAILABLE; identify designated initializer --- src/objective-c/GRPCClient/GRPCCall.h | 6 +++++- src/objective-c/ProtoRPC/ProtoRPC.h | 12 ++++++++++-- src/objective-c/ProtoRPC/ProtoService.h | 4 ++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 64a6df3134c..2ee181b93ba 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -190,8 +190,10 @@ extern id const kGRPCTrailersKey; - (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + /** Initialize with all properties. */ -- (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety; +- (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety NS_DESIGNATED_INITIALIZER; /** The host serving the RPC service. */ @property(copy, readonly) NSString *host; @@ -214,6 +216,8 @@ extern id const kGRPCTrailersKey; - (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + /** * Designated initializer for a call. * \param requestOptions Protobuf generated parameters for the call. diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 1a27cac2a32..a045ef10a6c 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -26,6 +26,10 @@ /** A unary-request RPC call with Protobuf. */ @interface GRPCUnaryProtoCall : NSObject +- (instancetype)init NS_UNAVAILABLE; + ++ (instancetype)new NS_UNAVAILABLE; + /** * Users should not use this initializer directly. Call objects will be created, initialized, and * returned to users by methods of the generated service. @@ -34,7 +38,7 @@ message:(GPBMessage *)message responseHandler:(id)handler callOptions:(GRPCCallOptions *)callOptions - responseClass:(Class)responseClass; + responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; /** Cancel the call at best effort. */ - (void)cancel; @@ -44,6 +48,10 @@ /** A client-streaming RPC call with Protobuf. */ @interface GRPCStreamingProtoCall : NSObject +- (instancetype)init NS_UNAVAILABLE; + ++ (instancetype)new NS_UNAVAILABLE; + /** * Users should not use this initializer directly. Call objects will be created, initialized, and * returned to users by methods of the generated service. @@ -51,7 +59,7 @@ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)handler callOptions:(GRPCCallOptions *)callOptions - responseClass:(Class)responseClass; + responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; /** Cancel the call at best effort. */ - (void)cancel; diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h index 2105de78a38..2985c5cb2dc 100644 --- a/src/objective-c/ProtoRPC/ProtoService.h +++ b/src/objective-c/ProtoRPC/ProtoService.h @@ -30,6 +30,10 @@ __attribute__((deprecated("Please use GRPCProtoService."))) @interface ProtoService : NSObject +- (instancetype)init NS_UNAVAILABLE; + ++ (instancetype)new NS_UNAVAILABLE; + - (instancetype)initWithHost : (NSString *)host packageName : (NSString *)packageName serviceName : (NSString *)serviceName callOptions From 0865a6098880b91235348cb9ffe49ddbb13ebdc6 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 10 Oct 2018 16:37:08 -0700 Subject: [PATCH 009/375] Typo and doc fix --- src/objective-c/GRPCClient/GRPCCall.h | 3 ++- src/objective-c/GRPCClient/GRPCCallOptions.m | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 2ee181b93ba..01d04807cc6 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -228,7 +228,8 @@ extern id const kGRPCTrailersKey; handler:(id)handler callOptions:(GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; /** - * Convevience initializer for a call that uses default call options. + * Convenience initializer for a call that uses default call options (see GRPCCallOptions.m for + * the default options). */ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions handler:(id)handler; diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index ee76c2a6420..072b980af42 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -18,6 +18,7 @@ #import "GRPCCallOptions.h" +// The default values for the call options. static NSString *const kDefaultServerAuthority = nil; static const NSTimeInterval kDefaultTimeout = 0; static NSDictionary *const kDefaultInitialMetadata = nil; From efa359b02b0122c90decfbcd5e1659198b565b4e Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 10 Oct 2018 16:50:12 -0700 Subject: [PATCH 010/375] Rename handler->responseHandler in function signature --- src/objective-c/GRPCClient/GRPCCall.h | 6 +++--- src/objective-c/GRPCClient/GRPCCall.m | 8 ++++---- src/objective-c/ProtoRPC/ProtoRPC.m | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 01d04807cc6..8554860aded 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -221,18 +221,18 @@ extern id const kGRPCTrailersKey; /** * Designated initializer for a call. * \param requestOptions Protobuf generated parameters for the call. - * \param handler The object to which responses should be issed. + * \param responseHandler The object to which responses should be issed. * \param callOptions Options for the call. */ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions - handler:(id)handler + responseHandler:(id)responseHandler callOptions:(GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; /** * Convenience initializer for a call that uses default call options (see GRPCCallOptions.m for * the default options). */ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions - handler:(id)handler; + responseHandler:(id)responseHandler; /** * Starts the call. Can only be called once. diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 519f91e5229..6eb9e2e4066 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -95,7 +95,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions - handler:(id)handler + responseHandler:(id)responseHandler callOptions:(GRPCCallOptions *)callOptions { if (!requestOptions || !requestOptions.host || !requestOptions.path) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; @@ -104,7 +104,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; if ((self = [super init])) { _requestOptions = [requestOptions copy]; _callOptions = [callOptions copy]; - _handler = handler; + _handler = responseHandler; _initialMetadataPublished = NO; _pipe = [GRXBufferedPipe pipe]; _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); @@ -114,8 +114,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions - handler:(id)handler { - return [self initWithRequestOptions:requestOptions handler:handler callOptions:nil]; + responseHandler:(id)responseHandler { + return [self initWithRequestOptions:requestOptions responseHandler:responseHandler callOptions:nil]; } - (void)start { diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index f89c1606507..34fd54a2162 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -86,7 +86,7 @@ - (void)start { _call = [[GRPCCall2 alloc] initWithRequestOptions:_requestOptions - handler:self + responseHandler:self callOptions:_callOptions]; [_call start]; } From eab498bef453e221abd4602e6ceff16da659b3c1 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 10 Oct 2018 16:44:00 -0700 Subject: [PATCH 011/375] Handle GRPCCall2:start: twice --- src/objective-c/GRPCClient/GRPCCall.h | 2 +- src/objective-c/GRPCClient/GRPCCall.m | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 8554860aded..5f6afab08cb 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -235,7 +235,7 @@ extern id const kGRPCTrailersKey; responseHandler:(id)responseHandler; /** - * Starts the call. Can only be called once. + * Starts the call. This function should only be called once; additional calls will be discarded. */ - (void)start; diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 6eb9e2e4066..9cb4aa34c24 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -92,6 +92,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; BOOL _initialMetadataPublished; GRXBufferedPipe *_pipe; dispatch_queue_t _dispatchQueue; + bool _started; } - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions @@ -108,6 +109,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; _initialMetadataPublished = NO; _pipe = [GRXBufferedPipe pipe]; _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + _started = NO; } return self; @@ -120,6 +122,10 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)start { dispatch_async(_dispatchQueue, ^{ + if (self->_started) { + return; + } + self->_started = YES; if (!self->_callOptions) { self->_callOptions = [[GRPCCallOptions alloc] init]; } From fe8a899b631b3fd804b59ca32639ef2a14bb597f Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 10 Oct 2018 16:56:00 -0700 Subject: [PATCH 012/375] Rename writeWithData to writeData --- src/objective-c/GRPCClient/GRPCCall.h | 2 +- src/objective-c/GRPCClient/GRPCCall.m | 2 +- src/objective-c/ProtoRPC/ProtoRPC.m | 2 +- src/objective-c/tests/GRPCClientTests.m | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 5f6afab08cb..c8f3919a633 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -249,7 +249,7 @@ extern id const kGRPCTrailersKey; /** * Send a message to the server. Data are sent as raw bytes in gRPC message frames. */ -- (void)writeWithData:(NSData *)data; +- (void)writeData:(NSData *)data; /** * Finish the RPC request and half-close the call. The server may still send messages and/or diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 9cb4aa34c24..7fdc8fcac26 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -206,7 +206,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; }); } -- (void)writeWithData:(NSData *)data { +- (void)writeData:(NSData *)data { dispatch_async(_dispatchQueue, ^{ [self->_pipe writeValue:data]; }); diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 34fd54a2162..957d6365341 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -120,7 +120,7 @@ dispatch_async(_dispatchQueue, ^{ if (_call) { - [_call writeWithData:[message data]]; + [_call writeData:[message data]]; } }); } diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index bad22d30cbb..db7265c7120 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -332,7 +332,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; callOptions:options]; [call start]; - [call writeWithData:[request data]]; + [call writeData:[request data]]; [call finish]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; @@ -495,7 +495,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; } }] callOptions:options]; - [call writeWithData:[NSData data]]; + [call writeData:[NSData data]]; [call start]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; @@ -632,7 +632,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; callOptions:options]; [call start]; - [call writeWithData:[request data]]; + [call writeData:[request data]]; [call finish]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; From 50dac6721425b225e3e031251c7eb888ec61f07e Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 10 Oct 2018 18:09:01 -0700 Subject: [PATCH 013/375] Update GRPCCall2:cancel: docs --- src/objective-c/GRPCClient/GRPCCall.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index c8f3919a633..354bdb7cfa2 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -240,9 +240,9 @@ extern id const kGRPCTrailersKey; - (void)start; /** - * Cancel the request of this call at best effort; notifies the server that the RPC should be - * cancelled, and issue callback to the user with an error code CANCELED if the call is not - * finished. + * Cancel the request of this call at best effort. It attempts to notify the server that the RPC + * should be cancelled, and issue closedWithTrailingMetadata:error: callback with error code + * CANCELED if no other error code has already been issued. */ - (void)cancel; From 161dc27b2d3882ab3f8a8bcc26733a729e034583 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 10 Oct 2018 18:09:42 -0700 Subject: [PATCH 014/375] Copy string fix --- src/objective-c/GRPCClient/GRPCCall.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 7fdc8fcac26..c0413ec6c2d 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -68,8 +68,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety { if ((self = [super init])) { - _host = host; - _path = path; + _host = [host copy]; + _path = [path copy]; _safety = safety; } return self; @@ -77,7 +77,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (id)copyWithZone:(NSZone *)zone { GRPCRequestOptions *request = - [[GRPCRequestOptions alloc] initWithHost:[_host copy] path:[_path copy] safety:_safety]; + [[GRPCRequestOptions alloc] initWithHost:_host path:_path safety:_safety]; return request; } From 413077101eab400635732b813da4f1e4a5b69c5a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 10 Oct 2018 18:10:21 -0700 Subject: [PATCH 015/375] requestOptions precondition check polishing --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index c0413ec6c2d..c9ee5084868 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -98,7 +98,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)responseHandler callOptions:(GRPCCallOptions *)callOptions { - if (!requestOptions || !requestOptions.host || !requestOptions.path) { + if (requestOptions.host.length == 0 || requestOptions.path.length == 0) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; } From f18b08a1a4454f8232c2815f0110427c1a86878f Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 10 Oct 2018 18:55:28 -0700 Subject: [PATCH 016/375] Check if optional method of GRPCCallOptions are implemented --- src/objective-c/GRPCClient/GRPCCall.h | 2 +- src/objective-c/GRPCClient/GRPCCall.m | 32 ++++++++++++++++++--------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 354bdb7cfa2..304fb17cca5 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -149,7 +149,7 @@ extern id const kGRPCHeadersKey; extern id const kGRPCTrailersKey; /** An object can implement this protocol to receive responses from server from a call. */ -@protocol GRPCResponseHandler +@protocol GRPCResponseHandler @optional diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index c9ee5084868..e1039a1b2a7 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -149,12 +149,16 @@ const char *kCFStreamVarName = "grpc_cfstream"; } if (headers) { dispatch_async(handler.dispatchQueue, ^{ - [handler receivedInitialMetadata:headers]; + if ([handler respondsToSelector:@selector(receivedInitialMetadata:)]) { + [handler receivedInitialMetadata:headers]; + } }); } if (value) { dispatch_async(handler.dispatchQueue, ^{ - [handler receivedMessage:value]; + if ([handler respondsToSelector:@selector(receivedMessage:)]) { + [handler receivedMessage:value]; + } }); } } @@ -171,11 +175,15 @@ const char *kCFStreamVarName = "grpc_cfstream"; } if (headers) { dispatch_async(handler.dispatchQueue, ^{ - [handler receivedInitialMetadata:headers]; + if ([handler respondsToSelector:@selector(receivedInitialMetadata:)]) { + [handler receivedInitialMetadata:headers]; + } }); } dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:self->_call.responseTrailers error:errorOrNil]; + if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + [handler closedWithTrailingMetadata:self->_call.responseTrailers error:errorOrNil]; + } }); } }); @@ -193,13 +201,15 @@ const char *kCFStreamVarName = "grpc_cfstream"; if (self->_handler) { id handler = self->_handler; dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:nil - error:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeCancelled - userInfo:@{ - NSLocalizedDescriptionKey : - @"Canceled by app" - }]]; + if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + [handler closedWithTrailingMetadata:nil + error:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeCancelled + userInfo:@{ + NSLocalizedDescriptionKey : + @"Canceled by app" + }]]; + } }); self->_handler = nil; } From 7b08066d8ff5cca57ee6eaa4cae014d07e4aa8e1 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 10:56:51 -0700 Subject: [PATCH 017/375] Fix CI failures --- src/objective-c/tests/GRPCClientTests.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index db7265c7120..8a4eddb1b70 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -306,7 +306,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; options.oauth2AccessToken = @"bogusToken"; GRPCCall2 *call = [[GRPCCall2 alloc] initWithRequestOptions:callRequest - handler:[[ClientTestsBlockCallbacks alloc] + responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { init_md = initialMetadata; } @@ -446,7 +446,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; options.initialMetadata = headers; GRPCCall2 *call = [[GRPCCall2 alloc] initWithRequestOptions:request - handler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:^( + responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:^( NSDictionary *initialMetadata) { NSString *userAgent = initialMetadata[@"x-grpc-test-echo-useragent"]; // Test the regex is correct @@ -609,7 +609,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; options.transportType = GRPCTransportTypeInsecure; GRPCCall2 *call = [[GRPCCall2 alloc] initWithRequestOptions:requestOptions - handler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil messageCallback:^(id message) { NSData *data = (NSData *)message; XCTAssertNotNil(data, @"nil value received as response."); @@ -739,7 +739,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; GRPCCall2 *call = [[GRPCCall2 alloc] initWithRequestOptions:requestOptions - handler: + responseHandler: [[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil messageCallback:^(id data) { XCTFail( @@ -835,9 +835,9 @@ static GRPCProtoMethod *kFullDuplexCallMethod; const double kMargin = 0.1; __weak XCTestExpectation *completion = [self expectationWithDescription:@"Timeout in a second."]; - NSString *const kDummyAddress = [NSString stringWithFormat:@"8.8.8.8:1"]; + NSString *const kDummyAddress = [NSString stringWithFormat:@"127.0.0.1:10000"]; GRPCRequestOptions *requestOptions = - [[GRPCRequestOptions alloc] initWithHost:kDummyAddress path:@"" safety:GRPCCallSafetyDefault]; + [[GRPCRequestOptions alloc] initWithHost:kDummyAddress path:@"/dummy/path" safety:GRPCCallSafetyDefault]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; options.connectMinTimeout = timeout; options.connectInitialBackoff = backoff; @@ -846,7 +846,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; NSDate *startTime = [NSDate date]; GRPCCall2 *call = [[GRPCCall2 alloc] initWithRequestOptions:requestOptions - handler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil messageCallback:^(id data) { XCTFail(@"Received message. Should not reach here."); } From 5d16c2ff92eb49319d9028cbe99bb80bf41e0578 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 11:20:26 -0700 Subject: [PATCH 018/375] Move issuance of response in helper functions --- src/objective-c/GRPCClient/GRPCCall.m | 54 ++++++++++++++++----------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index e1039a1b2a7..1e9bc41b41b 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -141,25 +141,16 @@ const char *kCFStreamVarName = "grpc_cfstream"; id responseWriteable = [[GRXWriteable alloc] initWithValueHandler:^(id value) { dispatch_async(self->_dispatchQueue, ^{ if (self->_handler) { - id handler = self->_handler; NSDictionary *headers = nil; if (!self->_initialMetadataPublished) { headers = self->_call.responseHeaders; self->_initialMetadataPublished = YES; } if (headers) { - dispatch_async(handler.dispatchQueue, ^{ - if ([handler respondsToSelector:@selector(receivedInitialMetadata:)]) { - [handler receivedInitialMetadata:headers]; - } - }); + [self issueInitialMetadata:headers]; } if (value) { - dispatch_async(handler.dispatchQueue, ^{ - if ([handler respondsToSelector:@selector(receivedMessage:)]) { - [handler receivedMessage:value]; - } - }); + [self issueMessage:value]; } } }); @@ -167,24 +158,15 @@ const char *kCFStreamVarName = "grpc_cfstream"; completionHandler:^(NSError *errorOrNil) { dispatch_async(self->_dispatchQueue, ^{ if (self->_handler) { - id handler = self->_handler; NSDictionary *headers = nil; if (!self->_initialMetadataPublished) { headers = self->_call.responseHeaders; self->_initialMetadataPublished = YES; } if (headers) { - dispatch_async(handler.dispatchQueue, ^{ - if ([handler respondsToSelector:@selector(receivedInitialMetadata:)]) { - [handler receivedInitialMetadata:headers]; - } - }); + [self issueInitialMetadata:headers]; } - dispatch_async(handler.dispatchQueue, ^{ - if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - [handler closedWithTrailingMetadata:self->_call.responseTrailers error:errorOrNil]; - } - }); + [self issueClosedWithTrailingMetadata:self->_call.responseTrailers error:errorOrNil]; } }); }]; @@ -230,6 +212,34 @@ const char *kCFStreamVarName = "grpc_cfstream"; }); } +- (void)issueInitialMetadata:(NSDictionary *)initialMetadata { + id handler = self->_handler; + if ([handler respondsToSelector:@selector(receivedInitialMetadata:)]) { + dispatch_async(handler.dispatchQueue, ^{ + [handler receivedInitialMetadata:initialMetadata]; + }); + } +} + +- (void)issueMessage:(id)message { + id handler = self->_handler; + if ([handler respondsToSelector:@selector(receivedMessage:)]) { + dispatch_async(handler.dispatchQueue, ^{ + [handler receivedMessage:message]; + }); + } +} + +- (void)issueClosedWithTrailingMetadata:(NSDictionary *)trailingMetadata + error:(NSError *)error { + id handler = self->_handler; + if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + dispatch_async(handler.dispatchQueue, ^{ + [handler closedWithTrailingMetadata:self->_call.responseTrailers error:error]; + }); + } +} + @end // The following methods of a C gRPC call object aren't reentrant, and thus From 92e81c80efb8d5dcbc6362206be09b2ef9107a2b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 11:33:27 -0700 Subject: [PATCH 019/375] Add comment on clearing GRPCCall2._handler --- src/objective-c/GRPCClient/GRPCCall.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 1e9bc41b41b..ace149fad5a 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -167,6 +167,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; [self issueInitialMetadata:headers]; } [self issueClosedWithTrailingMetadata:self->_call.responseTrailers error:errorOrNil]; + + // Clean up _handler so that no more responses are reported to the handler. + self->_handler = nil; } }); }]; @@ -193,6 +196,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; }]]; } }); + + // Clean up _handler so that no more responses are reported to the handler. self->_handler = nil; } }); From b634447d2cb762b47365218e1affd317a4ccd8b3 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 13:15:45 -0700 Subject: [PATCH 020/375] Resetting _call and _handler on finish --- src/objective-c/GRPCClient/GRPCCall.m | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index ace149fad5a..d0495f6cbf1 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -170,6 +170,13 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Clean up _handler so that no more responses are reported to the handler. self->_handler = nil; + + // If server terminated the call we should close the send path too. + if (self->_call) { + [self->_pipe writesFinishedWithError:nil]; + self->_call = nil; + self->_pipe = nil; + } } }); }]; @@ -182,6 +189,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; if (self->_call) { [self->_call cancel]; self->_call = nil; + self->_pipe = nil; } if (self->_handler) { id handler = self->_handler; @@ -214,6 +222,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; if (self->_call) { [self->_pipe writesFinishedWithError:nil]; } + self->_call = nil; + self->_pipe = nil; }); } From aabce5e19ca93c54fc0560116e0e8cb53dabdc19 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 13:16:09 -0700 Subject: [PATCH 021/375] Initialize flag --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index d0495f6cbf1..40db83155b4 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -541,7 +541,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)sendHeaders { // TODO (mxyan): Remove after deprecated methods are removed - uint32_t callSafetyFlags; + uint32_t callSafetyFlags = 0; switch (_callSafety) { case GRPCCallSafetyDefault: callSafetyFlags = 0; From fb9d054ac7da0cad67cb7431fc91823c7349df33 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 13:16:35 -0700 Subject: [PATCH 022/375] Check string length --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 40db83155b4..0f2c367331f 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -738,7 +738,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } else { callOptions = [[GRPCMutableCallOptions alloc] init]; } - if (_serverName != nil) { + if (_serverName.length != 0) { callOptions.serverAuthority = _serverName; } if (_timeout != 0) { From bca7e68ccbf15eab3d3a8a09d0e3d50d7db49cf9 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 13:17:40 -0700 Subject: [PATCH 023/375] use strong self for authTokenProvider --- src/objective-c/GRPCClient/GRPCCall.m | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 0f2c367331f..28d3b52d5e1 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -761,15 +761,13 @@ const char *kCFStreamVarName = "grpc_cfstream"; } if (_callOptions.authTokenProvider != nil) { self.isWaitingForToken = YES; - __weak typeof(self) weakSelf = self; [self.tokenProvider getTokenWithHandler:^(NSString *token) { - typeof(self) strongSelf = weakSelf; - if (strongSelf && strongSelf.isWaitingForToken) { + if (self.isWaitingForToken) { if (token) { - strongSelf->_fetchedOauth2AccessToken = token; + self->_fetchedOauth2AccessToken = [token copy]; } - [strongSelf startCallWithWriteable:writeable]; - strongSelf.isWaitingForToken = NO; + [self startCallWithWriteable:writeable]; + self.isWaitingForToken = NO; } }]; } else { From 8592dc27223e9ec41f4f52634f662c4485bd119b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 13:31:07 -0700 Subject: [PATCH 024/375] Rename GRPCTransportTypeDefault to GRPCTransportTypeChttp2CFStream --- src/objective-c/GRPCClient/GRPCCallOptions.h | 2 +- src/objective-c/GRPCClient/GRPCCallOptions.m | 2 +- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 2 +- src/objective-c/tests/ChannelTests/ChannelPoolTest.m | 2 +- src/objective-c/tests/ChannelTests/ChannelTests.m | 4 ++-- src/objective-c/tests/InteropTests.m | 2 +- src/objective-c/tests/InteropTestsLocalSSL.m | 2 +- .../InteropTestsMultipleChannels.m | 2 +- src/objective-c/tests/InteropTestsRemote.m | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 75b320ca6d6..1093044c0c8 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -42,7 +42,7 @@ typedef NS_ENUM(NSInteger, GRPCCompressAlgorithm) { // The transport to be used by a gRPC call typedef NS_ENUM(NSInteger, GRPCTransportType) { // gRPC internal HTTP/2 stack with BoringSSL - GRPCTransportTypeDefault = 0, + GRPCTransportTypeChttp2BoringSSL = 0, // Cronet stack GRPCTransportTypeCronet, // Insecure channel. FOR TEST ONLY! diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 072b980af42..0216342817b 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -37,7 +37,7 @@ static NSString *const kDefaultPemPrivateKey = nil; static NSString *const kDefaultPemCertChain = nil; static NSString *const kDefaultOauth2AccessToken = nil; static const id kDefaultAuthTokenProvider = nil; -static const GRPCTransportType kDefaultTransportType = GRPCTransportTypeDefault; +static const GRPCTransportType kDefaultTransportType = GRPCTransportTypeChttp2BoringSSL; static NSString *const kDefaultHostNameOverride = nil; static const id kDefaultLogContext = nil; static NSString *kDefaultChannelPoolDomain = nil; diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index b5f0949ef73..340f4f3c83e 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -49,7 +49,7 @@ const NSTimeInterval kChannelDestroyDelay = 30; id factory; GRPCTransportType type = _callOptions.transportType; switch (type) { - case GRPCTransportTypeDefault: + case GRPCTransportTypeChttp2BoringSSL: // TODO (mxyan): Remove when the API is deprecated #ifdef GRPC_COMPILE_WITH_CRONET if (![GRPCCall isUsingCronet]) { diff --git a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m index 3b6b10b1a5f..9e1c9eca746 100644 --- a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m +++ b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m @@ -127,7 +127,7 @@ NSString *kDummyHost = @"dummy.host"; GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; options1.transportType = GRPCTransportTypeInsecure; GRPCMutableCallOptions *options2 = [[GRPCMutableCallOptions alloc] init]; - options2.transportType = GRPCTransportTypeDefault; + options2.transportType = GRPCTransportTypeChttp2BoringSSL; GRPCChannelConfiguration *config1 = [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; GRPCChannelConfiguration *config2 = diff --git a/src/objective-c/tests/ChannelTests/ChannelTests.m b/src/objective-c/tests/ChannelTests/ChannelTests.m index 0a8b7ae6ee6..64c3356b13f 100644 --- a/src/objective-c/tests/ChannelTests/ChannelTests.m +++ b/src/objective-c/tests/ChannelTests/ChannelTests.m @@ -72,7 +72,7 @@ - (void)testDifferentChannelParameters { NSString *host = @"grpc-test.sandbox.googleapis.com"; GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; - options1.transportType = GRPCTransportTypeDefault; + options1.transportType = GRPCTransportTypeChttp2BoringSSL; NSMutableDictionary *args = [NSMutableDictionary new]; args[@"abc"] = @"xyz"; options1.additionalChannelArgs = [args copy]; @@ -80,7 +80,7 @@ options2.transportType = GRPCTransportTypeInsecure; options2.additionalChannelArgs = [args copy]; GRPCMutableCallOptions *options3 = [[GRPCMutableCallOptions alloc] init]; - options3.transportType = GRPCTransportTypeDefault; + options3.transportType = GRPCTransportTypeChttp2BoringSSL; args[@"def"] = @"uvw"; options3.additionalChannelArgs = [args copy]; GRPCChannel *channel1 = [GRPCChannel channelWithHost:host callOptions:options1]; diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 54af7036c35..16d5040a733 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -144,7 +144,7 @@ BOOL isRemoteInteropTest(NSString *host) { } + (GRPCTransportType)transportType { - return GRPCTransportTypeDefault; + return GRPCTransportTypeChttp2BoringSSL; } + (NSString *)pemRootCert { diff --git a/src/objective-c/tests/InteropTestsLocalSSL.m b/src/objective-c/tests/InteropTestsLocalSSL.m index eb72dd1d311..997dd87eeea 100644 --- a/src/objective-c/tests/InteropTestsLocalSSL.m +++ b/src/objective-c/tests/InteropTestsLocalSSL.m @@ -57,7 +57,7 @@ static int32_t kLocalInteropServerOverhead = 10; } + (GRPCTransportType)transportType { - return GRPCTransportTypeDefault; + return GRPCTransportTypeChttp2BoringSSL; } - (void)setUp { diff --git a/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m b/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m index eb0ba7f34b3..b1d663584c8 100644 --- a/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m +++ b/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m @@ -114,7 +114,7 @@ dispatch_once_t initCronet; XCTAssertNil(error); options = [[GRPCCallOptions alloc] init]; - options.transportType = GRPCTransportTypeDefault; + options.transportType = GRPCTransportTypeChttp2BoringSSL; options.pemRootCert = certs; options.hostNameOverride = @"foo.test.google.fr"; _localSSLService.options = options; diff --git a/src/objective-c/tests/InteropTestsRemote.m b/src/objective-c/tests/InteropTestsRemote.m index 516a1f432a5..30670facad0 100644 --- a/src/objective-c/tests/InteropTestsRemote.m +++ b/src/objective-c/tests/InteropTestsRemote.m @@ -59,7 +59,7 @@ static int32_t kRemoteInteropServerOverhead = 12; } #else + (GRPCTransportType)transportType { - return GRPCTransportTypeDefault; + return GRPCTransportTypeChttp2BoringSSL; } #endif From 96709ecb8cde75f2750d96dc288167292790eb5a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 13:34:24 -0700 Subject: [PATCH 025/375] Fix another NSString* != nil to NSString.length != 0 --- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 340f4f3c83e..2b08eb8d5e3 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -131,7 +131,7 @@ const NSTimeInterval kChannelDestroyDelay = 30; args[@GRPC_ARG_MOBILE_LOG_CONTEXT] = _callOptions.logContext; } - if (_callOptions.channelPoolDomain != nil) { + if (_callOptions.channelPoolDomain.length != 0) { args[@GRPC_ARG_CHANNEL_POOL_DOMAIN] = _callOptions.channelPoolDomain; } From 0d4ac971df9d2a795eac674e0a105d0c51f7387b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 13:45:43 -0700 Subject: [PATCH 026/375] Restrict NSTimeInterval parameters to non-negative --- src/objective-c/GRPCClient/GRPCCallOptions.h | 29 +++++++++------- src/objective-c/GRPCClient/GRPCCallOptions.m | 36 ++++++++++++++++---- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 1093044c0c8..70dd7741fd1 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -120,15 +120,15 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { */ @property(readonly) BOOL enableRetry; -/** - * HTTP/2 keep-alive feature. The parameter \a keepaliveInterval specifies the interval between two - * PING frames. The parameter \a keepaliveTimeout specifies the length of the period for which the - * call should wait for PING ACK. If PING ACK is not received after this period, the call fails. - */ +// HTTP/2 keep-alive feature. The parameter \a keepaliveInterval specifies the interval between two +// PING frames. The parameter \a keepaliveTimeout specifies the length of the period for which the +// call should wait for PING ACK. If PING ACK is not received after this period, the call fails. +// Negative values are not allowed. @property(readonly) NSTimeInterval keepaliveInterval; @property(readonly) NSTimeInterval keepaliveTimeout; -// Parameters for connection backoff. For details of gRPC's backoff behavior, refer to +// Parameters for connection backoff. Negative values are not allowed. +// For details of gRPC's backoff behavior, refer to // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md @property(readonly) NSTimeInterval connectMinTimeout; @property(readonly) NSTimeInterval connectInitialBackoff; @@ -203,7 +203,8 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { /** * The timeout for the RPC call in seconds. If set to 0, the call will not timeout. If set to * positive, the gRPC call returns with status GRPCErrorCodeDeadlineExceeded if it is not completed - * within \a timeout seconds. A negative value is not allowed. + * within \a timeout seconds. Negative value is invalid; setting the parameter to negative value + * will reset the parameter to 0. */ @property(readwrite) NSTimeInterval timeout; @@ -249,15 +250,17 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { */ @property(readwrite) BOOL enableRetry; -/** - * HTTP/2 keep-alive feature. The parameter \a keepaliveInterval specifies the interval between two - * PING frames. The parameter \a keepaliveTimeout specifies the length of the period for which the - * call should wait for PING ACK. If PING ACK is not received after this period, the call fails. - */ +// HTTP/2 keep-alive feature. The parameter \a keepaliveInterval specifies the interval between two +// PING frames. The parameter \a keepaliveTimeout specifies the length of the period for which the +// call should wait for PING ACK. If PING ACK is not received after this period, the call fails. +// Negative values are invalid; setting these parameters to negative value will reset the +// corresponding parameter to 0. @property(readwrite) NSTimeInterval keepaliveInterval; @property(readwrite) NSTimeInterval keepaliveTimeout; -// Parameters for connection backoff. For details of gRPC's backoff behavior, refer to +// Parameters for connection backoff. Negative value is invalid; setting the parameters to negative +// value will reset corresponding parameter to 0. +// For details of gRPC's backoff behavior, refer to // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md @property(readwrite) NSTimeInterval connectMinTimeout; @property(readwrite) NSTimeInterval connectInitialBackoff; diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 0216342817b..1f25df7d53b 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -342,7 +342,11 @@ static NSUInteger kDefaultChannelId = 0; } - (void)setTimeout:(NSTimeInterval)timeout { - _timeout = timeout; + if (timeout < 0) { + _timeout = 0; + } else { + _timeout = timeout; + } } - (void)setOauth2AccessToken:(NSString *)oauth2AccessToken { @@ -374,23 +378,43 @@ static NSUInteger kDefaultChannelId = 0; } - (void)setKeepaliveInterval:(NSTimeInterval)keepaliveInterval { - _keepaliveInterval = keepaliveInterval; + if (keepaliveInterval < 0) { + _keepaliveInterval = 0; + } else { + _keepaliveInterval = keepaliveInterval; + } } - (void)setKeepaliveTimeout:(NSTimeInterval)keepaliveTimeout { - _keepaliveTimeout = keepaliveTimeout; + if (keepaliveTimeout < 0) { + _keepaliveTimeout = 0; + } else { + _keepaliveTimeout = keepaliveTimeout; + } } - (void)setConnectMinTimeout:(NSTimeInterval)connectMinTimeout { - _connectMinTimeout = connectMinTimeout; + if (connectMinTimeout < 0) { + connectMinTimeout = 0; + } else { + _connectMinTimeout = connectMinTimeout; + } } - (void)setConnectInitialBackoff:(NSTimeInterval)connectInitialBackoff { - _connectInitialBackoff = connectInitialBackoff; + if (connectInitialBackoff < 0) { + _connectInitialBackoff = 0; + } else { + _connectInitialBackoff = connectInitialBackoff; + } } - (void)setConnectMaxBackoff:(NSTimeInterval)connectMaxBackoff { - _connectMaxBackoff = connectMaxBackoff; + if (connectMaxBackoff < 0) { + _connectMaxBackoff = 0; + } else { + _connectMaxBackoff = connectMaxBackoff; + } } - (void)setAdditionalChannelArgs:(NSDictionary *)additionalChannelArgs { From a397862fd56bca95da49062b7ca622a0823bc15a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 13:52:24 -0700 Subject: [PATCH 027/375] property attribute fixes --- src/objective-c/GRPCClient/GRPCCallOptions.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 70dd7741fd1..abfe3965115 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -64,7 +64,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { * :authority header field of the call and performs an extra check that server's certificate * matches the :authority header. */ -@property(readonly) NSString *serverAuthority; +@property(copy, readonly) NSString *serverAuthority; /** * The timeout for the RPC call in seconds. If set to 0, the call will not timeout. If set to @@ -91,7 +91,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { /** * Initial metadata key-value pairs that should be included in the request. */ -@property(copy, readwrite) NSDictionary *initialMetadata; +@property(copy, readonly) NSDictionary *initialMetadata; // Channel parameters; take into account of channel signature. @@ -198,7 +198,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { * :authority header field of the call and performs an extra check that server's certificate * matches the :authority header. */ -@property(readwrite) NSString *serverAuthority; +@property(copy, readwrite) NSString *serverAuthority; /** * The timeout for the RPC call in seconds. If set to 0, the call will not timeout. If set to From 2c1c22c3f1b9c0fe36589da691fbabc60ad1aa25 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 14:31:05 -0700 Subject: [PATCH 028/375] Do not nullify GRPCCall2._call on half-close --- src/objective-c/GRPCClient/GRPCCall.m | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 28d3b52d5e1..36cb71399ca 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -171,7 +171,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Clean up _handler so that no more responses are reported to the handler. self->_handler = nil; - // If server terminated the call we should close the send path too. if (self->_call) { [self->_pipe writesFinishedWithError:nil]; self->_call = nil; @@ -222,7 +221,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; if (self->_call) { [self->_pipe writesFinishedWithError:nil]; } - self->_call = nil; self->_pipe = nil; }); } @@ -247,10 +245,11 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)issueClosedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { - id handler = self->_handler; + id handler = _handler; + NSDictionary *trailers = _call.responseTrailers; if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:self->_call.responseTrailers error:error]; + [handler closedWithTrailingMetadata:trailers error:error]; }); } } From 0fc040d19acc960ed3ab331ed92b38b43d32a284 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 14:33:00 -0700 Subject: [PATCH 029/375] Rename pemXxx parameters to PEMXxx --- src/objective-c/GRPCClient/GRPCCallOptions.h | 12 +-- src/objective-c/GRPCClient/GRPCCallOptions.m | 84 +++++++++---------- .../GRPCClient/private/GRPCChannelPool.m | 24 +++--- src/objective-c/GRPCClient/private/GRPCHost.m | 14 ++-- src/objective-c/tests/InteropTests.h | 2 +- src/objective-c/tests/InteropTests.m | 8 +- .../tests/InteropTestsLocalCleartext.m | 2 +- src/objective-c/tests/InteropTestsLocalSSL.m | 2 +- .../InteropTestsMultipleChannels.m | 2 +- src/objective-c/tests/InteropTestsRemote.m | 2 +- 10 files changed, 76 insertions(+), 76 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index abfe3965115..ea7c1bf22db 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -146,17 +146,17 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { * PEM format root certifications that is trusted. If set to nil, gRPC uses a list of default * root certificates. */ -@property(copy, readonly) NSString *pemRootCert; +@property(copy, readonly) NSString *PEMRootCertificates; /** * PEM format private key for client authentication, if required by the server. */ -@property(copy, readonly) NSString *pemPrivateKey; +@property(copy, readonly) NSString *PEMPrivateKey; /** * PEM format certificate chain for client authentication, if required by the server. */ -@property(copy, readonly) NSString *pemCertChain; +@property(copy, readonly) NSString *PEMCertChain; /** * Select the transport type to be used for this call. @@ -278,17 +278,17 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { * PEM format root certifications that is trusted. If set to nil, gRPC uses a list of default * root certificates. */ -@property(copy, readwrite) NSString *pemRootCert; +@property(copy, readwrite) NSString *PEMRootCertificates; /** * PEM format private key for client authentication, if required by the server. */ -@property(copy, readwrite) NSString *pemPrivateKey; +@property(copy, readwrite) NSString *PEMPrivateKey; /** * PEM format certificate chain for client authentication, if required by the server. */ -@property(copy, readwrite) NSString *pemCertChain; +@property(copy, readwrite) NSString *PEMCertChain; /** * Select the transport type to be used for this call. diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 1f25df7d53b..539cb9929db 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -32,9 +32,9 @@ static const NSTimeInterval kDefaultConnectMinTimeout = 0; static const NSTimeInterval kDefaultConnectInitialBackoff = 0; static const NSTimeInterval kDefaultConnectMaxBackoff = 0; static NSDictionary *const kDefaultAdditionalChannelArgs = nil; -static NSString *const kDefaultPemRootCert = nil; -static NSString *const kDefaultPemPrivateKey = nil; -static NSString *const kDefaultPemCertChain = nil; +static NSString *const kDefaultPEMRootCertificates = nil; +static NSString *const kDefaultPEMPrivateKey = nil; +static NSString *const kDefaultPEMCertChain = nil; static NSString *const kDefaultOauth2AccessToken = nil; static const id kDefaultAuthTokenProvider = nil; static const GRPCTransportType kDefaultTransportType = GRPCTransportTypeChttp2BoringSSL; @@ -60,9 +60,9 @@ static NSUInteger kDefaultChannelId = 0; NSTimeInterval _connectInitialBackoff; NSTimeInterval _connectMaxBackoff; NSDictionary *_additionalChannelArgs; - NSString *_pemRootCert; - NSString *_pemPrivateKey; - NSString *_pemCertChain; + NSString *_PEMRootCertificates; + NSString *_PEMPrivateKey; + NSString *_PEMCertChain; GRPCTransportType _transportType; NSString *_hostNameOverride; id _logContext; @@ -85,9 +85,9 @@ static NSUInteger kDefaultChannelId = 0; @synthesize connectInitialBackoff = _connectInitialBackoff; @synthesize connectMaxBackoff = _connectMaxBackoff; @synthesize additionalChannelArgs = _additionalChannelArgs; -@synthesize pemRootCert = _pemRootCert; -@synthesize pemPrivateKey = _pemPrivateKey; -@synthesize pemCertChain = _pemCertChain; +@synthesize PEMRootCertificates = _PEMRootCertificates; +@synthesize PEMPrivateKey = _PEMPrivateKey; +@synthesize PEMCertChain = _PEMCertChain; @synthesize transportType = _transportType; @synthesize hostNameOverride = _hostNameOverride; @synthesize logContext = _logContext; @@ -110,9 +110,9 @@ static NSUInteger kDefaultChannelId = 0; connectInitialBackoff:kDefaultConnectInitialBackoff connectMaxBackoff:kDefaultConnectMaxBackoff additionalChannelArgs:kDefaultAdditionalChannelArgs - pemRootCert:kDefaultPemRootCert - pemPrivateKey:kDefaultPemPrivateKey - pemCertChain:kDefaultPemCertChain + PEMRootCertificates:kDefaultPEMRootCertificates + PEMPrivateKey:kDefaultPEMPrivateKey + PEMCertChain:kDefaultPEMCertChain transportType:kDefaultTransportType hostNameOverride:kDefaultHostNameOverride logContext:kDefaultLogContext @@ -135,9 +135,9 @@ static NSUInteger kDefaultChannelId = 0; connectInitialBackoff:(NSTimeInterval)connectInitialBackoff connectMaxBackoff:(NSTimeInterval)connectMaxBackoff additionalChannelArgs:(NSDictionary *)additionalChannelArgs - pemRootCert:(NSString *)pemRootCert - pemPrivateKey:(NSString *)pemPrivateKey - pemCertChain:(NSString *)pemCertChain + PEMRootCertificates:(NSString *)PEMRootCertificates + PEMPrivateKey:(NSString *)PEMPrivateKey + PEMCertChain:(NSString *)PEMCertChain transportType:(GRPCTransportType)transportType hostNameOverride:(NSString *)hostNameOverride logContext:(id)logContext @@ -159,9 +159,9 @@ static NSUInteger kDefaultChannelId = 0; _connectInitialBackoff = connectInitialBackoff; _connectMaxBackoff = connectMaxBackoff; _additionalChannelArgs = additionalChannelArgs; - _pemRootCert = pemRootCert; - _pemPrivateKey = pemPrivateKey; - _pemCertChain = pemCertChain; + _PEMRootCertificates = PEMRootCertificates; + _PEMPrivateKey = PEMPrivateKey; + _PEMCertChain = PEMCertChain; _transportType = transportType; _hostNameOverride = hostNameOverride; _logContext = logContext; @@ -188,9 +188,9 @@ static NSUInteger kDefaultChannelId = 0; connectInitialBackoff:_connectInitialBackoff connectMaxBackoff:_connectMaxBackoff additionalChannelArgs:[_additionalChannelArgs copy] - pemRootCert:_pemRootCert - pemPrivateKey:_pemPrivateKey - pemCertChain:_pemCertChain + PEMRootCertificates:_PEMRootCertificates + PEMPrivateKey:_PEMPrivateKey + PEMCertChain:_PEMCertChain transportType:_transportType hostNameOverride:_hostNameOverride logContext:_logContext @@ -216,9 +216,9 @@ static NSUInteger kDefaultChannelId = 0; connectInitialBackoff:_connectInitialBackoff connectMaxBackoff:_connectMaxBackoff additionalChannelArgs:[_additionalChannelArgs copy] - pemRootCert:_pemRootCert - pemPrivateKey:_pemPrivateKey - pemCertChain:_pemCertChain + PEMRootCertificates:_PEMRootCertificates + PEMPrivateKey:_PEMPrivateKey + PEMCertChain:_PEMCertChain transportType:_transportType hostNameOverride:_hostNameOverride logContext:_logContext @@ -246,9 +246,9 @@ static NSUInteger kDefaultChannelId = 0; @dynamic connectInitialBackoff; @dynamic connectMaxBackoff; @dynamic additionalChannelArgs; -@dynamic pemRootCert; -@dynamic pemPrivateKey; -@dynamic pemCertChain; +@dynamic PEMRootCertificates; +@dynamic PEMPrivateKey; +@dynamic PEMCertChain; @dynamic transportType; @dynamic hostNameOverride; @dynamic logContext; @@ -271,9 +271,9 @@ static NSUInteger kDefaultChannelId = 0; connectInitialBackoff:kDefaultConnectInitialBackoff connectMaxBackoff:kDefaultConnectMaxBackoff additionalChannelArgs:kDefaultAdditionalChannelArgs - pemRootCert:kDefaultPemRootCert - pemPrivateKey:kDefaultPemPrivateKey - pemCertChain:kDefaultPemCertChain + PEMRootCertificates:kDefaultPEMRootCertificates + PEMPrivateKey:kDefaultPEMPrivateKey + PEMCertChain:kDefaultPEMCertChain transportType:kDefaultTransportType hostNameOverride:kDefaultHostNameOverride logContext:kDefaultLogContext @@ -298,9 +298,9 @@ static NSUInteger kDefaultChannelId = 0; connectInitialBackoff:_connectInitialBackoff connectMaxBackoff:_connectMaxBackoff additionalChannelArgs:[_additionalChannelArgs copy] - pemRootCert:_pemRootCert - pemPrivateKey:_pemPrivateKey - pemCertChain:_pemCertChain + PEMRootCertificates:_PEMRootCertificates + PEMPrivateKey:_PEMPrivateKey + PEMCertChain:_PEMCertChain transportType:_transportType hostNameOverride:_hostNameOverride logContext:_logContext @@ -326,9 +326,9 @@ static NSUInteger kDefaultChannelId = 0; connectInitialBackoff:_connectInitialBackoff connectMaxBackoff:_connectMaxBackoff additionalChannelArgs:[_additionalChannelArgs copy] - pemRootCert:_pemRootCert - pemPrivateKey:_pemPrivateKey - pemCertChain:_pemCertChain + PEMRootCertificates:_PEMRootCertificates + PEMPrivateKey:_PEMPrivateKey + PEMCertChain:_PEMCertChain transportType:_transportType hostNameOverride:_hostNameOverride logContext:_logContext @@ -421,16 +421,16 @@ static NSUInteger kDefaultChannelId = 0; _additionalChannelArgs = additionalChannelArgs; } -- (void)setPemRootCert:(NSString *)pemRootCert { - _pemRootCert = pemRootCert; +- (void)setPEMRootCertificates:(NSString *)PEMRootCertificates { + _PEMRootCertificates = PEMRootCertificates; } -- (void)setPemPrivateKey:(NSString *)pemPrivateKey { - _pemPrivateKey = pemPrivateKey; +- (void)setPEMPrivateKey:(NSString *)PEMPrivateKey { + _PEMPrivateKey = PEMPrivateKey; } -- (void)setPemCertChain:(NSString *)pemCertChain { - _pemCertChain = pemCertChain; +- (void)setPEMCertChain:(NSString *)PEMCertChain { + _PEMCertChain = PEMCertChain; } - (void)setTransportType:(GRPCTransportType)transportType { diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 2b08eb8d5e3..9007f5fed51 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -54,9 +54,9 @@ const NSTimeInterval kChannelDestroyDelay = 30; #ifdef GRPC_COMPILE_WITH_CRONET if (![GRPCCall isUsingCronet]) { #endif - factory = [GRPCSecureChannelFactory factoryWithPEMRootCerts:_callOptions.pemRootCert - privateKey:_callOptions.pemPrivateKey - certChain:_callOptions.pemCertChain + factory = [GRPCSecureChannelFactory factoryWithPEMRootCerts:_callOptions.PEMRootCertificates + privateKey:_callOptions.PEMPrivateKey + certChain:_callOptions.PEMCertChain error:&error]; if (error) { NSLog(@"Error creating secure channel factory: %@", error); @@ -167,14 +167,14 @@ const NSTimeInterval kChannelDestroyDelay = 30; [obj.callOptions.additionalChannelArgs isEqualToDictionary:_callOptions.additionalChannelArgs])) return NO; - if (!(obj.callOptions.pemRootCert == _callOptions.pemRootCert || - [obj.callOptions.pemRootCert isEqualToString:_callOptions.pemRootCert])) + if (!(obj.callOptions.PEMRootCertificates == _callOptions.PEMRootCertificates || + [obj.callOptions.PEMRootCertificates isEqualToString:_callOptions.PEMRootCertificates])) return NO; - if (!(obj.callOptions.pemPrivateKey == _callOptions.pemPrivateKey || - [obj.callOptions.pemPrivateKey isEqualToString:_callOptions.pemPrivateKey])) + if (!(obj.callOptions.PEMPrivateKey == _callOptions.PEMPrivateKey || + [obj.callOptions.PEMPrivateKey isEqualToString:_callOptions.PEMPrivateKey])) return NO; - if (!(obj.callOptions.pemCertChain == _callOptions.pemCertChain || - [obj.callOptions.pemCertChain isEqualToString:_callOptions.pemCertChain])) + if (!(obj.callOptions.PEMCertChain == _callOptions.PEMCertChain || + [obj.callOptions.PEMCertChain isEqualToString:_callOptions.PEMCertChain])) return NO; if (!(obj.callOptions.hostNameOverride == _callOptions.hostNameOverride || [obj.callOptions.hostNameOverride isEqualToString:_callOptions.hostNameOverride])) @@ -204,9 +204,9 @@ const NSTimeInterval kChannelDestroyDelay = 30; result ^= (unsigned int)(_callOptions.connectInitialBackoff * 1000); result ^= (unsigned int)(_callOptions.connectMaxBackoff * 1000); result ^= _callOptions.additionalChannelArgs.hash; - result ^= _callOptions.pemRootCert.hash; - result ^= _callOptions.pemPrivateKey.hash; - result ^= _callOptions.pemCertChain.hash; + result ^= _callOptions.PEMRootCertificates.hash; + result ^= _callOptions.PEMPrivateKey.hash; + result ^= _callOptions.PEMCertChain.hash; result ^= _callOptions.hostNameOverride.hash; result ^= _callOptions.transportType; result ^= [_callOptions.logContext hash]; diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 0e3fa610f9e..429958b4083 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -38,8 +38,8 @@ NS_ASSUME_NONNULL_BEGIN static NSMutableDictionary *kHostCache; @implementation GRPCHost { - NSString *_pemRootCerts; - NSString *_pemPrivateKey; + NSString *_PEMRootCertificates; + NSString *_PEMPrivateKey; NSString *_pemCertChain; } @@ -92,8 +92,8 @@ static NSMutableDictionary *kHostCache; withPrivateKey:(nullable NSString *)pemPrivateKey withCertChain:(nullable NSString *)pemCertChain error:(NSError **)errorPtr { - _pemRootCerts = pemRootCerts; - _pemPrivateKey = pemPrivateKey; + _PEMRootCertificates = pemRootCerts; + _PEMPrivateKey = pemPrivateKey; _pemCertChain = pemCertChain; return YES; } @@ -109,9 +109,9 @@ static NSMutableDictionary *kHostCache; options.connectMinTimeout = (NSTimeInterval)_minConnectTimeout / 1000; options.connectInitialBackoff = (NSTimeInterval)_initialConnectBackoff / 1000; options.connectMaxBackoff = (NSTimeInterval)_maxConnectBackoff / 1000; - options.pemRootCert = _pemRootCerts; - options.pemPrivateKey = _pemPrivateKey; - options.pemCertChain = _pemCertChain; + options.PEMRootCertificates = _PEMRootCertificates; + options.PEMPrivateKey = _PEMPrivateKey; + options.PEMCertChain = _pemCertChain; options.hostNameOverride = _hostNameOverride; options.transportType = _transportType; options.logContext = _logContext; diff --git a/src/objective-c/tests/InteropTests.h b/src/objective-c/tests/InteropTests.h index e223839d3ac..038f24b62e5 100644 --- a/src/objective-c/tests/InteropTests.h +++ b/src/objective-c/tests/InteropTests.h @@ -51,7 +51,7 @@ * The root certificates to be used. The base implementation returns nil. Subclasses should override * to appropriate settings. */ -+ (NSString *)pemRootCert; ++ (NSString *)PEMRootCertificates; /** * The root certificates to be used. The base implementation returns nil. Subclasses should override diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 16d5040a733..0835ff909f5 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -147,7 +147,7 @@ BOOL isRemoteInteropTest(NSString *host) { return GRPCTransportTypeChttp2BoringSSL; } -+ (NSString *)pemRootCert { ++ (NSString *)PEMRootCertificates { return nil; } @@ -202,7 +202,7 @@ BOOL isRemoteInteropTest(NSString *host) { GPBEmpty *request = [GPBEmpty message]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; options.transportType = self.class.transportType; - options.pemRootCert = self.class.pemRootCert; + options.PEMRootCertificates = self.class.PEMRootCertificates; options.hostNameOverride = self.class.hostNameOverride; [_service @@ -484,7 +484,7 @@ BOOL isRemoteInteropTest(NSString *host) { requestedResponseSize:responses[index]]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; options.transportType = self.class.transportType; - options.pemRootCert = self.class.pemRootCert; + options.PEMRootCertificates = self.class.PEMRootCertificates; options.hostNameOverride = self.class.hostNameOverride; __block GRPCStreamingProtoCall *call = [_service @@ -629,7 +629,7 @@ BOOL isRemoteInteropTest(NSString *host) { GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; options.transportType = self.class.transportType; - options.pemRootCert = self.class.pemRootCert; + options.PEMRootCertificates = self.class.PEMRootCertificates; options.hostNameOverride = self.class.hostNameOverride; id request = diff --git a/src/objective-c/tests/InteropTestsLocalCleartext.m b/src/objective-c/tests/InteropTestsLocalCleartext.m index 42e327a3303..a9c69183332 100644 --- a/src/objective-c/tests/InteropTestsLocalCleartext.m +++ b/src/objective-c/tests/InteropTestsLocalCleartext.m @@ -41,7 +41,7 @@ static int32_t kLocalInteropServerOverhead = 10; return kLocalCleartextHost; } -+ (NSString *)pemRootCert { ++ (NSString *)PEMRootCertificates { return nil; } diff --git a/src/objective-c/tests/InteropTestsLocalSSL.m b/src/objective-c/tests/InteropTestsLocalSSL.m index 997dd87eeea..759a080380d 100644 --- a/src/objective-c/tests/InteropTestsLocalSSL.m +++ b/src/objective-c/tests/InteropTestsLocalSSL.m @@ -40,7 +40,7 @@ static int32_t kLocalInteropServerOverhead = 10; return kLocalSSLHost; } -+ (NSString *)pemRootCert { ++ (NSString *)PEMRootCertificates { NSBundle *bundle = [NSBundle bundleForClass:self.class]; NSString *certsPath = [bundle pathForResource:@"TestCertificates.bundle/test-certificates" ofType:@"pem"]; diff --git a/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m b/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m index b1d663584c8..237804d23de 100644 --- a/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m +++ b/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m @@ -115,7 +115,7 @@ dispatch_once_t initCronet; options = [[GRPCCallOptions alloc] init]; options.transportType = GRPCTransportTypeChttp2BoringSSL; - options.pemRootCert = certs; + options.PEMRootCertificates = certs; options.hostNameOverride = @"foo.test.google.fr"; _localSSLService.options = options; } diff --git a/src/objective-c/tests/InteropTestsRemote.m b/src/objective-c/tests/InteropTestsRemote.m index 30670facad0..c1cd9b81efc 100644 --- a/src/objective-c/tests/InteropTestsRemote.m +++ b/src/objective-c/tests/InteropTestsRemote.m @@ -41,7 +41,7 @@ static int32_t kRemoteInteropServerOverhead = 12; return kRemoteSSLHost; } -+ (NSString *)pemRootCert { ++ (NSString *)PEMRootCertificates { return nil; } From 521ffacd7c6b90b884aae72bc342d134e41053fb Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 14:44:55 -0700 Subject: [PATCH 030/375] Add example to channelPoolDomain --- src/objective-c/GRPCClient/GRPCCallOptions.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index ea7c1bf22db..dcd4de62233 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -307,7 +307,9 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { /** * A string that specify the domain where channel is being cached. Channels with different domains - * will not get cached to the same connection. + * will not get cached to the same connection. For example, a gRPC example app may use the channel + * pool domain 'io.grpc.example' so that its calls do not reuse the channel created by other modules + * in the same process. */ @property(copy, readwrite) NSString *channelPoolDomain; From 2c47c953380d0a02df4bc7e4d7772b235cd7da9c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 16:17:03 -0700 Subject: [PATCH 031/375] Rename channelId->channelID --- src/objective-c/GRPCClient/GRPCCallOptions.h | 14 +++++----- src/objective-c/GRPCClient/GRPCCallOptions.m | 28 +++++++++---------- .../GRPCClient/private/GRPCChannelPool.m | 4 +-- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index dcd4de62233..9c6e00fd187 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -181,9 +181,9 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { /** * Channel id allows a call to force creating a new channel (connection) rather than using a cached - * channel. Calls using distinct channelId will not get cached to the same connection. + * channel. Calls using distinct channelID will not get cached to the same connection. */ -@property(readonly) NSUInteger channelId; +@property(readonly) NSUInteger channelID; @end @@ -307,16 +307,16 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { /** * A string that specify the domain where channel is being cached. Channels with different domains - * will not get cached to the same connection. For example, a gRPC example app may use the channel - * pool domain 'io.grpc.example' so that its calls do not reuse the channel created by other modules - * in the same process. + * will not get cached to the same channel. For example, a gRPC example app may use the channel pool + * domain 'io.grpc.example' so that its calls do not reuse the channel created by other modules in + * the same process. */ @property(copy, readwrite) NSString *channelPoolDomain; /** * Channel id allows a call to force creating a new channel (connection) rather than using a cached - * channel. Calls using distinct channelId will not get cached to the same connection. + * channel. Calls using distinct channelID's will not get cached to the same channel. */ -@property(readwrite) NSUInteger channelId; +@property(readwrite) NSUInteger channelID; @end diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 539cb9929db..ad90fb829e8 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -41,7 +41,7 @@ static const GRPCTransportType kDefaultTransportType = GRPCTransportTypeChttp2Bo static NSString *const kDefaultHostNameOverride = nil; static const id kDefaultLogContext = nil; static NSString *kDefaultChannelPoolDomain = nil; -static NSUInteger kDefaultChannelId = 0; +static NSUInteger kDefaultChannelID = 0; @implementation GRPCCallOptions { @protected @@ -67,7 +67,7 @@ static NSUInteger kDefaultChannelId = 0; NSString *_hostNameOverride; id _logContext; NSString *_channelPoolDomain; - NSUInteger _channelId; + NSUInteger _channelID; } @synthesize serverAuthority = _serverAuthority; @@ -92,7 +92,7 @@ static NSUInteger kDefaultChannelId = 0; @synthesize hostNameOverride = _hostNameOverride; @synthesize logContext = _logContext; @synthesize channelPoolDomain = _channelPoolDomain; -@synthesize channelId = _channelId; +@synthesize channelID = _channelID; - (instancetype)init { return [self initWithServerAuthority:kDefaultServerAuthority @@ -117,7 +117,7 @@ static NSUInteger kDefaultChannelId = 0; hostNameOverride:kDefaultHostNameOverride logContext:kDefaultLogContext channelPoolDomain:kDefaultChannelPoolDomain - channelId:kDefaultChannelId]; + channelID:kDefaultChannelID]; } - (instancetype)initWithServerAuthority:(NSString *)serverAuthority @@ -142,7 +142,7 @@ static NSUInteger kDefaultChannelId = 0; hostNameOverride:(NSString *)hostNameOverride logContext:(id)logContext channelPoolDomain:(NSString *)channelPoolDomain - channelId:(NSUInteger)channelId { + channelID:(NSUInteger)channelID { if ((self = [super init])) { _serverAuthority = serverAuthority; _timeout = timeout; @@ -166,7 +166,7 @@ static NSUInteger kDefaultChannelId = 0; _hostNameOverride = hostNameOverride; _logContext = logContext; _channelPoolDomain = channelPoolDomain; - _channelId = channelId; + _channelID = channelID; } return self; } @@ -195,7 +195,7 @@ static NSUInteger kDefaultChannelId = 0; hostNameOverride:_hostNameOverride logContext:_logContext channelPoolDomain:_channelPoolDomain - channelId:_channelId]; + channelID:_channelID]; return newOptions; } @@ -223,7 +223,7 @@ static NSUInteger kDefaultChannelId = 0; hostNameOverride:_hostNameOverride logContext:_logContext channelPoolDomain:_channelPoolDomain - channelId:_channelId]; + channelID:_channelID]; return newOptions; } @@ -253,7 +253,7 @@ static NSUInteger kDefaultChannelId = 0; @dynamic hostNameOverride; @dynamic logContext; @dynamic channelPoolDomain; -@dynamic channelId; +@dynamic channelID; - (instancetype)init { return [self initWithServerAuthority:kDefaultServerAuthority @@ -278,7 +278,7 @@ static NSUInteger kDefaultChannelId = 0; hostNameOverride:kDefaultHostNameOverride logContext:kDefaultLogContext channelPoolDomain:kDefaultChannelPoolDomain - channelId:kDefaultChannelId]; + channelID:kDefaultChannelID]; } - (nonnull id)copyWithZone:(NSZone *)zone { @@ -305,7 +305,7 @@ static NSUInteger kDefaultChannelId = 0; hostNameOverride:_hostNameOverride logContext:_logContext channelPoolDomain:_channelPoolDomain - channelId:_channelId]; + channelID:_channelID]; return newOptions; } @@ -333,7 +333,7 @@ static NSUInteger kDefaultChannelId = 0; hostNameOverride:_hostNameOverride logContext:_logContext channelPoolDomain:_channelPoolDomain - channelId:_channelId]; + channelID:_channelID]; return newOptions; } @@ -449,8 +449,8 @@ static NSUInteger kDefaultChannelId = 0; _channelPoolDomain = channelPoolDomain; } -- (void)setChannelId:(NSUInteger)channelId { - _channelId = channelId; +- (void)setChannelID:(NSUInteger)channelID { + _channelID = channelID; } @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 9007f5fed51..37e42f8c75b 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -186,7 +186,7 @@ const NSTimeInterval kChannelDestroyDelay = 30; if (!(obj.callOptions.channelPoolDomain == _callOptions.channelPoolDomain || [obj.callOptions.channelPoolDomain isEqualToString:_callOptions.channelPoolDomain])) return NO; - if (!(obj.callOptions.channelId == _callOptions.channelId)) return NO; + if (!(obj.callOptions.channelID == _callOptions.channelID)) return NO; return YES; } @@ -211,7 +211,7 @@ const NSTimeInterval kChannelDestroyDelay = 30; result ^= _callOptions.transportType; result ^= [_callOptions.logContext hash]; result ^= _callOptions.channelPoolDomain.hash; - result ^= _callOptions.channelId; + result ^= _callOptions.channelID; return result; } From 229651a371ac590f47793cdacc8d28c0ac74bf48 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 16:17:38 -0700 Subject: [PATCH 032/375] Check range of value-typed channel arg --- src/objective-c/GRPCClient/private/ChannelArgsUtil.m | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m index 8ebf3a26593..04a5cc8345a 100644 --- a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m +++ b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m @@ -21,6 +21,8 @@ #include #include +#include + static void *copy_pointer_arg(void *p) { // Add ref count to the object when making copy id obj = (__bridge id)p; @@ -79,6 +81,11 @@ grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) { arg->type = GRPC_ARG_STRING; arg->value.string = gpr_strdup([value UTF8String]); } else if ([value respondsToSelector:@selector(intValue)]) { + if ([value compare:[NSNumber numberWithInteger:INT_MAX]] == NSOrderedDescending || + [value compare:[NSNumber numberWithInteger:INT_MIN]] == NSOrderedAscending) { + [NSException raise:NSInvalidArgumentException + format:@"Range exceeded for a value typed channel argument: %@", value]; + } arg->type = GRPC_ARG_INTEGER; arg->value.integer = [value intValue]; } else if (value != nil) { From ecf85f045975265d19a94b116e94f7fea42a9d38 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 16:23:25 -0700 Subject: [PATCH 033/375] Copy fields in GRPCCallOptions initializer --- src/objective-c/GRPCClient/GRPCCallOptions.m | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index ad90fb829e8..f9706b18467 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -144,12 +144,12 @@ static NSUInteger kDefaultChannelID = 0; channelPoolDomain:(NSString *)channelPoolDomain channelID:(NSUInteger)channelID { if ((self = [super init])) { - _serverAuthority = serverAuthority; + _serverAuthority = [serverAuthority copy]; _timeout = timeout; - _oauth2AccessToken = oauth2AccessToken; + _oauth2AccessToken = [oauth2AccessToken copy]; _authTokenProvider = authTokenProvider; - _initialMetadata = initialMetadata; - _userAgentPrefix = userAgentPrefix; + _initialMetadata = [[NSDictionary alloc] initWithDictionary:initialMetadata copyItems:YES]; + _userAgentPrefix = [userAgentPrefix copy]; _responseSizeLimit = responseSizeLimit; _compressAlgorithm = compressAlgorithm; _enableRetry = enableRetry; @@ -158,14 +158,14 @@ static NSUInteger kDefaultChannelID = 0; _connectMinTimeout = connectMinTimeout; _connectInitialBackoff = connectInitialBackoff; _connectMaxBackoff = connectMaxBackoff; - _additionalChannelArgs = additionalChannelArgs; - _PEMRootCertificates = PEMRootCertificates; - _PEMPrivateKey = PEMPrivateKey; - _PEMCertChain = PEMCertChain; + _additionalChannelArgs = [[NSDictionary alloc] initWithDictionary:additionalChannelArgs copyItems:YES]; + _PEMRootCertificates = [PEMRootCertificates copy]; + _PEMPrivateKey = [PEMPrivateKey copy]; + _PEMCertChain = [PEMCertChain copy]; _transportType = transportType; - _hostNameOverride = hostNameOverride; + _hostNameOverride = [hostNameOverride copy]; _logContext = logContext; - _channelPoolDomain = channelPoolDomain; + _channelPoolDomain = [channelPoolDomain copy]; _channelID = channelID; } return self; From 1c8751f366fc4b51a49cc83aa8477dd2b12664a8 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 16:33:02 -0700 Subject: [PATCH 034/375] Avoid copy in GRPCCallOptions:copyWithZone: --- src/objective-c/GRPCClient/GRPCCallOptions.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index f9706b18467..c700bba794a 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -187,7 +187,7 @@ static NSUInteger kDefaultChannelID = 0; connectMinTimeout:_connectMinTimeout connectInitialBackoff:_connectInitialBackoff connectMaxBackoff:_connectMaxBackoff - additionalChannelArgs:[_additionalChannelArgs copy] + additionalChannelArgs:_additionalChannelArgs PEMRootCertificates:_PEMRootCertificates PEMPrivateKey:_PEMPrivateKey PEMCertChain:_PEMCertChain From 454966e36cab39ee1b18828575a23c75d812d895 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 16:38:14 -0700 Subject: [PATCH 035/375] Copy in GRPCCallOptions setters --- src/objective-c/GRPCClient/GRPCCallOptions.m | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index c700bba794a..b19917d7784 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -338,7 +338,7 @@ static NSUInteger kDefaultChannelID = 0; } - (void)setServerAuthority:(NSString *)serverAuthority { - _serverAuthority = serverAuthority; + _serverAuthority = [serverAuthority copy]; } - (void)setTimeout:(NSTimeInterval)timeout { @@ -350,7 +350,7 @@ static NSUInteger kDefaultChannelID = 0; } - (void)setOauth2AccessToken:(NSString *)oauth2AccessToken { - _oauth2AccessToken = oauth2AccessToken; + _oauth2AccessToken = [oauth2AccessToken copy]; } - (void)setAuthTokenProvider:(id)authTokenProvider { @@ -358,11 +358,11 @@ static NSUInteger kDefaultChannelID = 0; } - (void)setInitialMetadata:(NSDictionary *)initialMetadata { - _initialMetadata = initialMetadata; + _initialMetadata = [[NSDictionary alloc] initWithDictionary:initialMetadata copyItems:YES]; } - (void)setUserAgentPrefix:(NSString *)userAgentPrefix { - _userAgentPrefix = userAgentPrefix; + _userAgentPrefix = [userAgentPrefix copy]; } - (void)setResponseSizeLimit:(NSUInteger)responseSizeLimit { @@ -418,19 +418,19 @@ static NSUInteger kDefaultChannelID = 0; } - (void)setAdditionalChannelArgs:(NSDictionary *)additionalChannelArgs { - _additionalChannelArgs = additionalChannelArgs; + _additionalChannelArgs = [[NSDictionary alloc] initWithDictionary:additionalChannelArgs copyItems:YES]; } - (void)setPEMRootCertificates:(NSString *)PEMRootCertificates { - _PEMRootCertificates = PEMRootCertificates; + _PEMRootCertificates = [PEMRootCertificates copy]; } - (void)setPEMPrivateKey:(NSString *)PEMPrivateKey { - _PEMPrivateKey = PEMPrivateKey; + _PEMPrivateKey = [PEMPrivateKey copy]; } - (void)setPEMCertChain:(NSString *)PEMCertChain { - _PEMCertChain = PEMCertChain; + _PEMCertChain = [PEMCertChain copy]; } - (void)setTransportType:(GRPCTransportType)transportType { @@ -438,7 +438,7 @@ static NSUInteger kDefaultChannelID = 0; } - (void)setHostNameOverride:(NSString *)hostNameOverride { - _hostNameOverride = hostNameOverride; + _hostNameOverride = [hostNameOverride copy]; } - (void)setLogContext:(id)logContext { @@ -446,7 +446,7 @@ static NSUInteger kDefaultChannelID = 0; } - (void)setChannelPoolDomain:(NSString *)channelPoolDomain { - _channelPoolDomain = channelPoolDomain; + _channelPoolDomain = [channelPoolDomain copy]; } - (void)setChannelID:(NSUInteger)channelID { From 92d6e285d174bf6c8b2e60054f82d7288231da14 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 11 Oct 2018 16:42:53 -0700 Subject: [PATCH 036/375] Polish exception message --- src/objective-c/GRPCClient/private/ChannelArgsUtil.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m index 04a5cc8345a..b26fb12d597 100644 --- a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m +++ b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m @@ -84,7 +84,7 @@ grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) { if ([value compare:[NSNumber numberWithInteger:INT_MAX]] == NSOrderedDescending || [value compare:[NSNumber numberWithInteger:INT_MIN]] == NSOrderedAscending) { [NSException raise:NSInvalidArgumentException - format:@"Range exceeded for a value typed channel argument: %@", value]; + format:@"Out of range for a value-typed channel argument: %@", value]; } arg->type = GRPC_ARG_INTEGER; arg->value.integer = [value intValue]; @@ -94,7 +94,7 @@ grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) { arg->value.pointer.vtable = &objc_arg_vtable; } else { [NSException raise:NSInvalidArgumentException - format:@"Invalid value type: %@", [value class]]; + format:@"Invalid channel argument type: %@", [value class]]; } } From e457b0dacc70a28fffd42064236fbf240952e3b4 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 12 Oct 2018 09:02:52 -0700 Subject: [PATCH 037/375] Fix missing initialMetadata in GRPCMutableCallOptions --- src/objective-c/GRPCClient/GRPCCallOptions.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 9c6e00fd187..68d3eb4fbb3 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -223,6 +223,11 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { */ @property(readwrite) id authTokenProvider; +/** + * Initial metadata key-value pairs that should be included in the request. + */ +@property(copy, readonly) NSDictionary *initialMetadata; + // Channel parameters; take into account of channel signature. /** From e69a7cc7f7497e67232843a3843f543740480c4e Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 12 Oct 2018 11:21:52 -0700 Subject: [PATCH 038/375] patch the previous fix --- src/objective-c/GRPCClient/GRPCCallOptions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 68d3eb4fbb3..ff575d09cf8 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -226,7 +226,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { /** * Initial metadata key-value pairs that should be included in the request. */ -@property(copy, readonly) NSDictionary *initialMetadata; +@property(copy, readwrite) NSDictionary *initialMetadata; // Channel parameters; take into account of channel signature. From bf092064962664a1a949750c9f9b273f7d27c529 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 16 Oct 2018 15:34:39 -0700 Subject: [PATCH 039/375] Separate GRPCProtoResponseHandler from GRPCResponseHandler --- src/objective-c/GRPCClient/GRPCCall.h | 6 +- src/objective-c/GRPCClient/GRPCCall.m | 4 +- src/objective-c/ProtoRPC/ProtoRPC.h | 37 +++++++++++- src/objective-c/ProtoRPC/ProtoRPC.m | 76 ++++++++++++++----------- src/objective-c/tests/GRPCClientTests.m | 2 +- src/objective-c/tests/InteropTests.m | 4 +- 6 files changed, 85 insertions(+), 44 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 304fb17cca5..48f4514a06f 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -157,10 +157,10 @@ extern id const kGRPCTrailersKey; - (void)receivedInitialMetadata:(NSDictionary *)initialMetadata; /** - * Issued when a message is received from the server. The message may be raw data from the server - * (when using \a GRPCCall2 directly) or deserialized proto object (when using \a ProtoRPC). + * Issued when a message is received from the server. The message is the raw data received from the + * server, with decompression and without proto deserialization. */ -- (void)receivedMessage:(id)message; +- (void)receivedRawMessage:(id)message; /** * Issued when a call finished. If the call finished successfully, \a error is nil and \a diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 36cb71399ca..eb9b21eccb0 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -236,9 +236,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)issueMessage:(id)message { id handler = self->_handler; - if ([handler respondsToSelector:@selector(receivedMessage:)]) { + if ([handler respondsToSelector:@selector(receivedRawMessage:)]) { dispatch_async(handler.dispatchQueue, ^{ - [handler receivedMessage:message]; + [handler receivedRawMessage:message]; }); } } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index a045ef10a6c..d20098ce8c9 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -23,6 +23,39 @@ @class GPBMessage; +/** An object can implement this protocol to receive responses from server from a call. */ +@protocol GRPCProtoResponseHandler + +@optional + +/** Issued when initial metadata is received from the server. */ +- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata; + +/** + * Issued when a message is received from the server. The message is the deserialized proto object. + */ +- (void)receivedProtoMessage:(id)message; + +/** + * Issued when a call finished. If the call finished successfully, \a error is nil and \a + * trainingMetadata consists any trailing metadata received from the server. Otherwise, \a error + * is non-nil and contains the corresponding error information, including gRPC error codes and + * error descriptions. + */ +- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error; + +@required + +/** + * All the responses must be issued to a user-provided dispatch queue. This property specifies the + * dispatch queue to be used for issuing the notifications. A serial queue should be provided if + * the order of responses (initial metadata, message, message, ..., message, trailing metadata) + * needs to be maintained. + */ +@property(atomic, readonly) dispatch_queue_t dispatchQueue; + +@end + /** A unary-request RPC call with Protobuf. */ @interface GRPCUnaryProtoCall : NSObject @@ -36,7 +69,7 @@ */ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions message:(GPBMessage *)message - responseHandler:(id)handler + responseHandler:(id)handler callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; @@ -57,7 +90,7 @@ * returned to users by methods of the generated service. */ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions - responseHandler:(id)handler + responseHandler:(id)handler callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 957d6365341..7a57affbf15 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -33,7 +33,7 @@ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions message:(GPBMessage *)message - responseHandler:(id)handler + responseHandler:(id)handler callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass { if ((self = [super init])) { @@ -60,7 +60,7 @@ @implementation GRPCStreamingProtoCall { GRPCRequestOptions *_requestOptions; - id _handler; + id _handler; GRPCCallOptions *_callOptions; Class _responseClass; @@ -69,7 +69,7 @@ } - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions - responseHandler:(id)handler + responseHandler:(id)handler callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass { if ((self = [super init])) { @@ -98,16 +98,18 @@ _call = nil; } if (_handler) { - id handler = _handler; - dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:nil - error:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeCancelled - userInfo:@{ - NSLocalizedDescriptionKey : - @"Canceled by app" - }]]; - }); + id handler = _handler; + if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + dispatch_async(handler.dispatchQueue, ^{ + [handler closedWithTrailingMetadata:nil + error:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeCancelled + userInfo:@{ + NSLocalizedDescriptionKey : + @"Canceled by app" + }]]; + }); + } _handler = nil; } }); @@ -136,27 +138,33 @@ - (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { if (_handler) { - id handler = _handler; - dispatch_async(handler.dispatchQueue, ^{ - [handler receivedInitialMetadata:initialMetadata]; - }); + id handler = _handler; + if ([handler respondsToSelector:@selector(initialMetadata:)]) { + dispatch_async(handler.dispatchQueue, ^{ + [handler receivedInitialMetadata:initialMetadata]; + }); + } } } -- (void)receivedMessage:(NSData *)message { +- (void)receivedRawMessage:(NSData *)message { if (_handler) { - id handler = _handler; + id handler = _handler; NSError *error = nil; id parsed = [_responseClass parseFromData:message error:&error]; if (parsed) { - dispatch_async(handler.dispatchQueue, ^{ - [handler receivedMessage:parsed]; - }); + if ([handler respondsToSelector:@selector(receivedProtoMessage:)]) { + dispatch_async(handler.dispatchQueue, ^{ + [handler receivedProtoMessage:parsed]; + }); + } } else { - dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:nil error:error]; - }); - handler = nil; + if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + dispatch_async(handler.dispatchQueue, ^{ + [handler closedWithTrailingMetadata:nil error:error]; + }); + } + _handler = nil; [_call cancel]; _call = nil; } @@ -165,16 +173,16 @@ - (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { if (_handler) { - id handler = _handler; - dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:trailingMetadata error:error]; - }); + id handler = _handler; + if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + dispatch_async(handler.dispatchQueue, ^{ + [handler closedWithTrailingMetadata:trailingMetadata error:error]; + }); + } _handler = nil; } - if (_call) { - [_call cancel]; - _call = nil; - } + [_call cancel]; + _call = nil; } - (dispatch_queue_t)dispatchQueue { diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 8a4eddb1b70..f961b6a86fd 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -120,7 +120,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; } } -- (void)receivedMessage:(id)message { +- (void)receivedProtoMessage:(id)message { if (_messageCallback) { _messageCallback(message); } diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 0835ff909f5..11d4b95663a 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -75,7 +75,7 @@ BOOL isRemoteInteropTest(NSString *host) { } // Convenience class to use blocks as callbacks -@interface InteropTestsBlockCallbacks : NSObject +@interface InteropTestsBlockCallbacks : NSObject - (instancetype)initWithInitialMetadataCallback:(void (^)(NSDictionary *))initialMetadataCallback messageCallback:(void (^)(id))messageCallback @@ -108,7 +108,7 @@ BOOL isRemoteInteropTest(NSString *host) { } } -- (void)receivedMessage:(id)message { +- (void)receivedProtoMessage:(id)message { if (_messageCallback) { _messageCallback(message); } From 9f47e76fc8b72c432e9b3d4711c7b2898236f37b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 16 Oct 2018 16:06:54 -0700 Subject: [PATCH 040/375] QoS for internal dispatch queues --- src/objective-c/GRPCClient/GRPCCall.m | 11 ++++++++--- src/objective-c/ProtoRPC/ProtoRPC.m | 6 +++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index eb9b21eccb0..df50d43e076 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -108,7 +108,12 @@ const char *kCFStreamVarName = "grpc_cfstream"; _handler = responseHandler; _initialMetadataPublished = NO; _pipe = [GRXBufferedPipe pipe]; - _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + if (@available(iOS 8.0, *)) { + _dispatchQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + } else { + // Fallback on earlier versions + _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + } _started = NO; } @@ -226,7 +231,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)issueInitialMetadata:(NSDictionary *)initialMetadata { - id handler = self->_handler; + id handler = _handler; if ([handler respondsToSelector:@selector(receivedInitialMetadata:)]) { dispatch_async(handler.dispatchQueue, ^{ [handler receivedInitialMetadata:initialMetadata]; @@ -235,7 +240,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)issueMessage:(id)message { - id handler = self->_handler; + id handler = _handler; if ([handler respondsToSelector:@selector(receivedRawMessage:)]) { dispatch_async(handler.dispatchQueue, ^{ [handler receivedRawMessage:message]; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 7a57affbf15..b860515d4e4 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -77,7 +77,11 @@ _handler = handler; _callOptions = [callOptions copy]; _responseClass = responseClass; - _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); + if (@available(iOS 8.0, *)) { + _dispatchQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + } else { + _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); + } [self start]; } From b3d236d1bf4acebce821fb7f36c262e34104a9b1 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 16 Oct 2018 16:07:35 -0700 Subject: [PATCH 041/375] Prevent empty string --- src/objective-c/GRPCClient/GRPCCall.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index df50d43e076..7b100cb02a1 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -380,8 +380,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; callSafety:(GRPCCallSafety)safety requestsWriter:(GRXWriter *)requestWriter callOptions:(GRPCCallOptions *)callOptions { - if (!host || !path) { - [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; + if (host.length == 0 || path.length == 0) { + [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil or empty."]; } if (requestWriter.state != GRXWriterStateNotStarted) { [NSException raise:NSInvalidArgumentException From da43545ff7b4b1a6e310ff7fdeec6eb21f0e26b8 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 16 Oct 2018 16:38:04 -0700 Subject: [PATCH 042/375] Check callSafety in -init in GRPCCall --- src/objective-c/GRPCClient/GRPCCall.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 7b100cb02a1..50c38ed99ed 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -383,6 +383,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; if (host.length == 0 || path.length == 0) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil or empty."]; } + if (safety > GRPCCallSafetyCacheableRequest) { + [NSException raise:NSInvalidArgumentException format:@"Invalid call safety value."]; + } if (requestWriter.state != GRXWriterStateNotStarted) { [NSException raise:NSInvalidArgumentException format:@"The requests writer can't be already started."]; @@ -556,8 +559,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; case GRPCCallSafetyCacheableRequest: callSafetyFlags = GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; break; - default: - [NSException raise:NSInvalidArgumentException format:@"Invalid call safety value."]; } uint32_t callFlag = callSafetyFlags; From 7d32a2cb25275e03a44184ad9f8a3e494e62dd0d Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 16 Oct 2018 17:10:32 -0700 Subject: [PATCH 043/375] Set user's dispatch queue's handler to internal serial queue --- src/objective-c/GRPCClient/GRPCCall.h | 4 +--- src/objective-c/GRPCClient/GRPCCall.m | 7 +++++++ src/objective-c/ProtoRPC/ProtoRPC.h | 4 +--- src/objective-c/ProtoRPC/ProtoRPC.m | 11 +++++++++++ 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 48f4514a06f..6adecec144a 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -174,9 +174,7 @@ extern id const kGRPCTrailersKey; /** * All the responses must be issued to a user-provided dispatch queue. This property specifies the - * dispatch queue to be used for issuing the notifications. A serial queue should be provided if - * the order of responses (initial metadata, message, message, ..., message, trailing metadata) - * needs to be maintained. + * dispatch queue to be used for issuing the notifications. */ @property(atomic, readonly) dispatch_queue_t dispatchQueue; diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 50c38ed99ed..917788e9f2e 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -101,6 +101,12 @@ const char *kCFStreamVarName = "grpc_cfstream"; if (requestOptions.host.length == 0 || requestOptions.path.length == 0) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; } + if (requestOptions.safety > GRPCCallSafetyCacheableRequest) { + [NSException raise:NSInvalidArgumentException format:@"Invalid call safety value."]; + } + if (responseHandler == nil) { + [NSException raise:NSInvalidArgumentException format:@"Response handler required."]; + } if ((self = [super init])) { _requestOptions = [requestOptions copy]; @@ -114,6 +120,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Fallback on earlier versions _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); } + dispatch_set_target_queue(responseHandler.dispatchQueue, _dispatchQueue); _started = NO; } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index d20098ce8c9..db1e8c6deb3 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -48,9 +48,7 @@ /** * All the responses must be issued to a user-provided dispatch queue. This property specifies the - * dispatch queue to be used for issuing the notifications. A serial queue should be provided if - * the order of responses (initial metadata, message, message, ..., message, trailing metadata) - * needs to be maintained. + * dispatch queue to be used for issuing the notifications. */ @property(atomic, readonly) dispatch_queue_t dispatchQueue; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index b860515d4e4..9fb398408bf 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -72,6 +72,16 @@ responseHandler:(id)handler callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass { + if (requestOptions.host.length == 0 || requestOptions.path.length == 0) { + [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; + } + if (requestOptions.safety > GRPCCallSafetyCacheableRequest) { + [NSException raise:NSInvalidArgumentException format:@"Invalid call safety value."]; + } + if (handler == nil) { + [NSException raise:NSInvalidArgumentException format:@"Response handler required."]; + } + if ((self = [super init])) { _requestOptions = [requestOptions copy]; _handler = handler; @@ -82,6 +92,7 @@ } else { _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); } + dispatch_set_target_queue(handler.dispatchQueue, _dispatchQueue); [self start]; } From a8b07a37df7680bbe853f4efa0c358447db946fe Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 16 Oct 2018 17:39:51 -0700 Subject: [PATCH 044/375] Synchronized access to kHostCache --- src/objective-c/GRPCClient/private/GRPCHost.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 429958b4083..de6f09a44b2 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -125,7 +125,10 @@ static NSMutableDictionary *kHostCache; if (hostURL.host && !hostURL.port) { address = [hostURL.host stringByAppendingString:@":443"]; } - GRPCHost *cachedHost = kHostCache[address]; + __block GRPCHost *cachedHost; + @synchronized (kHostCache) { + cachedHost = kHostCache[address]; + } return (cachedHost != nil); } From 543fbf38c0ad1690558f7be3d1c58ff445a8714f Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 16 Oct 2018 17:40:35 -0700 Subject: [PATCH 045/375] timeout > 0 --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 917788e9f2e..16acca249d6 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -753,7 +753,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; if (_serverName.length != 0) { callOptions.serverAuthority = _serverName; } - if (_timeout != 0) { + if (_timeout > 0) { callOptions.timeout = _timeout; } uint32_t callFlags = [GRPCCall callFlagsForHost:_host path:_path]; From 6032e960d43af5912d06553adc22012d3f7c758a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 16 Oct 2018 18:06:13 -0700 Subject: [PATCH 046/375] Polish channelID comments --- src/objective-c/GRPCClient/GRPCCallOptions.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index ff575d09cf8..e1a63f83b2e 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -41,6 +41,7 @@ typedef NS_ENUM(NSInteger, GRPCCompressAlgorithm) { // The transport to be used by a gRPC call typedef NS_ENUM(NSInteger, GRPCTransportType) { + GRPCTransportTypeDefault = 0, // gRPC internal HTTP/2 stack with BoringSSL GRPCTransportTypeChttp2BoringSSL = 0, // Cronet stack @@ -180,8 +181,10 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { @property(copy, readonly) NSString *channelPoolDomain; /** - * Channel id allows a call to force creating a new channel (connection) rather than using a cached - * channel. Calls using distinct channelID will not get cached to the same connection. + * Channel id allows control of channel caching within a channelPoolDomain. A call with a unique + * channelID will create a new channel (connection) instead of reusing an existing one. Multiple + * calls in the same channelPoolDomain using identical channelID are allowed to share connection + * if other channel options are also the same. */ @property(readonly) NSUInteger channelID; From 62fb609df7b9534f188804c43401f6219345577c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 16 Oct 2018 18:10:02 -0700 Subject: [PATCH 047/375] rename kChannelPool->gChannelPool --- src/objective-c/GRPCClient/private/GRPCChannel.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index cf44b96e220..ae90821de03 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -64,7 +64,7 @@ } - (void)unmanagedCallUnref { - [kChannelPool unrefChannelWithConfiguration:_configuration]; + [gChannelPool unrefChannelWithConfiguration:_configuration]; } - (nullable instancetype)initWithUnmanagedChannel:(nullable grpc_channel *)unmanagedChannel @@ -94,12 +94,12 @@ } static dispatch_once_t initChannelPool; -static GRPCChannelPool *kChannelPool; +static GRPCChannelPool *gChannelPool; + (nullable instancetype)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { dispatch_once(&initChannelPool, ^{ - kChannelPool = [[GRPCChannelPool alloc] init]; + gChannelPool = [[GRPCChannelPool alloc] init]; }); NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:host]]; @@ -109,7 +109,7 @@ static GRPCChannelPool *kChannelPool; GRPCChannelConfiguration *channelConfig = [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; - return [kChannelPool channelWithConfiguration:channelConfig + return [gChannelPool channelWithConfiguration:channelConfig createChannel:^{ return [GRPCChannel createChannelWithConfiguration:channelConfig]; @@ -117,7 +117,7 @@ static GRPCChannelPool *kChannelPool; } + (void)closeOpenConnections { - [kChannelPool clear]; + [gChannelPool clear]; } @end From 549db7b80b3e6e91aaf08f9f9bf2f932050cc310 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 16 Oct 2018 18:10:48 -0700 Subject: [PATCH 048/375] host == nil -> host.length == 0 --- src/objective-c/GRPCClient/private/GRPCChannel.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index ae90821de03..495af5ebe87 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -82,7 +82,7 @@ + (nullable instancetype)createChannelWithConfiguration:(GRPCChannelConfiguration *)config { NSString *host = config.host; - if (host == nil || [host length] == 0) { + if (host.length == 0) { return nil; } From bc292b87c26ea8f6465443a152e86b3ed71e585b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 16 Oct 2018 18:14:34 -0700 Subject: [PATCH 049/375] polish attributes of GRPCChannelConfiguration --- src/objective-c/GRPCClient/private/GRPCChannelPool.h | 4 ++-- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 1145039549c..2a99089d2f2 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -31,8 +31,8 @@ NS_ASSUME_NONNULL_BEGIN @interface GRPCChannelConfiguration : NSObject -@property(atomic, strong, readwrite) NSString *host; -@property(atomic, strong, readwrite) GRPCCallOptions *callOptions; +@property(copy, readonly) NSString *host; +@property(strong, readonly) GRPCCallOptions *callOptions; @property(readonly) id channelFactory; @property(readonly) NSMutableDictionary *channelArgs; diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 37e42f8c75b..10a15f5255b 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -141,9 +141,7 @@ const NSTimeInterval kChannelDestroyDelay = 30; } - (nonnull id)copyWithZone:(nullable NSZone *)zone { - GRPCChannelConfiguration *newConfig = [[GRPCChannelConfiguration alloc] init]; - newConfig.host = _host; - newConfig.callOptions = _callOptions; + GRPCChannelConfiguration *newConfig = [[GRPCChannelConfiguration alloc] initWithHost:_host callOptions:_callOptions]; return newConfig; } From ad5485ae4ef4ec31cb6b3ed54876fd9868343388 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 16 Oct 2018 18:28:16 -0700 Subject: [PATCH 050/375] Make channel args immutable --- src/objective-c/GRPCClient/private/GRPCChannel.m | 10 ++++++++-- .../GRPCClient/private/GRPCChannelFactory.h | 2 +- src/objective-c/GRPCClient/private/GRPCChannelPool.h | 2 +- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 2 +- .../GRPCClient/private/GRPCCronetChannelFactory.h | 2 +- .../GRPCClient/private/GRPCCronetChannelFactory.m | 4 ++-- .../GRPCClient/private/GRPCInsecureChannelFactory.h | 2 +- .../GRPCClient/private/GRPCInsecureChannelFactory.m | 2 +- .../GRPCClient/private/GRPCSecureChannelFactory.h | 2 +- .../GRPCClient/private/GRPCSecureChannelFactory.m | 2 +- 10 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 495af5ebe87..2274fa5d6ab 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -86,8 +86,14 @@ return nil; } - NSMutableDictionary *channelArgs = config.channelArgs; - [channelArgs addEntriesFromDictionary:config.callOptions.additionalChannelArgs]; + NSDictionary *channelArgs; + if (config.callOptions.additionalChannelArgs.count != 0) { + NSMutableDictionary *args = [config.channelArgs copy]; + [args addEntriesFromDictionary:config.callOptions.additionalChannelArgs]; + channelArgs = args; + } else { + channelArgs = config.channelArgs; + } id factory = config.channelFactory; grpc_channel *unmanaged_channel = [factory createChannelWithHost:host channelArgs:channelArgs]; return [[GRPCChannel alloc] initWithUnmanagedChannel:unmanaged_channel configuration:config]; diff --git a/src/objective-c/GRPCClient/private/GRPCChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h index e44f8260dfd..492145da80b 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h @@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN @protocol GRPCChannelFactory - (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSMutableDictionary *)args; + channelArgs:(nullable NSDictionary *)args; @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 2a99089d2f2..1984919fa75 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -35,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN @property(strong, readonly) GRPCCallOptions *callOptions; @property(readonly) id channelFactory; -@property(readonly) NSMutableDictionary *channelArgs; +@property(readonly) NSDictionary *channelArgs; - (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 10a15f5255b..11c9d4be8dd 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -76,7 +76,7 @@ const NSTimeInterval kChannelDestroyDelay = 30; } } -- (NSMutableDictionary *)channelArgs { +- (NSDictionary *)channelArgs { NSMutableDictionary *args = [NSMutableDictionary new]; NSString *userAgent = @"grpc-objc/" GRPC_OBJC_VERSION_STRING; diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h index 97e1ae920a0..738dfdb7370 100644 --- a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h @@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN + (nullable instancetype)sharedInstance; - (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSMutableDictionary *)args; + channelArgs:(nullable NSDictionary *)args; - (nullable instancetype)init NS_UNAVAILABLE; diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m index 5c0fe16d39b..00b388ebbe0 100644 --- a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m @@ -53,7 +53,7 @@ NS_ASSUME_NONNULL_BEGIN } - (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSMutableDictionary *)args { + channelArgs:(nullable NSDictionary *)args { // Remove client authority filter since that is not supported args[@GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER] = [NSNumber numberWithInt:1]; @@ -81,7 +81,7 @@ NS_ASSUME_NONNULL_BEGIN } - (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSMutableArray *)args { + channelArgs:(nullable NSDictionary *)args { [NSException raise:NSInvalidArgumentException format:@"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."]; return nil; diff --git a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h index 905a181ca78..2d471aebed6 100644 --- a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h @@ -26,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN + (nullable instancetype)sharedInstance; - (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSMutableDictionary *)args; + channelArgs:(nullable NSDictionary *)args; - (nullable instancetype)init NS_UNAVAILABLE; diff --git a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m index 41860bf6ff5..d969b887b40 100644 --- a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m @@ -35,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN } - (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSMutableDictionary *)args { + channelArgs:(nullable NSDictionary *)args { grpc_channel_args *coreChannelArgs = BuildChannelArgs([args copy]); grpc_channel *unmanagedChannel = grpc_insecure_channel_create(host.UTF8String, coreChannelArgs, NULL); diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h index ab5eee478e1..82af0dc3e68 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h @@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN error:(NSError **)errorPtr; - (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSMutableDictionary *)args; + channelArgs:(nullable NSDictionary *)args; - (nullable instancetype)init NS_UNAVAILABLE; diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index a0d56e4bdc7..277823c4e33 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -110,7 +110,7 @@ NS_ASSUME_NONNULL_BEGIN } - (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSMutableArray *)args { + channelArgs:(nullable NSDictionary *)args { grpc_channel_args *coreChannelArgs = BuildChannelArgs([args copy]); grpc_channel *unmanagedChannel = grpc_secure_channel_create(_channelCreds, host.UTF8String, coreChannelArgs, NULL); From da42aa1c1ba38a12450e6b75b20281d6603b3d7e Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 17 Oct 2018 10:06:07 -0700 Subject: [PATCH 051/375] Add designated initializer annotation --- src/objective-c/GRPCClient/private/GRPCChannelPool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 1984919fa75..5ceb0b6d821 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -49,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init; -- (instancetype)initWithChannelDestroyDelay:(NSTimeInterval)channelDestroyDelay; +- (instancetype)initWithChannelDestroyDelay:(NSTimeInterval)channelDestroyDelay NS_DESIGNATED_INITIALIZER; /** * Return a channel with a particular configuration. If the channel does not exist, execute \a From 677ab86b4a8567197550d6969a4d5bd76b8206e1 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 17 Oct 2018 10:33:38 -0700 Subject: [PATCH 052/375] rename createChannel -> createChannelCallback --- src/objective-c/GRPCClient/private/GRPCChannel.m | 8 ++++---- src/objective-c/GRPCClient/private/GRPCChannelPool.h | 2 +- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 2274fa5d6ab..bea75d25a98 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -116,10 +116,10 @@ static GRPCChannelPool *gChannelPool; GRPCChannelConfiguration *channelConfig = [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; return [gChannelPool channelWithConfiguration:channelConfig - createChannel:^{ - return - [GRPCChannel createChannelWithConfiguration:channelConfig]; - }]; + createChannelCallback:^{ + return + [GRPCChannel createChannelWithConfiguration:channelConfig]; + }]; } + (void)closeOpenConnections { diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 5ceb0b6d821..48c35eacb01 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -56,7 +56,7 @@ NS_ASSUME_NONNULL_BEGIN * createChannel then add it in the pool. If the channel exists, increase its reference count. */ - (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration - createChannel:(GRPCChannel * (^)(void))createChannel; + createChannelCallback:(GRPCChannel * (^)(void))createChannelCallback; /** Decrease a channel's refcount. */ - (void)unrefChannelWithConfiguration:configuration; diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 11c9d4be8dd..680b268dcfa 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -338,14 +338,14 @@ const NSTimeInterval kChannelDestroyDelay = 30; } - (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration - createChannel:(GRPCChannel * (^)(void))createChannel { + createChannelCallback:(GRPCChannel * (^)(void))createChannelCallback { __block GRPCChannel *channel; dispatch_sync(_dispatchQueue, ^{ if ([self->_channelPool objectForKey:configuration]) { [self->_callRefs[configuration] refChannel]; channel = self->_channelPool[configuration]; } else { - channel = createChannel(); + channel = createChannelCallback(); self->_channelPool[configuration] = channel; GRPCChannelCallRef *callRef = [[GRPCChannelCallRef alloc] From 86ff72bb4736cb9333505baeb324386cfa24bcb9 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 17 Oct 2018 10:49:30 -0700 Subject: [PATCH 053/375] Add missing type information --- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 680b268dcfa..c46b9ddfc80 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -363,7 +363,7 @@ const NSTimeInterval kChannelDestroyDelay = 30; return channel; } -- (void)unrefChannelWithConfiguration:configuration { +- (void)unrefChannelWithConfiguration:(GRPCChannelConfiguration *)configuration { dispatch_sync(_dispatchQueue, ^{ if ([self->_channelPool objectForKey:configuration]) { [self->_callRefs[configuration] unrefChannel]; From 8fef0c87893ceda1c5bb7aaa09ddb8dfaefacbdb Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 17 Oct 2018 16:59:00 -0700 Subject: [PATCH 054/375] Rewrite the channel pool --- src/objective-c/GRPCClient/GRPCCall.m | 9 +- .../GRPCClient/private/GRPCChannel.h | 13 +- .../GRPCClient/private/GRPCChannel.m | 204 +++++++++++++++--- .../GRPCClient/private/GRPCChannelPool.h | 14 +- .../GRPCClient/private/GRPCChannelPool.m | 139 ++---------- .../tests/ChannelTests/ChannelPoolTest.m | 109 ++++------ 6 files changed, 262 insertions(+), 226 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 16acca249d6..5ffdfbaa89f 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -718,7 +718,14 @@ const char *kCFStreamVarName = "grpc_cfstream"; [[GRXConcurrentWriteable alloc] initWithWriteable:writeable dispatchQueue:_responseQueue]; _wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host path:_path callOptions:_callOptions]; - NSAssert(_wrappedCall, @"Error allocating RPC objects. Low memory?"); + if (_wrappedCall == nil) { + [self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeUnavailable + userInfo:@{ + NSLocalizedDescriptionKey : @"Failed to create call from channel." + }]]; + return; + } [self sendHeaders]; [self invokeCall]; diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index 7d5039a8a20..7a40638dc33 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -39,6 +39,11 @@ struct grpc_channel_credentials; + (nullable instancetype)channelWithHost:(nonnull NSString *)host callOptions:(nullable GRPCCallOptions *)callOptions; +/** + * Create a channel object with the signature \a config. + */ ++ (nullable instancetype)createChannelWithConfiguration:(nonnull GRPCChannelConfiguration *)config; + /** * Get a grpc core call object from this channel. */ @@ -46,13 +51,11 @@ struct grpc_channel_credentials; completionQueue:(nonnull GRPCCompletionQueue *)queue callOptions:(nonnull GRPCCallOptions *)callOptions; +- (void)unmanagedCallRef; + - (void)unmanagedCallUnref; -/** - * Create a channel object with the signature \a config. This function is used for testing only. Use - * channelWithHost:callOptions: in production. - */ -+ (nullable instancetype)createChannelWithConfiguration:(nonnull GRPCChannelConfiguration *)config; +- (void)disconnect; // TODO (mxyan): deprecate with GRPCCall:closeOpenConnections + (void)closeOpenConnections; diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index bea75d25a98..9e7e1ea1fc6 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -24,7 +24,6 @@ #import "GRPCChannelFactory.h" #import "GRPCChannelPool.h" #import "GRPCCompletionQueue.h" -#import "GRPCConnectivityMonitor.h" #import "GRPCCronetChannelFactory.h" #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" @@ -33,38 +32,180 @@ #import #import +// When all calls of a channel are destroyed, destroy the channel after this much seconds. +NSTimeInterval kChannelDestroyDelay = 30; + +/** + * Time the channel destroy when the channel's calls are unreffed. If there's new call, reset the + * timer. + */ +@interface GRPCChannelRef : NSObject + +- (instancetype)initWithDestroyDelay:(NSTimeInterval)destroyDelay + destroyChannelCallback:(void (^)())destroyChannelCallback; + +/** Add call ref count to the channel and maybe reset the timer. */ +- (void)refChannel; + +/** Reduce call ref count to the channel and maybe set the timer. */ +- (void)unrefChannel; + +/** Disconnect the channel immediately. */ +- (void)disconnect; + +@end + +@implementation GRPCChannelRef { + NSTimeInterval _destroyDelay; + // We use dispatch queue for this purpose since timer invalidation must happen on the same + // thread which issued the timer. + dispatch_queue_t _dispatchQueue; + void (^_destroyChannelCallback)(); + + NSUInteger _refCount; + NSTimer *_timer; + BOOL _disconnected; +} + +- (instancetype)initWithDestroyDelay:(NSTimeInterval)destroyDelay + destroyChannelCallback:(void (^)())destroyChannelCallback { + if ((self = [super init])) { + _destroyDelay = destroyDelay; + _destroyChannelCallback = destroyChannelCallback; + + _refCount = 1; + _timer = nil; + _disconnected = NO; + } + return self; +} + +// This function is protected by channel dispatch queue. +- (void)refChannel { + if (!_disconnected) { + _refCount++; + if (_timer) { + [_timer invalidate]; + _timer = nil; + } + } +} + +// This function is protected by channel dispatch queue. +- (void)unrefChannel { + if (!_disconnected) { + _refCount--; + if (_refCount == 0) { + if (_timer) { + [_timer invalidate]; + } + _timer = [NSTimer scheduledTimerWithTimeInterval:self->_destroyDelay + target:self + selector:@selector(timerFire:) + userInfo:nil + repeats:NO]; + } + } +} + +// This function is protected by channel dispatch queue. +- (void)disconnect { + if (!_disconnected) { + if (self->_timer != nil) { + [self->_timer invalidate]; + self->_timer = nil; + } + _disconnected = YES; + // Break retain loop + _destroyChannelCallback = nil; + } +} + +// This function is protected by channel dispatch queue. +- (void)timerFire:(NSTimer *)timer { + if (_disconnected || _timer == nil || _timer != timer) { + return; + } + _timer = nil; + _destroyChannelCallback(); + // Break retain loop + _destroyChannelCallback = nil; + _disconnected = YES; +} + +@end + @implementation GRPCChannel { GRPCChannelConfiguration *_configuration; grpc_channel *_unmanagedChannel; + GRPCChannelRef *_channelRef; + dispatch_queue_t _dispatchQueue; } - (grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(nonnull GRPCCompletionQueue *)queue callOptions:(GRPCCallOptions *)callOptions { - NSString *serverAuthority = callOptions.serverAuthority; - NSTimeInterval timeout = callOptions.timeout; - GPR_ASSERT(timeout >= 0); - grpc_slice host_slice = grpc_empty_slice(); - if (serverAuthority) { - host_slice = grpc_slice_from_copied_string(serverAuthority.UTF8String); - } - grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); - gpr_timespec deadline_ms = + __block grpc_call *call = nil; + dispatch_sync(_dispatchQueue, ^{ + if (self->_unmanagedChannel) { + NSString *serverAuthority = callOptions.serverAuthority; + NSTimeInterval timeout = callOptions.timeout; + GPR_ASSERT(timeout >= 0); + grpc_slice host_slice = grpc_empty_slice(); + if (serverAuthority) { + host_slice = grpc_slice_from_copied_string(serverAuthority.UTF8String); + } + grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); + gpr_timespec deadline_ms = timeout == 0 ? gpr_inf_future(GPR_CLOCK_REALTIME) - : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); - grpc_call *call = grpc_channel_create_call( - _unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, queue.unmanagedQueue, path_slice, - serverAuthority ? &host_slice : NULL, deadline_ms, NULL); - if (serverAuthority) { - grpc_slice_unref(host_slice); - } - grpc_slice_unref(path_slice); + : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); + call = grpc_channel_create_call( + self->_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, queue.unmanagedQueue, path_slice, + serverAuthority ? &host_slice : NULL, deadline_ms, NULL); + if (serverAuthority) { + grpc_slice_unref(host_slice); + } + grpc_slice_unref(path_slice); + } + }); return call; } +- (void)unmanagedCallRef { + dispatch_async(_dispatchQueue, ^{ + if (self->_unmanagedChannel) { + [self->_channelRef refChannel]; + } + }); +} + - (void)unmanagedCallUnref { - [gChannelPool unrefChannelWithConfiguration:_configuration]; + dispatch_async(_dispatchQueue, ^{ + if (self->_unmanagedChannel) { + [self->_channelRef unrefChannel]; + } + }); +} + +- (void)disconnect { + dispatch_async(_dispatchQueue, ^{ + if (self->_unmanagedChannel) { + grpc_channel_destroy(self->_unmanagedChannel); + self->_unmanagedChannel = nil; + [self->_channelRef disconnect]; + } + }); +} + +- (void)destroyChannel { + dispatch_async(_dispatchQueue, ^{ + if (self->_unmanagedChannel) { + grpc_channel_destroy(self->_unmanagedChannel); + self->_unmanagedChannel = nil; + [gChannelPool removeChannelWithConfiguration:self->_configuration]; + } + }); } - (nullable instancetype)initWithUnmanagedChannel:(nullable grpc_channel *)unmanagedChannel @@ -72,12 +213,22 @@ if ((self = [super init])) { _unmanagedChannel = unmanagedChannel; _configuration = configuration; + _channelRef = [[GRPCChannelRef alloc] initWithDestroyDelay:kChannelDestroyDelay destroyChannelCallback:^{ + [self destroyChannel]; + }]; + if (@available(iOS 8.0, *)) { + _dispatchQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + } else { + _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + } } return self; } - (void)dealloc { - grpc_channel_destroy(_unmanagedChannel); + if (_unmanagedChannel) { + grpc_channel_destroy(_unmanagedChannel); + } } + (nullable instancetype)createChannelWithConfiguration:(GRPCChannelConfiguration *)config { @@ -88,7 +239,7 @@ NSDictionary *channelArgs; if (config.callOptions.additionalChannelArgs.count != 0) { - NSMutableDictionary *args = [config.channelArgs copy]; + NSMutableDictionary *args = [config.channelArgs mutableCopy]; [args addEntriesFromDictionary:config.callOptions.additionalChannelArgs]; channelArgs = args; } else { @@ -115,15 +266,12 @@ static GRPCChannelPool *gChannelPool; GRPCChannelConfiguration *channelConfig = [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; - return [gChannelPool channelWithConfiguration:channelConfig - createChannelCallback:^{ - return - [GRPCChannel createChannelWithConfiguration:channelConfig]; - }]; + + return [gChannelPool channelWithConfiguration:channelConfig]; } + (void)closeOpenConnections { - [gChannelPool clear]; + [gChannelPool removeAndCloseAllChannels]; } @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 48c35eacb01..bd1350c15d2 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -49,20 +49,20 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init; -- (instancetype)initWithChannelDestroyDelay:(NSTimeInterval)channelDestroyDelay NS_DESIGNATED_INITIALIZER; - /** * Return a channel with a particular configuration. If the channel does not exist, execute \a * createChannel then add it in the pool. If the channel exists, increase its reference count. */ -- (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration - createChannelCallback:(GRPCChannel * (^)(void))createChannelCallback; +- (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration; -/** Decrease a channel's refcount. */ -- (void)unrefChannelWithConfiguration:configuration; +/** Remove a channel with particular configuration. */ +- (void)removeChannelWithConfiguration:(GRPCChannelConfiguration *)configuration; /** Clear all channels in the pool. */ -- (void)clear; +- (void)removeAllChannels; + +/** Clear all channels in the pool and destroy the channels. */ +- (void)removeAndCloseAllChannels; @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index c46b9ddfc80..7c0a8a8621d 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -18,6 +18,7 @@ #import +#import "GRPCChannel.h" #import "GRPCChannelFactory.h" #import "GRPCChannelPool.h" #import "GRPCConnectivityMonitor.h" @@ -31,9 +32,6 @@ extern const char *kCFStreamVarName; -// When all calls of a channel are destroyed, destroy the channel after this much seconds. -const NSTimeInterval kChannelDestroyDelay = 30; - @implementation GRPCChannelConfiguration - (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { @@ -216,109 +214,22 @@ const NSTimeInterval kChannelDestroyDelay = 30; @end -/** - * Time the channel destroy when the channel's calls are unreffed. If there's new call, reset the - * timer. - */ -@interface GRPCChannelCallRef : NSObject - -- (instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)configuration - destroyDelay:(NSTimeInterval)destroyDelay - dispatchQueue:(dispatch_queue_t)dispatchQueue - destroyChannel:(void (^)())destroyChannel; - -/** Add call ref count to the channel and maybe reset the timer. */ -- (void)refChannel; - -/** Reduce call ref count to the channel and maybe set the timer. */ -- (void)unrefChannel; - -@end - -@implementation GRPCChannelCallRef { - GRPCChannelConfiguration *_configuration; - NSTimeInterval _destroyDelay; - // We use dispatch queue for this purpose since timer invalidation must happen on the same - // thread which issued the timer. - dispatch_queue_t _dispatchQueue; - void (^_destroyChannel)(); - - NSUInteger _refCount; - NSTimer *_timer; -} - -- (instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)configuration - destroyDelay:(NSTimeInterval)destroyDelay - dispatchQueue:(dispatch_queue_t)dispatchQueue - destroyChannel:(void (^)())destroyChannel { - if ((self = [super init])) { - _configuration = configuration; - _destroyDelay = destroyDelay; - _dispatchQueue = dispatchQueue; - _destroyChannel = destroyChannel; - - _refCount = 0; - _timer = nil; - } - return self; -} - -// This function is protected by channel pool dispatch queue. -- (void)refChannel { - _refCount++; - if (_timer) { - [_timer invalidate]; - } - _timer = nil; -} - -// This function is protected by channel spool dispatch queue. -- (void)unrefChannel { - self->_refCount--; - if (self->_refCount == 0) { - if (self->_timer) { - [self->_timer invalidate]; - } - self->_timer = [NSTimer scheduledTimerWithTimeInterval:self->_destroyDelay - target:self - selector:@selector(timerFire:) - userInfo:nil - repeats:NO]; - } -} - -- (void)timerFire:(NSTimer *)timer { - dispatch_sync(_dispatchQueue, ^{ - if (self->_timer == nil || self->_timer != timer) { - return; - } - self->_timer = nil; - self->_destroyChannel(self->_configuration); - }); -} - -@end - #pragma mark GRPCChannelPool @implementation GRPCChannelPool { - NSTimeInterval _channelDestroyDelay; NSMutableDictionary *_channelPool; - NSMutableDictionary *_callRefs; // Dedicated queue for timer dispatch_queue_t _dispatchQueue; } - (instancetype)init { - return [self initWithChannelDestroyDelay:kChannelDestroyDelay]; -} - -- (instancetype)initWithChannelDestroyDelay:(NSTimeInterval)channelDestroyDelay { if ((self = [super init])) { - _channelDestroyDelay = channelDestroyDelay; _channelPool = [NSMutableDictionary dictionary]; - _callRefs = [NSMutableDictionary dictionary]; - _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + if (@available(iOS 8.0, *)) { + _dispatchQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + } else { + _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + } // Connectivity monitor is not required for CFStream char *enableCFStream = getenv(kCFStreamVarName); @@ -337,49 +248,43 @@ const NSTimeInterval kChannelDestroyDelay = 30; } } -- (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration - createChannelCallback:(GRPCChannel * (^)(void))createChannelCallback { +- (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration { __block GRPCChannel *channel; dispatch_sync(_dispatchQueue, ^{ if ([self->_channelPool objectForKey:configuration]) { - [self->_callRefs[configuration] refChannel]; channel = self->_channelPool[configuration]; + [channel unmanagedCallRef]; } else { - channel = createChannelCallback(); + channel = [GRPCChannel createChannelWithConfiguration:configuration]; self->_channelPool[configuration] = channel; - - GRPCChannelCallRef *callRef = [[GRPCChannelCallRef alloc] - initWithChannelConfiguration:configuration - destroyDelay:self->_channelDestroyDelay - dispatchQueue:self->_dispatchQueue - destroyChannel:^(GRPCChannelConfiguration *configuration) { - [self->_channelPool removeObjectForKey:configuration]; - [self->_callRefs removeObjectForKey:configuration]; - }]; - [callRef refChannel]; - self->_callRefs[configuration] = callRef; } }); return channel; } -- (void)unrefChannelWithConfiguration:(GRPCChannelConfiguration *)configuration { +- (void)removeChannelWithConfiguration:(GRPCChannelConfiguration *)configuration { + dispatch_async(_dispatchQueue, ^{ + [self->_channelPool removeObjectForKey:configuration]; + }); +} + +- (void)removeAllChannels { dispatch_sync(_dispatchQueue, ^{ - if ([self->_channelPool objectForKey:configuration]) { - [self->_callRefs[configuration] unrefChannel]; - } + self->_channelPool = [NSMutableDictionary dictionary]; }); } -- (void)clear { +- (void)removeAndCloseAllChannels { dispatch_sync(_dispatchQueue, ^{ + [self->_channelPool enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration * _Nonnull key, GRPCChannel * _Nonnull obj, BOOL * _Nonnull stop) { + [obj disconnect]; + }]; self->_channelPool = [NSMutableDictionary dictionary]; - self->_callRefs = [NSMutableDictionary dictionary]; }); } - (void)connectivityChange:(NSNotification *)note { - [self clear]; + [self removeAndCloseAllChannels]; } @end diff --git a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m index 9e1c9eca746..b195b747a12 100644 --- a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m +++ b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m @@ -44,83 +44,68 @@ NSString *kDummyHost = @"dummy.host"; [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; GRPCChannelConfiguration *config2 = [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options2]; - GRPCChannelPool *pool = [[GRPCChannelPool alloc] initWithChannelDestroyDelay:1]; + GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; - __weak XCTestExpectation *expectCreateChannel = - [self expectationWithDescription:@"Create first channel"]; - GRPCChannel *channel1 = - [pool channelWithConfiguration:config1 - createChannel:^{ - [expectCreateChannel fulfill]; - return [GRPCChannel createChannelWithConfiguration:config1]; - }]; - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; - GRPCChannel *channel2 = [pool channelWithConfiguration:config2 - createChannel:^{ - XCTFail(@"Should not create a second channel."); - return (GRPCChannel *)nil; - }]; + GRPCChannel *channel1 = [pool channelWithConfiguration:config1]; + GRPCChannel *channel2 = [pool channelWithConfiguration:config2]; XCTAssertEqual(channel1, channel2); } -- (void)testChannelTimeout { - NSTimeInterval kChannelDestroyDelay = 1.0; +- (void)testChannelRemove { GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; options1.transportType = GRPCTransportTypeInsecure; GRPCChannelConfiguration *config1 = [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; - GRPCChannelPool *pool = - [[GRPCChannelPool alloc] initWithChannelDestroyDelay:kChannelDestroyDelay]; + GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; GRPCChannel *channel1 = - [pool channelWithConfiguration:config1 - createChannel:^{ - return [GRPCChannel createChannelWithConfiguration:config1]; - }]; - [pool unrefChannelWithConfiguration:config1]; - __weak XCTestExpectation *expectTimerDone = [self expectationWithDescription:@"Timer elapse."]; - NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:kChannelDestroyDelay + 1 - repeats:NO - block:^(NSTimer *_Nonnull timer) { - [expectTimerDone fulfill]; - }]; - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; - timer = nil; + [pool channelWithConfiguration:config1]; + [pool removeChannelWithConfiguration:config1]; GRPCChannel *channel2 = - [pool channelWithConfiguration:config1 - createChannel:^{ - return [GRPCChannel createChannelWithConfiguration:config1]; - }]; + [pool channelWithConfiguration:config1]; XCTAssertNotEqual(channel1, channel2); } +extern NSTimeInterval kChannelDestroyDelay; + - (void)testChannelTimeoutCancel { - NSTimeInterval kChannelDestroyDelay = 3.0; + NSTimeInterval kOriginalInterval = kChannelDestroyDelay; + kChannelDestroyDelay = 3.0; GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; options1.transportType = GRPCTransportTypeInsecure; GRPCChannelConfiguration *config1 = [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; GRPCChannelPool *pool = - [[GRPCChannelPool alloc] initWithChannelDestroyDelay:kChannelDestroyDelay]; + [[GRPCChannelPool alloc] init]; GRPCChannel *channel1 = - [pool channelWithConfiguration:config1 - createChannel:^{ - return [GRPCChannel createChannelWithConfiguration:config1]; - }]; + [pool channelWithConfiguration:config1]; [channel1 unmanagedCallUnref]; sleep(1); GRPCChannel *channel2 = - [pool channelWithConfiguration:config1 - createChannel:^{ - return [GRPCChannel createChannelWithConfiguration:config1]; - }]; + [pool channelWithConfiguration:config1]; XCTAssertEqual(channel1, channel2); sleep((int)kChannelDestroyDelay + 2); GRPCChannel *channel3 = - [pool channelWithConfiguration:config1 - createChannel:^{ - return [GRPCChannel createChannelWithConfiguration:config1]; - }]; + [pool channelWithConfiguration:config1]; XCTAssertEqual(channel1, channel3); + kChannelDestroyDelay = kOriginalInterval; +} + +- (void)testChannelDisconnect { + NSString *kDummyHost = @"dummy.host"; + GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; + options1.transportType = GRPCTransportTypeInsecure; + GRPCCallOptions *options2 = [options1 copy]; + GRPCChannelConfiguration *config1 = + [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; + GRPCChannelConfiguration *config2 = + [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options2]; + GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; + + + GRPCChannel *channel1 = [pool channelWithConfiguration:config1]; + [pool removeAndCloseAllChannels]; + GRPCChannel *channel2 = [pool channelWithConfiguration:config2]; + XCTAssertNotEqual(channel1, channel2); } - (void)testClearChannels { @@ -132,31 +117,19 @@ NSString *kDummyHost = @"dummy.host"; [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; GRPCChannelConfiguration *config2 = [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options2]; - GRPCChannelPool *pool = [[GRPCChannelPool alloc] initWithChannelDestroyDelay:1]; + GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; GRPCChannel *channel1 = - [pool channelWithConfiguration:config1 - createChannel:^{ - return [GRPCChannel createChannelWithConfiguration:config1]; - }]; + [pool channelWithConfiguration:config1]; GRPCChannel *channel2 = - [pool channelWithConfiguration:config2 - createChannel:^{ - return [GRPCChannel createChannelWithConfiguration:config2]; - }]; + [pool channelWithConfiguration:config2]; XCTAssertNotEqual(channel1, channel2); - [pool clear]; + [pool removeAndCloseAllChannels]; GRPCChannel *channel3 = - [pool channelWithConfiguration:config1 - createChannel:^{ - return [GRPCChannel createChannelWithConfiguration:config1]; - }]; + [pool channelWithConfiguration:config1]; GRPCChannel *channel4 = - [pool channelWithConfiguration:config2 - createChannel:^{ - return [GRPCChannel createChannelWithConfiguration:config2]; - }]; + [pool channelWithConfiguration:config2]; XCTAssertNotEqual(channel1, channel3); XCTAssertNotEqual(channel2, channel4); } From d47f4b4c23a9dab2813e9b521d2545ea26d0105c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 17 Oct 2018 17:06:16 -0700 Subject: [PATCH 055/375] Check return value rather than error --- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 7c0a8a8621d..740eeaf6cf8 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -36,8 +36,8 @@ extern const char *kCFStreamVarName; - (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { if ((self = [super init])) { - _host = host; - _callOptions = callOptions; + _host = [host copy]; + _callOptions = [callOptions copy]; } return self; } @@ -56,9 +56,8 @@ extern const char *kCFStreamVarName; privateKey:_callOptions.PEMPrivateKey certChain:_callOptions.PEMCertChain error:&error]; - if (error) { + if (factory == nil) { NSLog(@"Error creating secure channel factory: %@", error); - return nil; } return factory; #ifdef GRPC_COMPILE_WITH_CRONET From f48c90606f246afab3a2aa1e1547578c4c34292a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 17 Oct 2018 17:46:09 -0700 Subject: [PATCH 056/375] Add isChannelOptionsEqualTo: to GRPCCallOptions --- src/objective-c/GRPCClient/GRPCCallOptions.h | 5 +++ src/objective-c/GRPCClient/GRPCCallOptions.m | 40 +++++++++++++++++++ .../GRPCClient/private/GRPCChannelPool.m | 38 +----------------- 3 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index e1a63f83b2e..bf03938b272 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -188,6 +188,11 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { */ @property(readonly) NSUInteger channelID; +/** + * Return if the channel options are equal to another object. + */ +- (BOOL)isChannelOptionsEqualTo:(GRPCCallOptions *)callOptions; + @end @interface GRPCMutableCallOptions : GRPCCallOptions diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index b19917d7784..1fc8c9fb1af 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -227,6 +227,46 @@ static NSUInteger kDefaultChannelID = 0; return newOptions; } +- (BOOL)isChannelOptionsEqualTo:(GRPCCallOptions *)callOptions { + if (!(callOptions.userAgentPrefix == _userAgentPrefix || + [callOptions.userAgentPrefix isEqualToString:_userAgentPrefix])) + return NO; + if (!(callOptions.responseSizeLimit == _responseSizeLimit)) return NO; + if (!(callOptions.compressAlgorithm == _compressAlgorithm)) return NO; + if (!(callOptions.enableRetry == _enableRetry)) return NO; + if (!(callOptions.keepaliveInterval == _keepaliveInterval)) return NO; + if (!(callOptions.keepaliveTimeout == _keepaliveTimeout)) return NO; + if (!(callOptions.connectMinTimeout == _connectMinTimeout)) return NO; + if (!(callOptions.connectInitialBackoff == _connectInitialBackoff)) return NO; + if (!(callOptions.connectMaxBackoff == _connectMaxBackoff)) return NO; + if (!(callOptions.additionalChannelArgs == _additionalChannelArgs || + [callOptions.additionalChannelArgs + isEqualToDictionary:_additionalChannelArgs])) + return NO; + if (!(callOptions.PEMRootCertificates == _PEMRootCertificates || + [callOptions.PEMRootCertificates isEqualToString:_PEMRootCertificates])) + return NO; + if (!(callOptions.PEMPrivateKey == _PEMPrivateKey || + [callOptions.PEMPrivateKey isEqualToString:_PEMPrivateKey])) + return NO; + if (!(callOptions.PEMCertChain == _PEMCertChain || + [callOptions.PEMCertChain isEqualToString:_PEMCertChain])) + return NO; + if (!(callOptions.hostNameOverride == _hostNameOverride || + [callOptions.hostNameOverride isEqualToString:_hostNameOverride])) + return NO; + if (!(callOptions.transportType == _transportType)) return NO; + if (!(callOptions.logContext == _logContext || + [callOptions.logContext isEqual:_logContext])) + return NO; + if (!(callOptions.channelPoolDomain == _channelPoolDomain || + [callOptions.channelPoolDomain isEqualToString:_channelPoolDomain])) + return NO; + if (!(callOptions.channelID == _channelID)) return NO; + + return YES; +} + @end @implementation GRPCMutableCallOptions diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 740eeaf6cf8..995212fdb6d 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -68,8 +68,6 @@ extern const char *kCFStreamVarName; return [GRPCCronetChannelFactory sharedInstance]; case GRPCTransportTypeInsecure: return [GRPCInsecureChannelFactory sharedInstance]; - default: - GPR_UNREACHABLE_CODE(return nil); } } @@ -147,41 +145,7 @@ extern const char *kCFStreamVarName; NSAssert([object isKindOfClass:[GRPCChannelConfiguration class]], @"Illegal :isEqual"); GRPCChannelConfiguration *obj = (GRPCChannelConfiguration *)object; if (!(obj.host == _host || [obj.host isEqualToString:_host])) return NO; - if (!(obj.callOptions.userAgentPrefix == _callOptions.userAgentPrefix || - [obj.callOptions.userAgentPrefix isEqualToString:_callOptions.userAgentPrefix])) - return NO; - if (!(obj.callOptions.responseSizeLimit == _callOptions.responseSizeLimit)) return NO; - if (!(obj.callOptions.compressAlgorithm == _callOptions.compressAlgorithm)) return NO; - if (!(obj.callOptions.enableRetry == _callOptions.enableRetry)) return NO; - if (!(obj.callOptions.keepaliveInterval == _callOptions.keepaliveInterval)) return NO; - if (!(obj.callOptions.keepaliveTimeout == _callOptions.keepaliveTimeout)) return NO; - if (!(obj.callOptions.connectMinTimeout == _callOptions.connectMinTimeout)) return NO; - if (!(obj.callOptions.connectInitialBackoff == _callOptions.connectInitialBackoff)) return NO; - if (!(obj.callOptions.connectMaxBackoff == _callOptions.connectMaxBackoff)) return NO; - if (!(obj.callOptions.additionalChannelArgs == _callOptions.additionalChannelArgs || - [obj.callOptions.additionalChannelArgs - isEqualToDictionary:_callOptions.additionalChannelArgs])) - return NO; - if (!(obj.callOptions.PEMRootCertificates == _callOptions.PEMRootCertificates || - [obj.callOptions.PEMRootCertificates isEqualToString:_callOptions.PEMRootCertificates])) - return NO; - if (!(obj.callOptions.PEMPrivateKey == _callOptions.PEMPrivateKey || - [obj.callOptions.PEMPrivateKey isEqualToString:_callOptions.PEMPrivateKey])) - return NO; - if (!(obj.callOptions.PEMCertChain == _callOptions.PEMCertChain || - [obj.callOptions.PEMCertChain isEqualToString:_callOptions.PEMCertChain])) - return NO; - if (!(obj.callOptions.hostNameOverride == _callOptions.hostNameOverride || - [obj.callOptions.hostNameOverride isEqualToString:_callOptions.hostNameOverride])) - return NO; - if (!(obj.callOptions.transportType == _callOptions.transportType)) return NO; - if (!(obj.callOptions.logContext == _callOptions.logContext || - [obj.callOptions.logContext isEqual:_callOptions.logContext])) - return NO; - if (!(obj.callOptions.channelPoolDomain == _callOptions.channelPoolDomain || - [obj.callOptions.channelPoolDomain isEqualToString:_callOptions.channelPoolDomain])) - return NO; - if (!(obj.callOptions.channelID == _callOptions.channelID)) return NO; + if (!(obj.callOptions == _callOptions || [obj.callOptions isChannelOptionsEqualTo:_callOptions])) return NO; return YES; } From d578b4321812715de7fe615a1ae8624fd05f1c69 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 17 Oct 2018 18:01:14 -0700 Subject: [PATCH 057/375] Add channelOptionsHash: to GRPCCChannelOptions --- src/objective-c/GRPCClient/GRPCCallOptions.h | 5 ++++ src/objective-c/GRPCClient/GRPCCallOptions.m | 24 +++++++++++++++++++ .../GRPCClient/private/GRPCChannelPool.m | 19 +-------------- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index bf03938b272..8864bcb8a2f 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -193,6 +193,11 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { */ - (BOOL)isChannelOptionsEqualTo:(GRPCCallOptions *)callOptions; +/** + * Hash for channel options. + */ +@property(readonly) NSUInteger channelOptionsHash; + @end @interface GRPCMutableCallOptions : GRPCCallOptions diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 1fc8c9fb1af..8d2b84b7484 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -267,6 +267,30 @@ static NSUInteger kDefaultChannelID = 0; return YES; } +- (NSUInteger)channelOptionsHash { + NSUInteger result = 0; + result ^= _userAgentPrefix.hash; + result ^= _responseSizeLimit; + result ^= _compressAlgorithm; + result ^= _enableRetry; + result ^= (unsigned int)(_keepaliveInterval * 1000); + result ^= (unsigned int)(_keepaliveTimeout * 1000); + result ^= (unsigned int)(_connectMinTimeout * 1000); + result ^= (unsigned int)(_connectInitialBackoff * 1000); + result ^= (unsigned int)(_connectMaxBackoff * 1000); + result ^= _additionalChannelArgs.hash; + result ^= _PEMRootCertificates.hash; + result ^= _PEMPrivateKey.hash; + result ^= _PEMCertChain.hash; + result ^= _hostNameOverride.hash; + result ^= _transportType; + result ^= [_logContext hash]; + result ^= _channelPoolDomain.hash; + result ^= _channelID; + + return result; +} + @end @implementation GRPCMutableCallOptions diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 995212fdb6d..4fae7d57ca2 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -153,24 +153,7 @@ extern const char *kCFStreamVarName; - (NSUInteger)hash { NSUInteger result = 0; result ^= _host.hash; - result ^= _callOptions.userAgentPrefix.hash; - result ^= _callOptions.responseSizeLimit; - result ^= _callOptions.compressAlgorithm; - result ^= _callOptions.enableRetry; - result ^= (unsigned int)(_callOptions.keepaliveInterval * 1000); - result ^= (unsigned int)(_callOptions.keepaliveTimeout * 1000); - result ^= (unsigned int)(_callOptions.connectMinTimeout * 1000); - result ^= (unsigned int)(_callOptions.connectInitialBackoff * 1000); - result ^= (unsigned int)(_callOptions.connectMaxBackoff * 1000); - result ^= _callOptions.additionalChannelArgs.hash; - result ^= _callOptions.PEMRootCertificates.hash; - result ^= _callOptions.PEMPrivateKey.hash; - result ^= _callOptions.PEMCertChain.hash; - result ^= _callOptions.hostNameOverride.hash; - result ^= _callOptions.transportType; - result ^= [_callOptions.logContext hash]; - result ^= _callOptions.channelPoolDomain.hash; - result ^= _callOptions.channelID; + result ^= _callOptions.channelOptionsHash; return result; } From 34e4db810fcf08f51ee5104561426fc736308216 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 17 Oct 2018 18:04:42 -0700 Subject: [PATCH 058/375] Take advantage of nil messaging --- src/objective-c/GRPCClient/private/GRPCChannel.m | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 9e7e1ea1fc6..5e0b37c1b82 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -84,10 +84,8 @@ NSTimeInterval kChannelDestroyDelay = 30; - (void)refChannel { if (!_disconnected) { _refCount++; - if (_timer) { - [_timer invalidate]; - _timer = nil; - } + [_timer invalidate]; + _timer = nil; } } @@ -96,9 +94,7 @@ NSTimeInterval kChannelDestroyDelay = 30; if (!_disconnected) { _refCount--; if (_refCount == 0) { - if (_timer) { - [_timer invalidate]; - } + [_timer invalidate]; _timer = [NSTimer scheduledTimerWithTimeInterval:self->_destroyDelay target:self selector:@selector(timerFire:) @@ -111,10 +107,8 @@ NSTimeInterval kChannelDestroyDelay = 30; // This function is protected by channel dispatch queue. - (void)disconnect { if (!_disconnected) { - if (self->_timer != nil) { - [self->_timer invalidate]; - self->_timer = nil; - } + [_timer invalidate]; + _timer = nil; _disconnected = YES; // Break retain loop _destroyChannelCallback = nil; From be4ab30899f6ae91e07f02c33297ca462f778296 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 17 Oct 2018 18:05:22 -0700 Subject: [PATCH 059/375] Remove dereferencing --- src/objective-c/GRPCClient/private/GRPCChannel.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 5e0b37c1b82..a17cc253feb 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -95,7 +95,7 @@ NSTimeInterval kChannelDestroyDelay = 30; _refCount--; if (_refCount == 0) { [_timer invalidate]; - _timer = [NSTimer scheduledTimerWithTimeInterval:self->_destroyDelay + _timer = [NSTimer scheduledTimerWithTimeInterval:_destroyDelay target:self selector:@selector(timerFire:) userInfo:nil From 67a4eb6623d0870992051d0280b78dd7a2b2c0ff Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 09:53:41 -0700 Subject: [PATCH 060/375] Lock GRPCCall in GRPCAuthorizatioProtocol --- src/objective-c/GRPCClient/GRPCCall.m | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 5ffdfbaa89f..68f0f8892d7 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -461,10 +461,12 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)cancel { - if (!self.isWaitingForToken) { - [self cancelCall]; - } else { - self.isWaitingForToken = NO; + @synchronized (self) { + if (!self.isWaitingForToken) { + [self cancelCall]; + } else { + self.isWaitingForToken = NO; + } } [self maybeFinishWithError:[NSError @@ -779,14 +781,18 @@ const char *kCFStreamVarName = "grpc_cfstream"; _callOptions = callOptions; } if (_callOptions.authTokenProvider != nil) { - self.isWaitingForToken = YES; + @synchronized (self) { + self.isWaitingForToken = YES; + } [self.tokenProvider getTokenWithHandler:^(NSString *token) { - if (self.isWaitingForToken) { - if (token) { - self->_fetchedOauth2AccessToken = [token copy]; + @synchronized (self) { + if (self.isWaitingForToken) { + if (token) { + self->_fetchedOauth2AccessToken = [token copy]; + } + [self startCallWithWriteable:writeable]; + self.isWaitingForToken = NO; } - [self startCallWithWriteable:writeable]; - self.isWaitingForToken = NO; } }]; } else { From ac211b4214b9a5bbc00631b61af396557837b9fb Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 10:39:48 -0700 Subject: [PATCH 061/375] Use dispatch_after for delayed destroy of channel --- .../GRPCClient/private/GRPCChannel.m | 87 ++++++++++--------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index a17cc253feb..a91949684c4 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -57,14 +57,13 @@ NSTimeInterval kChannelDestroyDelay = 30; @implementation GRPCChannelRef { NSTimeInterval _destroyDelay; - // We use dispatch queue for this purpose since timer invalidation must happen on the same - // thread which issued the timer. - dispatch_queue_t _dispatchQueue; void (^_destroyChannelCallback)(); NSUInteger _refCount; - NSTimer *_timer; BOOL _disconnected; + dispatch_queue_t _dispatchQueue; + dispatch_queue_t _timerQueue; + NSDate *_lastDispatch; } - (instancetype)initWithDestroyDelay:(NSTimeInterval)destroyDelay @@ -74,57 +73,65 @@ NSTimeInterval kChannelDestroyDelay = 30; _destroyChannelCallback = destroyChannelCallback; _refCount = 1; - _timer = nil; _disconnected = NO; + if (@available(iOS 8.0, *)) { + _dispatchQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + _timerQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_DEFAULT, -1)); + } else { + _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + _timerQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT); + } + _lastDispatch = nil; } return self; } -// This function is protected by channel dispatch queue. - (void)refChannel { - if (!_disconnected) { - _refCount++; - [_timer invalidate]; - _timer = nil; - } + dispatch_async(_dispatchQueue, ^{ + if (!self->_disconnected) { + self->_refCount++; + self->_lastDispatch = nil; + } + }); } -// This function is protected by channel dispatch queue. - (void)unrefChannel { - if (!_disconnected) { - _refCount--; - if (_refCount == 0) { - [_timer invalidate]; - _timer = [NSTimer scheduledTimerWithTimeInterval:_destroyDelay - target:self - selector:@selector(timerFire:) - userInfo:nil - repeats:NO]; + dispatch_async(_dispatchQueue, ^{ + if (!self->_disconnected) { + self->_refCount--; + if (self->_refCount == 0) { + self->_lastDispatch = [NSDate date]; + dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)kChannelDestroyDelay * 1e9); + dispatch_after(delay, self->_timerQueue, ^{ + [self timerFire]; + }); + } } - } + }); } -// This function is protected by channel dispatch queue. - (void)disconnect { - if (!_disconnected) { - [_timer invalidate]; - _timer = nil; - _disconnected = YES; - // Break retain loop - _destroyChannelCallback = nil; - } + dispatch_async(_dispatchQueue, ^{ + if (!self->_disconnected) { + self->_lastDispatch = nil; + self->_disconnected = YES; + // Break retain loop + self->_destroyChannelCallback = nil; + } + }); } -// This function is protected by channel dispatch queue. -- (void)timerFire:(NSTimer *)timer { - if (_disconnected || _timer == nil || _timer != timer) { - return; - } - _timer = nil; - _destroyChannelCallback(); - // Break retain loop - _destroyChannelCallback = nil; - _disconnected = YES; +- (void)timerFire { + dispatch_async(_dispatchQueue, ^{ + if (self->_disconnected || self->_lastDispatch == nil || -[self->_lastDispatch timeIntervalSinceNow] < -kChannelDestroyDelay) { + return; + } + self->_lastDispatch = nil; + self->_disconnected = YES; + self->_destroyChannelCallback(); + // Break retain loop + self->_destroyChannelCallback = nil; + }); } @end From 7871fedfd6e594ac5935d2018b9680e18979991c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 11:13:22 -0700 Subject: [PATCH 062/375] always unregister observer --- src/objective-c/GRPCClient/GRPCCall.m | 6 +----- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 68f0f8892d7..a142c669db0 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -445,11 +445,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; [_responseWriteable enqueueSuccessfulCompletion]; } - // Connectivity monitor is not required for CFStream - char *enableCFStream = getenv(kCFStreamVarName); - if (enableCFStream == nil || enableCFStream[0] != '1') { - [GRPCConnectivityMonitor unregisterObserver:self]; - } + [GRPCConnectivityMonitor unregisterObserver:self]; // If the call isn't retained anywhere else, it can be deallocated now. _retainSelf = nil; diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 4fae7d57ca2..5707e7f9507 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -187,11 +187,7 @@ extern const char *kCFStreamVarName; } - (void)dealloc { - // Connectivity monitor is not required for CFStream - char *enableCFStream = getenv(kCFStreamVarName); - if (enableCFStream == nil || enableCFStream[0] != '1') { - [GRPCConnectivityMonitor unregisterObserver:self]; - } + [GRPCConnectivityMonitor unregisterObserver:self]; } - (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration { From 4af17518c023cd32bc98c796d6f99e4f4978f49a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 11:42:41 -0700 Subject: [PATCH 063/375] Use simple locking in GRPCChannelPool --- .../GRPCClient/private/GRPCChannelPool.m | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 5707e7f9507..bfc624eb4ea 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -164,18 +164,11 @@ extern const char *kCFStreamVarName; @implementation GRPCChannelPool { NSMutableDictionary *_channelPool; - // Dedicated queue for timer - dispatch_queue_t _dispatchQueue; } - (instancetype)init { if ((self = [super init])) { _channelPool = [NSMutableDictionary dictionary]; - if (@available(iOS 8.0, *)) { - _dispatchQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); - } else { - _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); - } // Connectivity monitor is not required for CFStream char *enableCFStream = getenv(kCFStreamVarName); @@ -192,37 +185,39 @@ extern const char *kCFStreamVarName; - (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration { __block GRPCChannel *channel; - dispatch_sync(_dispatchQueue, ^{ - if ([self->_channelPool objectForKey:configuration]) { - channel = self->_channelPool[configuration]; + @synchronized(self) { + if ([_channelPool objectForKey:configuration]) { + channel = _channelPool[configuration]; [channel unmanagedCallRef]; } else { channel = [GRPCChannel createChannelWithConfiguration:configuration]; - self->_channelPool[configuration] = channel; + if (channel != nil) { + _channelPool[configuration] = channel; + } } - }); + } return channel; } - (void)removeChannelWithConfiguration:(GRPCChannelConfiguration *)configuration { - dispatch_async(_dispatchQueue, ^{ + @synchronized(self) { [self->_channelPool removeObjectForKey:configuration]; - }); + } } - (void)removeAllChannels { - dispatch_sync(_dispatchQueue, ^{ - self->_channelPool = [NSMutableDictionary dictionary]; - }); + @synchronized(self) { + _channelPool = [NSMutableDictionary dictionary]; + } } - (void)removeAndCloseAllChannels { - dispatch_sync(_dispatchQueue, ^{ - [self->_channelPool enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration * _Nonnull key, GRPCChannel * _Nonnull obj, BOOL * _Nonnull stop) { + @synchronized(self) { + [_channelPool enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration * _Nonnull key, GRPCChannel * _Nonnull obj, BOOL * _Nonnull stop) { [obj disconnect]; }]; - self->_channelPool = [NSMutableDictionary dictionary]; - }); + _channelPool = [NSMutableDictionary dictionary]; + } } - (void)connectivityChange:(NSNotification *)note { From 3bdf794bd031162913f533a2a9535f4066a41abd Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 11:50:00 -0700 Subject: [PATCH 064/375] Handle channel nil case --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index a142c669db0..0facf97e09e 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -720,7 +720,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; [self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeUnavailable userInfo:@{ - NSLocalizedDescriptionKey : @"Failed to create call from channel." + NSLocalizedDescriptionKey : @"Failed to create call or channel." }]]; return; } From a0f83554bbe47d9d99d6e3146a8ec7ba3a129b63 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 12:11:29 -0700 Subject: [PATCH 065/375] remove channel from pool with pointer rather than config --- src/objective-c/GRPCClient/private/GRPCChannel.m | 2 +- src/objective-c/GRPCClient/private/GRPCChannelPool.h | 4 ++-- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 8 ++++++-- src/objective-c/tests/ChannelTests/ChannelPoolTest.m | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index a91949684c4..2420988f427 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -204,7 +204,7 @@ NSTimeInterval kChannelDestroyDelay = 30; if (self->_unmanagedChannel) { grpc_channel_destroy(self->_unmanagedChannel); self->_unmanagedChannel = nil; - [gChannelPool removeChannelWithConfiguration:self->_configuration]; + [gChannelPool removeChannel:self]; } }); } diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index bd1350c15d2..e9c2ef2bd14 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -55,8 +55,8 @@ NS_ASSUME_NONNULL_BEGIN */ - (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration; -/** Remove a channel with particular configuration. */ -- (void)removeChannelWithConfiguration:(GRPCChannelConfiguration *)configuration; +/** Remove a channel from the pool. */ +- (void)removeChannel:(GRPCChannel *)channel; /** Clear all channels in the pool. */ - (void)removeAllChannels; diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index bfc624eb4ea..b5b3ff60efa 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -199,9 +199,13 @@ extern const char *kCFStreamVarName; return channel; } -- (void)removeChannelWithConfiguration:(GRPCChannelConfiguration *)configuration { +- (void)removeChannel:(GRPCChannel *)channel { @synchronized(self) { - [self->_channelPool removeObjectForKey:configuration]; + [_channelPool enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration * _Nonnull key, GRPCChannel * _Nonnull obj, BOOL * _Nonnull stop) { + if (obj == channel) { + [self->_channelPool removeObjectForKey:key]; + } + }]; } } diff --git a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m index b195b747a12..db64ac6339e 100644 --- a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m +++ b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m @@ -59,7 +59,7 @@ NSString *kDummyHost = @"dummy.host"; GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; GRPCChannel *channel1 = [pool channelWithConfiguration:config1]; - [pool removeChannelWithConfiguration:config1]; + [pool removeChannel:channel1]; GRPCChannel *channel2 = [pool channelWithConfiguration:config1]; XCTAssertNotEqual(channel1, channel2); From 1a88be4edfba35732236956e6e835ecd5c9de13d Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 13:56:03 -0700 Subject: [PATCH 066/375] Prefix functions in ChannelArgsUtil --- src/objective-c/GRPCClient/private/ChannelArgsUtil.h | 4 ++-- src/objective-c/GRPCClient/private/ChannelArgsUtil.m | 4 ++-- .../GRPCClient/private/GRPCInsecureChannelFactory.m | 4 ++-- src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/objective-c/GRPCClient/private/ChannelArgsUtil.h b/src/objective-c/GRPCClient/private/ChannelArgsUtil.h index d9d6933c6bb..d0be4849105 100644 --- a/src/objective-c/GRPCClient/private/ChannelArgsUtil.h +++ b/src/objective-c/GRPCClient/private/ChannelArgsUtil.h @@ -20,6 +20,6 @@ #include -void FreeChannelArgs(grpc_channel_args* channel_args); +void GRPCFreeChannelArgs(grpc_channel_args* channel_args); -grpc_channel_args* BuildChannelArgs(NSDictionary* dictionary); +grpc_channel_args* GRPCBuildChannelArgs(NSDictionary* dictionary); diff --git a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m index b26fb12d597..8669f79992c 100644 --- a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m +++ b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m @@ -39,7 +39,7 @@ static int cmp_pointer_arg(void *p, void *q) { return p == q; } static const grpc_arg_pointer_vtable objc_arg_vtable = {copy_pointer_arg, destroy_pointer_arg, cmp_pointer_arg}; -void FreeChannelArgs(grpc_channel_args *channel_args) { +void GRPCFreeChannelArgs(grpc_channel_args *channel_args) { for (size_t i = 0; i < channel_args->num_args; ++i) { grpc_arg *arg = &channel_args->args[i]; gpr_free(arg->key); @@ -58,7 +58,7 @@ void FreeChannelArgs(grpc_channel_args *channel_args) { * value responds to @c @selector(intValue). Otherwise, an exception will be raised. The caller of * this function is responsible for calling @c freeChannelArgs on a non-NULL returned value. */ -grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) { +grpc_channel_args *GRPCBuildChannelArgs(NSDictionary *dictionary) { if (!dictionary) { return NULL; } diff --git a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m index d969b887b40..5773f2d9af1 100644 --- a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m @@ -36,10 +36,10 @@ NS_ASSUME_NONNULL_BEGIN - (nullable grpc_channel *)createChannelWithHost:(NSString *)host channelArgs:(nullable NSDictionary *)args { - grpc_channel_args *coreChannelArgs = BuildChannelArgs([args copy]); + grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs([args copy]); grpc_channel *unmanagedChannel = grpc_insecure_channel_create(host.UTF8String, coreChannelArgs, NULL); - FreeChannelArgs(coreChannelArgs); + GRPCFreeChannelArgs(coreChannelArgs); return unmanagedChannel; } diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 277823c4e33..8a00d080a11 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -111,10 +111,10 @@ NS_ASSUME_NONNULL_BEGIN - (nullable grpc_channel *)createChannelWithHost:(NSString *)host channelArgs:(nullable NSDictionary *)args { - grpc_channel_args *coreChannelArgs = BuildChannelArgs([args copy]); + grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs([args copy]); grpc_channel *unmanagedChannel = grpc_secure_channel_create(_channelCreds, host.UTF8String, coreChannelArgs, NULL); - FreeChannelArgs(coreChannelArgs); + GRPCFreeChannelArgs(coreChannelArgs); return unmanagedChannel; } From e114983643479d20e44536cb704f5738cb848329 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 13:57:53 -0700 Subject: [PATCH 067/375] NULL return for non-id type --- src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m index 00b388ebbe0..70675784678 100644 --- a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m @@ -84,7 +84,7 @@ NS_ASSUME_NONNULL_BEGIN channelArgs:(nullable NSDictionary *)args { [NSException raise:NSInvalidArgumentException format:@"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."]; - return nil; + return NULL; } @end From 31de6d67e7557208b9d1e8c37300fb3f6b45a47d Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 14:00:07 -0700 Subject: [PATCH 068/375] Make GRPCHost.callOptions immutable --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- src/objective-c/GRPCClient/private/GRPCHost.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 0facf97e09e..3f77aaafb3a 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -751,7 +751,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; GRPCMutableCallOptions *callOptions; if ([GRPCHost isHostConfigured:_host]) { GRPCHost *hostConfig = [GRPCHost hostWithAddress:_host]; - callOptions = hostConfig.callOptions; + callOptions = [hostConfig.callOptions mutableCopy]; } else { callOptions = [[GRPCMutableCallOptions alloc] init]; } diff --git a/src/objective-c/GRPCClient/private/GRPCHost.h b/src/objective-c/GRPCClient/private/GRPCHost.h index 32d3585351e..e321363bcbf 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.h +++ b/src/objective-c/GRPCClient/private/GRPCHost.h @@ -66,7 +66,7 @@ struct grpc_channel_credentials; @property(atomic, readwrite) GRPCTransportType transportType; -@property(readonly) GRPCMutableCallOptions *callOptions; +@property(readonly) GRPCCallOptions *callOptions; + (BOOL)isHostConfigured:(NSString *)address; From d92c62fcde8559393aee346e5518faecb6f1301b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 15:22:16 -0700 Subject: [PATCH 069/375] Enable Cronet with old API --- src/objective-c/GRPCClient/private/GRPCHost.m | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 7c31b106360..6bb5996a1ba 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -113,7 +113,21 @@ static NSMutableDictionary *kHostCache; options.PEMPrivateKey = _PEMPrivateKey; options.PEMCertChain = _pemCertChain; options.hostNameOverride = _hostNameOverride; - options.transportType = _transportType; +#ifdef GRPC_COMPILE_WITH_CRONET + // By old API logic, insecure channel precedes Cronet channel; Cronet channel preceeds default + // channel. + if ([GRPCCall isUsingCronet]) { + if (_transportType == GRPCTransportTypeInsecure) { + options.transportType = GRPCTransportTypeInsecure; + } else { + NSAssert(_transportType == GRPCTransportTypeDefault, @"Invalid transport type"); + options.transportType = GRPCTransportTypeCronet; + } + } else +#endif + { + options.transportType = _transportType; + } options.logContext = _logContext; return options; From 1084f49c310b62ff5a06fa5f6c262f813dce75a5 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 15:22:38 -0700 Subject: [PATCH 070/375] rename kHostCache->gHostCache --- src/objective-c/GRPCClient/private/GRPCHost.m | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 6bb5996a1ba..c1992b84e99 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -35,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN -static NSMutableDictionary *kHostCache; +static NSMutableDictionary *gHostCache; @implementation GRPCHost { NSString *_PEMRootCertificates; @@ -65,10 +65,10 @@ static NSMutableDictionary *kHostCache; // Look up the GRPCHost in the cache. static dispatch_once_t cacheInitialization; dispatch_once(&cacheInitialization, ^{ - kHostCache = [NSMutableDictionary dictionary]; + gHostCache = [NSMutableDictionary dictionary]; }); - @synchronized(kHostCache) { - GRPCHost *cachedHost = kHostCache[address]; + @synchronized(gHostCache) { + GRPCHost *cachedHost = gHostCache[address]; if (cachedHost) { return cachedHost; } @@ -76,15 +76,15 @@ static NSMutableDictionary *kHostCache; if ((self = [super init])) { _address = address; _retryEnabled = YES; - kHostCache[address] = self; + gHostCache[address] = self; } } return self; } + (void)resetAllHostSettings { - @synchronized(kHostCache) { - kHostCache = [NSMutableDictionary dictionary]; + @synchronized(gHostCache) { + gHostCache = [NSMutableDictionary dictionary]; } } @@ -140,8 +140,8 @@ static NSMutableDictionary *kHostCache; address = [hostURL.host stringByAppendingString:@":443"]; } __block GRPCHost *cachedHost; - @synchronized (kHostCache) { - cachedHost = kHostCache[address]; + @synchronized (gHostCache) { + cachedHost = gHostCache[address]; } return (cachedHost != nil); } From b9e522420741024e05f8ef3ccde7fbeeaaea2234 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 15:28:15 -0700 Subject: [PATCH 071/375] more copy settings --- src/objective-c/GRPCClient/private/GRPCHost.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index c1992b84e99..032b274ffcc 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -92,9 +92,9 @@ static NSMutableDictionary *gHostCache; withPrivateKey:(nullable NSString *)pemPrivateKey withCertChain:(nullable NSString *)pemCertChain error:(NSError **)errorPtr { - _PEMRootCertificates = pemRootCerts; - _PEMPrivateKey = pemPrivateKey; - _pemCertChain = pemCertChain; + _PEMRootCertificates = [pemRootCerts copy]; + _PEMPrivateKey = [pemPrivateKey copy]; + _pemCertChain = [pemCertChain copy]; return YES; } From 4201ad1681064d591f6a47fa5b3c6f824cb7cecb Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 16:05:18 -0700 Subject: [PATCH 072/375] add callOptionsForHost: to GRPCHost --- src/objective-c/GRPCClient/GRPCCall.m | 8 ++----- src/objective-c/GRPCClient/private/GRPCHost.h | 4 +--- src/objective-c/GRPCClient/private/GRPCHost.m | 22 ++++++++++++------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 3f77aaafb3a..399206a346c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -749,12 +749,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; if (_callOptions == nil) { GRPCMutableCallOptions *callOptions; - if ([GRPCHost isHostConfigured:_host]) { - GRPCHost *hostConfig = [GRPCHost hostWithAddress:_host]; - callOptions = [hostConfig.callOptions mutableCopy]; - } else { - callOptions = [[GRPCMutableCallOptions alloc] init]; - } + + callOptions = [[GRPCHost callOptionsForHost:_host] mutableCopy]; if (_serverName.length != 0) { callOptions.serverAuthority = _serverName; } diff --git a/src/objective-c/GRPCClient/private/GRPCHost.h b/src/objective-c/GRPCClient/private/GRPCHost.h index e321363bcbf..f1d57196424 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.h +++ b/src/objective-c/GRPCClient/private/GRPCHost.h @@ -66,9 +66,7 @@ struct grpc_channel_credentials; @property(atomic, readwrite) GRPCTransportType transportType; -@property(readonly) GRPCCallOptions *callOptions; - -+ (BOOL)isHostConfigured:(NSString *)address; ++ (GRPCCallOptions *)callOptionsForHost:(NSString *)host; @end diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 032b274ffcc..5fe022a1bae 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -133,17 +133,23 @@ static NSMutableDictionary *gHostCache; return options; } -+ (BOOL)isHostConfigured:(NSString *)address { ++ (GRPCCallOptions *)callOptionsForHost:(NSString *)host { // TODO (mxyan): Remove when old API is deprecated - NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:address]]; - if (hostURL.host && !hostURL.port) { - address = [hostURL.host stringByAppendingString:@":443"]; + NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:host]]; + if (hostURL.host && hostURL.port == nil) { + host = [hostURL.host stringByAppendingString:@":443"]; + } + + __block GRPCCallOptions *callOptions = nil; + @synchronized(gHostCache) { + if ([gHostCache objectForKey:host]) { + callOptions = [gHostCache[host] callOptions]; + } } - __block GRPCHost *cachedHost; - @synchronized (gHostCache) { - cachedHost = gHostCache[address]; + if (callOptions == nil) { + callOptions = [[GRPCCallOptions alloc] init]; } - return (cachedHost != nil); + return callOptions; } @end From f00be37dd19842e2e2f906b71d0525c2dc913378 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 16:07:09 -0700 Subject: [PATCH 073/375] Spell out 'certificates' rather than 'certs' --- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 8 ++++---- .../GRPCClient/private/GRPCSecureChannelFactory.h | 8 ++++---- .../GRPCClient/private/GRPCSecureChannelFactory.m | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index b5b3ff60efa..5d53cb2e99f 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -52,10 +52,10 @@ extern const char *kCFStreamVarName; #ifdef GRPC_COMPILE_WITH_CRONET if (![GRPCCall isUsingCronet]) { #endif - factory = [GRPCSecureChannelFactory factoryWithPEMRootCerts:_callOptions.PEMRootCertificates - privateKey:_callOptions.PEMPrivateKey - certChain:_callOptions.PEMCertChain - error:&error]; + factory = [GRPCSecureChannelFactory factoryWithPEMRootCertificates:_callOptions.PEMRootCertificates + privateKey:_callOptions.PEMPrivateKey + certChain:_callOptions.PEMCertChain + error:&error]; if (factory == nil) { NSLog(@"Error creating secure channel factory: %@", error); } diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h index 82af0dc3e68..588239b7064 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h @@ -23,10 +23,10 @@ NS_ASSUME_NONNULL_BEGIN @interface GRPCSecureChannelFactory : NSObject -+ (nullable instancetype)factoryWithPEMRootCerts:(nullable NSString *)rootCerts - privateKey:(nullable NSString *)privateKey - certChain:(nullable NSString *)certChain - error:(NSError **)errorPtr; ++ (nullable instancetype)factoryWithPEMRootCertificates:(nullable NSString *)rootCerts + privateKey:(nullable NSString *)privateKey + certChain:(nullable NSString *)certChain + error:(NSError **)errorPtr; - (nullable grpc_channel *)createChannelWithHost:(NSString *)host channelArgs:(nullable NSDictionary *)args; diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 8a00d080a11..b116c16ec0f 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -29,10 +29,10 @@ NS_ASSUME_NONNULL_BEGIN grpc_channel_credentials *_channelCreds; } -+ (nullable instancetype)factoryWithPEMRootCerts:(nullable NSString *)rootCerts - privateKey:(nullable NSString *)privateKey - certChain:(nullable NSString *)certChain - error:(NSError **)errorPtr { ++ (nullable instancetype)factoryWithPEMRootCertificates:(nullable NSString *)rootCerts + privateKey:(nullable NSString *)privateKey + certChain:(nullable NSString *)certChain + error:(NSError **)errorPtr { return [[self alloc] initWithPEMRootCerts:rootCerts privateKey:privateKey certChain:certChain From 6ae2ea643d89f7b2e7839f9016a61361ce92b5d5 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 16:32:42 -0700 Subject: [PATCH 074/375] obj.class->[obj class] --- .../GRPCClient/private/GRPCRequestHeaders.m | 4 +- .../private/GRPCSecureChannelFactory.m | 2 +- src/objective-c/ProtoRPC/ProtoRPC.m | 2 +- src/objective-c/tests/InteropTests.m | 62 +++++++++---------- src/objective-c/tests/InteropTestsLocalSSL.m | 4 +- 5 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m index fa4f022ff02..5f117f0607b 100644 --- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m +++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m @@ -36,7 +36,7 @@ static void CheckIsNonNilASCII(NSString *name, NSString *value) { // Precondition: key isn't nil. static void CheckKeyValuePairIsValid(NSString *key, id value) { if ([key hasSuffix:@"-bin"]) { - if (![value isKindOfClass:NSData.class]) { + if (![value isKindOfClass:[NSData class]]) { [NSException raise:NSInvalidArgumentException format: @"Expected NSData value for header %@ ending in \"-bin\", " @@ -44,7 +44,7 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) { key, value]; } } else { - if (![value isKindOfClass:NSString.class]) { + if (![value isKindOfClass:[NSString class]]) { [NSException raise:NSInvalidArgumentException format: @"Expected NSString value for header %@ not ending in \"-bin\", " diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index b116c16ec0f..13bca6c40d6 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -57,7 +57,7 @@ NS_ASSUME_NONNULL_BEGIN dispatch_once(&loading, ^{ 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]; + 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 diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 9fb398408bf..d3005e30a51 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -252,7 +252,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } // A writer that serializes the proto messages to send. GRXWriter *bytesWriter = [requestsWriter map:^id(GPBMessage *proto) { - if (![proto isKindOfClass:GPBMessage.class]) { + if (![proto isKindOfClass:[GPBMessage class]]) { [NSException raise:NSInvalidArgumentException format:@"Request must be a proto message: %@", proto]; } diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 11d4b95663a..ca49b5fc390 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -173,11 +173,11 @@ BOOL isRemoteInteropTest(NSString *host) { [GRPCCall resetHostSettings]; - _service = self.class.host ? [RMTTestService serviceWithHost:self.class.host] : nil; + _service = [[self class] host] ? [RMTTestService serviceWithHost:[[self class] host]] : nil; } - (void)testEmptyUnaryRPC { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"]; GPBEmpty *request = [GPBEmpty message]; @@ -196,14 +196,14 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testEmptyUnaryRPCWithV2API { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"]; GPBEmpty *request = [GPBEmpty message]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.transportType = self.class.transportType; - options.PEMRootCertificates = self.class.PEMRootCertificates; - options.hostNameOverride = self.class.hostNameOverride; + options.transportType = [[self class] transportType]; + options.PEMRootCertificates = [[self class] PEMRootCertificates]; + options.hostNameOverride = [[self class] hostNameOverride]; [_service emptyCallWithMessage:request @@ -223,7 +223,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testLargeUnaryRPC { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; RMTSimpleRequest *request = [RMTSimpleRequest message]; @@ -247,7 +247,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testPacketCoalescing { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; RMTSimpleRequest *request = [RMTSimpleRequest message]; @@ -286,7 +286,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)test4MBResponsesAreAccepted { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"MaxResponseSize"]; RMTSimpleRequest *request = [RMTSimpleRequest message]; @@ -304,7 +304,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testResponsesOverMaxSizeFailWithActionableMessage { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ResponseOverMaxSize"]; RMTSimpleRequest *request = [RMTSimpleRequest message]; @@ -330,7 +330,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testResponsesOver4MBAreAcceptedIfOptedIn { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"HigherResponseSizeLimit"]; @@ -338,7 +338,7 @@ BOOL isRemoteInteropTest(NSString *host) { const size_t kPayloadSize = 5 * 1024 * 1024; // 5MB request.responseSize = kPayloadSize; - [GRPCCall setResponseSizeLimit:6 * 1024 * 1024 forHost:self.class.host]; + [GRPCCall setResponseSizeLimit:6 * 1024 * 1024 forHost:[[self class] host]]; [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { @@ -351,7 +351,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testClientStreamingRPC { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ClientStreaming"]; RMTStreamingInputCallRequest *request1 = [RMTStreamingInputCallRequest message]; @@ -386,7 +386,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testServerStreamingRPC { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ServerStreaming"]; NSArray *expectedSizes = @[ @31415, @9, @2653, @58979 ]; @@ -425,7 +425,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testPingPongRPC { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPong"]; NSArray *requests = @[ @27182, @8, @1828, @45904 ]; @@ -472,7 +472,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testPingPongRPCWithV2API { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPong"]; NSArray *requests = @[ @27182, @8, @1828, @45904 ]; @@ -483,9 +483,9 @@ BOOL isRemoteInteropTest(NSString *host) { id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] requestedResponseSize:responses[index]]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.transportType = self.class.transportType; - options.PEMRootCertificates = self.class.PEMRootCertificates; - options.hostNameOverride = self.class.hostNameOverride; + options.transportType = [[self class] transportType ]; + options.PEMRootCertificates = [[self class] PEMRootCertificates]; + options.hostNameOverride = [[self class] hostNameOverride]; __block GRPCStreamingProtoCall *call = [_service fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] @@ -523,7 +523,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testEmptyStreamRPC { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"]; [_service fullDuplexCallWithRequestsWriter:[GRXWriter emptyWriter] eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response, @@ -536,7 +536,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testCancelAfterBeginRPC { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBegin"]; // A buffered pipe to which we never write any value acts as a writer that just hangs. @@ -561,7 +561,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testCancelAfterBeginRPCWithV2API { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBegin"]; // A buffered pipe to which we never write any value acts as a writer that just hangs. @@ -583,7 +583,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testCancelAfterFirstResponseRPC { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterFirstResponse"]; @@ -619,7 +619,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testCancelAfterFirstResponseRPCWithV2API { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *completionExpectation = [self expectationWithDescription:@"Call completed."]; __weak XCTestExpectation *responseExpectation = @@ -630,7 +630,7 @@ BOOL isRemoteInteropTest(NSString *host) { GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; options.transportType = self.class.transportType; options.PEMRootCertificates = self.class.PEMRootCertificates; - options.hostNameOverride = self.class.hostNameOverride; + options.hostNameOverride = [[self class] hostNameOverride]; id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 requestedResponseSize:@31415]; @@ -656,7 +656,7 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)testRPCAfterClosingOpenConnections { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"RPC after closing connection"]; @@ -688,10 +688,10 @@ BOOL isRemoteInteropTest(NSString *host) { - (void)testCompressedUnaryRPC { // This test needs to be disabled for remote test because interop server grpc-test // does not support compression. - if (isRemoteInteropTest(self.class.host)) { + if (isRemoteInteropTest([[self class] host])) { return; } - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; RMTSimpleRequest *request = [RMTSimpleRequest message]; @@ -699,7 +699,7 @@ BOOL isRemoteInteropTest(NSString *host) { request.responseSize = 314159; request.payload.body = [NSMutableData dataWithLength:271828]; request.expectCompressed.value = YES; - [GRPCCall setDefaultCompressMethod:GRPCCompressGzip forhost:self.class.host]; + [GRPCCall setDefaultCompressMethod:GRPCCompressGzip forhost:[[self class] host]]; [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) { @@ -718,10 +718,10 @@ BOOL isRemoteInteropTest(NSString *host) { #ifndef GRPC_COMPILE_WITH_CRONET - (void)testKeepalive { - XCTAssertNotNil(self.class.host); + XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Keepalive"]; - [GRPCCall setKeepaliveWithInterval:1500 timeout:0 forHost:self.class.host]; + [GRPCCall setKeepaliveWithInterval:1500 timeout:0 forHost:[[self class] host]]; NSArray *requests = @[ @27182, @8 ]; NSArray *responses = @[ @31415, @9 ]; diff --git a/src/objective-c/tests/InteropTestsLocalSSL.m b/src/objective-c/tests/InteropTestsLocalSSL.m index 759a080380d..e8222f602f4 100644 --- a/src/objective-c/tests/InteropTestsLocalSSL.m +++ b/src/objective-c/tests/InteropTestsLocalSSL.m @@ -41,7 +41,7 @@ static int32_t kLocalInteropServerOverhead = 10; } + (NSString *)PEMRootCertificates { - NSBundle *bundle = [NSBundle bundleForClass:self.class]; + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSString *certsPath = [bundle pathForResource:@"TestCertificates.bundle/test-certificates" ofType:@"pem"]; NSError *error; @@ -64,7 +64,7 @@ static int32_t kLocalInteropServerOverhead = 10; [super setUp]; // Register test server certificates and name. - NSBundle *bundle = [NSBundle bundleForClass:self.class]; + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSString *certsPath = [bundle pathForResource:@"TestCertificates.bundle/test-certificates" ofType:@"pem"]; [GRPCCall useTestCertsPath:certsPath testName:@"foo.test.google.fr" forHost:kLocalSSLHost]; From 4264ea2b55f46c1904fc179fb0db7b733b8c3e4b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 18 Oct 2018 17:04:03 -0700 Subject: [PATCH 075/375] clang-format --- src/objective-c/GRPCClient/GRPCCall.h | 10 +- src/objective-c/GRPCClient/GRPCCall.m | 34 +++--- src/objective-c/GRPCClient/GRPCCallOptions.m | 26 ++--- .../GRPCClient/private/GRPCChannel.m | 36 ++++--- .../GRPCClient/private/GRPCChannelPool.m | 35 +++--- src/objective-c/ProtoRPC/ProtoRPC.h | 6 +- src/objective-c/ProtoRPC/ProtoRPC.m | 10 +- src/objective-c/ProtoRPC/ProtoService.h | 13 +-- .../tests/ChannelTests/ChannelPoolTest.m | 35 +++--- src/objective-c/tests/GRPCClientTests.m | 101 +++++++++--------- src/objective-c/tests/InteropTests.m | 2 +- 11 files changed, 161 insertions(+), 147 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 6adecec144a..bd43a0a384b 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -149,7 +149,7 @@ extern id const kGRPCHeadersKey; extern id const kGRPCTrailersKey; /** An object can implement this protocol to receive responses from server from a call. */ -@protocol GRPCResponseHandler +@protocol GRPCResponseHandler @optional @@ -188,10 +188,12 @@ extern id const kGRPCTrailersKey; - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; ++ (instancetype) new NS_UNAVAILABLE; /** Initialize with all properties. */ -- (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithHost:(NSString *)host + path:(NSString *)path + safety:(GRPCCallSafety)safety NS_DESIGNATED_INITIALIZER; /** The host serving the RPC service. */ @property(copy, readonly) NSString *host; @@ -214,7 +216,7 @@ extern id const kGRPCTrailersKey; - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; ++ (instancetype) new NS_UNAVAILABLE; /** * Designated initializer for a call. diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 399206a346c..bd4b4e10f0f 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -28,8 +28,8 @@ #include #import "GRPCCallOptions.h" -#import "private/GRPCHost.h" #import "private/GRPCConnectivityMonitor.h" +#import "private/GRPCHost.h" #import "private/GRPCRequestHeaders.h" #import "private/GRPCWrappedCall.h" #import "private/NSData+GRPC.h" @@ -115,7 +115,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; _initialMetadataPublished = NO; _pipe = [GRXBufferedPipe pipe]; if (@available(iOS 8.0, *)) { - _dispatchQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + _dispatchQueue = dispatch_queue_create( + NULL, + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); } else { // Fallback on earlier versions _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); @@ -129,7 +131,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)responseHandler { - return [self initWithRequestOptions:requestOptions responseHandler:responseHandler callOptions:nil]; + return + [self initWithRequestOptions:requestOptions responseHandler:responseHandler callOptions:nil]; } - (void)start { @@ -210,9 +213,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; error:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeCancelled userInfo:@{ - NSLocalizedDescriptionKey : - @"Canceled by app" - }]]; + NSLocalizedDescriptionKey : + @"Canceled by app" + }]]; } }); @@ -255,13 +258,12 @@ const char *kCFStreamVarName = "grpc_cfstream"; } } -- (void)issueClosedWithTrailingMetadata:(NSDictionary *)trailingMetadata - error:(NSError *)error { +- (void)issueClosedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { id handler = _handler; NSDictionary *trailers = _call.responseTrailers; if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:trailers error:error]; + [handler closedWithTrailingMetadata:trailers error:error]; }); } } @@ -388,7 +390,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; requestsWriter:(GRXWriter *)requestWriter callOptions:(GRPCCallOptions *)callOptions { if (host.length == 0 || path.length == 0) { - [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil or empty."]; + [NSException raise:NSInvalidArgumentException + format:@"Neither host nor path can be nil or empty."]; } if (safety > GRPCCallSafetyCacheableRequest) { [NSException raise:NSInvalidArgumentException format:@"Invalid call safety value."]; @@ -457,7 +460,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)cancel { - @synchronized (self) { + @synchronized(self) { if (!self.isWaitingForToken) { [self cancelCall]; } else { @@ -720,8 +723,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; [self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeUnavailable userInfo:@{ - NSLocalizedDescriptionKey : @"Failed to create call or channel." - }]]; + NSLocalizedDescriptionKey : + @"Failed to create call or channel." + }]]; return; } @@ -773,11 +777,11 @@ const char *kCFStreamVarName = "grpc_cfstream"; _callOptions = callOptions; } if (_callOptions.authTokenProvider != nil) { - @synchronized (self) { + @synchronized(self) { self.isWaitingForToken = YES; } [self.tokenProvider getTokenWithHandler:^(NSString *token) { - @synchronized (self) { + @synchronized(self) { if (self.isWaitingForToken) { if (token) { self->_fetchedOauth2AccessToken = [token copy]; diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 8d2b84b7484..37ed3ebd1d1 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -110,7 +110,7 @@ static NSUInteger kDefaultChannelID = 0; connectInitialBackoff:kDefaultConnectInitialBackoff connectMaxBackoff:kDefaultConnectMaxBackoff additionalChannelArgs:kDefaultAdditionalChannelArgs - PEMRootCertificates:kDefaultPEMRootCertificates + PEMRootCertificates:kDefaultPEMRootCertificates PEMPrivateKey:kDefaultPEMPrivateKey PEMCertChain:kDefaultPEMCertChain transportType:kDefaultTransportType @@ -135,7 +135,7 @@ static NSUInteger kDefaultChannelID = 0; connectInitialBackoff:(NSTimeInterval)connectInitialBackoff connectMaxBackoff:(NSTimeInterval)connectMaxBackoff additionalChannelArgs:(NSDictionary *)additionalChannelArgs - PEMRootCertificates:(NSString *)PEMRootCertificates + PEMRootCertificates:(NSString *)PEMRootCertificates PEMPrivateKey:(NSString *)PEMPrivateKey PEMCertChain:(NSString *)PEMCertChain transportType:(GRPCTransportType)transportType @@ -158,7 +158,8 @@ static NSUInteger kDefaultChannelID = 0; _connectMinTimeout = connectMinTimeout; _connectInitialBackoff = connectInitialBackoff; _connectMaxBackoff = connectMaxBackoff; - _additionalChannelArgs = [[NSDictionary alloc] initWithDictionary:additionalChannelArgs copyItems:YES]; + _additionalChannelArgs = + [[NSDictionary alloc] initWithDictionary:additionalChannelArgs copyItems:YES]; _PEMRootCertificates = [PEMRootCertificates copy]; _PEMPrivateKey = [PEMPrivateKey copy]; _PEMCertChain = [PEMCertChain copy]; @@ -188,7 +189,7 @@ static NSUInteger kDefaultChannelID = 0; connectInitialBackoff:_connectInitialBackoff connectMaxBackoff:_connectMaxBackoff additionalChannelArgs:_additionalChannelArgs - PEMRootCertificates:_PEMRootCertificates + PEMRootCertificates:_PEMRootCertificates PEMPrivateKey:_PEMPrivateKey PEMCertChain:_PEMCertChain transportType:_transportType @@ -216,7 +217,7 @@ static NSUInteger kDefaultChannelID = 0; connectInitialBackoff:_connectInitialBackoff connectMaxBackoff:_connectMaxBackoff additionalChannelArgs:[_additionalChannelArgs copy] - PEMRootCertificates:_PEMRootCertificates + PEMRootCertificates:_PEMRootCertificates PEMPrivateKey:_PEMPrivateKey PEMCertChain:_PEMCertChain transportType:_transportType @@ -240,8 +241,7 @@ static NSUInteger kDefaultChannelID = 0; if (!(callOptions.connectInitialBackoff == _connectInitialBackoff)) return NO; if (!(callOptions.connectMaxBackoff == _connectMaxBackoff)) return NO; if (!(callOptions.additionalChannelArgs == _additionalChannelArgs || - [callOptions.additionalChannelArgs - isEqualToDictionary:_additionalChannelArgs])) + [callOptions.additionalChannelArgs isEqualToDictionary:_additionalChannelArgs])) return NO; if (!(callOptions.PEMRootCertificates == _PEMRootCertificates || [callOptions.PEMRootCertificates isEqualToString:_PEMRootCertificates])) @@ -256,8 +256,7 @@ static NSUInteger kDefaultChannelID = 0; [callOptions.hostNameOverride isEqualToString:_hostNameOverride])) return NO; if (!(callOptions.transportType == _transportType)) return NO; - if (!(callOptions.logContext == _logContext || - [callOptions.logContext isEqual:_logContext])) + if (!(callOptions.logContext == _logContext || [callOptions.logContext isEqual:_logContext])) return NO; if (!(callOptions.channelPoolDomain == _channelPoolDomain || [callOptions.channelPoolDomain isEqualToString:_channelPoolDomain])) @@ -335,7 +334,7 @@ static NSUInteger kDefaultChannelID = 0; connectInitialBackoff:kDefaultConnectInitialBackoff connectMaxBackoff:kDefaultConnectMaxBackoff additionalChannelArgs:kDefaultAdditionalChannelArgs - PEMRootCertificates:kDefaultPEMRootCertificates + PEMRootCertificates:kDefaultPEMRootCertificates PEMPrivateKey:kDefaultPEMPrivateKey PEMCertChain:kDefaultPEMCertChain transportType:kDefaultTransportType @@ -362,7 +361,7 @@ static NSUInteger kDefaultChannelID = 0; connectInitialBackoff:_connectInitialBackoff connectMaxBackoff:_connectMaxBackoff additionalChannelArgs:[_additionalChannelArgs copy] - PEMRootCertificates:_PEMRootCertificates + PEMRootCertificates:_PEMRootCertificates PEMPrivateKey:_PEMPrivateKey PEMCertChain:_PEMCertChain transportType:_transportType @@ -390,7 +389,7 @@ static NSUInteger kDefaultChannelID = 0; connectInitialBackoff:_connectInitialBackoff connectMaxBackoff:_connectMaxBackoff additionalChannelArgs:[_additionalChannelArgs copy] - PEMRootCertificates:_PEMRootCertificates + PEMRootCertificates:_PEMRootCertificates PEMPrivateKey:_PEMPrivateKey PEMCertChain:_PEMCertChain transportType:_transportType @@ -482,7 +481,8 @@ static NSUInteger kDefaultChannelID = 0; } - (void)setAdditionalChannelArgs:(NSDictionary *)additionalChannelArgs { - _additionalChannelArgs = [[NSDictionary alloc] initWithDictionary:additionalChannelArgs copyItems:YES]; + _additionalChannelArgs = + [[NSDictionary alloc] initWithDictionary:additionalChannelArgs copyItems:YES]; } - (void)setPEMRootCertificates:(NSString *)PEMRootCertificates { diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 2420988f427..63bc267a762 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -75,8 +75,12 @@ NSTimeInterval kChannelDestroyDelay = 30; _refCount = 1; _disconnected = NO; if (@available(iOS 8.0, *)) { - _dispatchQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); - _timerQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_DEFAULT, -1)); + _dispatchQueue = dispatch_queue_create( + NULL, + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + _timerQueue = + dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class( + DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_DEFAULT, -1)); } else { _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); _timerQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT); @@ -101,7 +105,8 @@ NSTimeInterval kChannelDestroyDelay = 30; self->_refCount--; if (self->_refCount == 0) { self->_lastDispatch = [NSDate date]; - dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)kChannelDestroyDelay * 1e9); + dispatch_time_t delay = + dispatch_time(DISPATCH_TIME_NOW, (int64_t)kChannelDestroyDelay * 1e9); dispatch_after(delay, self->_timerQueue, ^{ [self timerFire]; }); @@ -123,7 +128,8 @@ NSTimeInterval kChannelDestroyDelay = 30; - (void)timerFire { dispatch_async(_dispatchQueue, ^{ - if (self->_disconnected || self->_lastDispatch == nil || -[self->_lastDispatch timeIntervalSinceNow] < -kChannelDestroyDelay) { + if (self->_disconnected || self->_lastDispatch == nil || + -[self->_lastDispatch timeIntervalSinceNow] < -kChannelDestroyDelay) { return; } self->_lastDispatch = nil; @@ -158,11 +164,12 @@ NSTimeInterval kChannelDestroyDelay = 30; } grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); gpr_timespec deadline_ms = - timeout == 0 ? gpr_inf_future(GPR_CLOCK_REALTIME) - : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); - call = grpc_channel_create_call( - self->_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, queue.unmanagedQueue, path_slice, + timeout == 0 + ? gpr_inf_future(GPR_CLOCK_REALTIME) + : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); + call = grpc_channel_create_call(self->_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, + queue.unmanagedQueue, path_slice, serverAuthority ? &host_slice : NULL, deadline_ms, NULL); if (serverAuthority) { grpc_slice_unref(host_slice); @@ -214,11 +221,14 @@ NSTimeInterval kChannelDestroyDelay = 30; if ((self = [super init])) { _unmanagedChannel = unmanagedChannel; _configuration = configuration; - _channelRef = [[GRPCChannelRef alloc] initWithDestroyDelay:kChannelDestroyDelay destroyChannelCallback:^{ - [self destroyChannel]; - }]; + _channelRef = [[GRPCChannelRef alloc] initWithDestroyDelay:kChannelDestroyDelay + destroyChannelCallback:^{ + [self destroyChannel]; + }]; if (@available(iOS 8.0, *)) { - _dispatchQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + _dispatchQueue = dispatch_queue_create( + NULL, + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); } else { _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); } diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 5d53cb2e99f..6659d193c68 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -52,10 +52,11 @@ extern const char *kCFStreamVarName; #ifdef GRPC_COMPILE_WITH_CRONET if (![GRPCCall isUsingCronet]) { #endif - factory = [GRPCSecureChannelFactory factoryWithPEMRootCertificates:_callOptions.PEMRootCertificates - privateKey:_callOptions.PEMPrivateKey - certChain:_callOptions.PEMCertChain - error:&error]; + factory = [GRPCSecureChannelFactory + factoryWithPEMRootCertificates:_callOptions.PEMRootCertificates + privateKey:_callOptions.PEMPrivateKey + certChain:_callOptions.PEMCertChain + error:&error]; if (factory == nil) { NSLog(@"Error creating secure channel factory: %@", error); } @@ -136,7 +137,8 @@ extern const char *kCFStreamVarName; } - (nonnull id)copyWithZone:(nullable NSZone *)zone { - GRPCChannelConfiguration *newConfig = [[GRPCChannelConfiguration alloc] initWithHost:_host callOptions:_callOptions]; + GRPCChannelConfiguration *newConfig = + [[GRPCChannelConfiguration alloc] initWithHost:_host callOptions:_callOptions]; return newConfig; } @@ -145,7 +147,8 @@ extern const char *kCFStreamVarName; NSAssert([object isKindOfClass:[GRPCChannelConfiguration class]], @"Illegal :isEqual"); GRPCChannelConfiguration *obj = (GRPCChannelConfiguration *)object; if (!(obj.host == _host || [obj.host isEqualToString:_host])) return NO; - if (!(obj.callOptions == _callOptions || [obj.callOptions isChannelOptionsEqualTo:_callOptions])) return NO; + if (!(obj.callOptions == _callOptions || [obj.callOptions isChannelOptionsEqualTo:_callOptions])) + return NO; return YES; } @@ -201,11 +204,13 @@ extern const char *kCFStreamVarName; - (void)removeChannel:(GRPCChannel *)channel { @synchronized(self) { - [_channelPool enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration * _Nonnull key, GRPCChannel * _Nonnull obj, BOOL * _Nonnull stop) { - if (obj == channel) { - [self->_channelPool removeObjectForKey:key]; - } - }]; + [_channelPool + enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration *_Nonnull key, + GRPCChannel *_Nonnull obj, BOOL *_Nonnull stop) { + if (obj == channel) { + [self->_channelPool removeObjectForKey:key]; + } + }]; } } @@ -217,9 +222,11 @@ extern const char *kCFStreamVarName; - (void)removeAndCloseAllChannels { @synchronized(self) { - [_channelPool enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration * _Nonnull key, GRPCChannel * _Nonnull obj, BOOL * _Nonnull stop) { - [obj disconnect]; - }]; + [_channelPool + enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration *_Nonnull key, + GRPCChannel *_Nonnull obj, BOOL *_Nonnull stop) { + [obj disconnect]; + }]; _channelPool = [NSMutableDictionary dictionary]; } } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index db1e8c6deb3..f2ba5134952 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -24,7 +24,7 @@ @class GPBMessage; /** An object can implement this protocol to receive responses from server from a call. */ -@protocol GRPCProtoResponseHandler +@protocol GRPCProtoResponseHandler @optional @@ -59,7 +59,7 @@ - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; ++ (instancetype) new NS_UNAVAILABLE; /** * Users should not use this initializer directly. Call objects will be created, initialized, and @@ -81,7 +81,7 @@ - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; ++ (instancetype) new NS_UNAVAILABLE; /** * Users should not use this initializer directly. Call objects will be created, initialized, and diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index d3005e30a51..238faa33437 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -88,7 +88,9 @@ _callOptions = [callOptions copy]; _responseClass = responseClass; if (@available(iOS 8.0, *)) { - _dispatchQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + _dispatchQueue = dispatch_queue_create( + NULL, + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); } else { _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); } @@ -120,9 +122,9 @@ error:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeCancelled userInfo:@{ - NSLocalizedDescriptionKey : - @"Canceled by app" - }]]; + NSLocalizedDescriptionKey : + @"Canceled by app" + }]]; }); } _handler = nil; diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h index 2985c5cb2dc..3a16ab24026 100644 --- a/src/objective-c/ProtoRPC/ProtoService.h +++ b/src/objective-c/ProtoRPC/ProtoService.h @@ -30,14 +30,15 @@ __attribute__((deprecated("Please use GRPCProtoService."))) @interface ProtoService : NSObject -- (instancetype)init NS_UNAVAILABLE; + - + (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; ++ (instancetype) new NS_UNAVAILABLE; - - - (instancetype)initWithHost : (NSString *)host packageName - : (NSString *)packageName serviceName : (NSString *)serviceName callOptions - : (GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithHost:(NSString *)host + packageName:(NSString *)packageName + serviceName:(NSString *)serviceName + callOptions:(GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; - (instancetype)initWithHost:(NSString *)host packageName:(NSString *)packageName diff --git a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m index db64ac6339e..f4a9fb4a2c4 100644 --- a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m +++ b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m @@ -57,11 +57,9 @@ NSString *kDummyHost = @"dummy.host"; GRPCChannelConfiguration *config1 = [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; - GRPCChannel *channel1 = - [pool channelWithConfiguration:config1]; + GRPCChannel *channel1 = [pool channelWithConfiguration:config1]; [pool removeChannel:channel1]; - GRPCChannel *channel2 = - [pool channelWithConfiguration:config1]; + GRPCChannel *channel2 = [pool channelWithConfiguration:config1]; XCTAssertNotEqual(channel1, channel2); } @@ -74,18 +72,14 @@ extern NSTimeInterval kChannelDestroyDelay; options1.transportType = GRPCTransportTypeInsecure; GRPCChannelConfiguration *config1 = [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; - GRPCChannelPool *pool = - [[GRPCChannelPool alloc] init]; - GRPCChannel *channel1 = - [pool channelWithConfiguration:config1]; + GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; + GRPCChannel *channel1 = [pool channelWithConfiguration:config1]; [channel1 unmanagedCallUnref]; sleep(1); - GRPCChannel *channel2 = - [pool channelWithConfiguration:config1]; + GRPCChannel *channel2 = [pool channelWithConfiguration:config1]; XCTAssertEqual(channel1, channel2); sleep((int)kChannelDestroyDelay + 2); - GRPCChannel *channel3 = - [pool channelWithConfiguration:config1]; + GRPCChannel *channel3 = [pool channelWithConfiguration:config1]; XCTAssertEqual(channel1, channel3); kChannelDestroyDelay = kOriginalInterval; } @@ -96,12 +90,11 @@ extern NSTimeInterval kChannelDestroyDelay; options1.transportType = GRPCTransportTypeInsecure; GRPCCallOptions *options2 = [options1 copy]; GRPCChannelConfiguration *config1 = - [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; + [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; GRPCChannelConfiguration *config2 = - [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options2]; + [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options2]; GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; - GRPCChannel *channel1 = [pool channelWithConfiguration:config1]; [pool removeAndCloseAllChannels]; GRPCChannel *channel2 = [pool channelWithConfiguration:config2]; @@ -119,17 +112,13 @@ extern NSTimeInterval kChannelDestroyDelay; [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options2]; GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; - GRPCChannel *channel1 = - [pool channelWithConfiguration:config1]; - GRPCChannel *channel2 = - [pool channelWithConfiguration:config2]; + GRPCChannel *channel1 = [pool channelWithConfiguration:config1]; + GRPCChannel *channel2 = [pool channelWithConfiguration:config2]; XCTAssertNotEqual(channel1, channel2); [pool removeAndCloseAllChannels]; - GRPCChannel *channel3 = - [pool channelWithConfiguration:config1]; - GRPCChannel *channel4 = - [pool channelWithConfiguration:config2]; + GRPCChannel *channel3 = [pool channelWithConfiguration:config1]; + GRPCChannel *channel4 = [pool channelWithConfiguration:config2]; XCTAssertNotEqual(channel1, channel3); XCTAssertNotEqual(channel2, channel4); } diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index f961b6a86fd..387fcab7e9f 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -446,42 +446,40 @@ static GRPCProtoMethod *kFullDuplexCallMethod; options.initialMetadata = headers; GRPCCall2 *call = [[GRPCCall2 alloc] initWithRequestOptions:request - responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:^( + responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:^( NSDictionary *initialMetadata) { - NSString *userAgent = initialMetadata[@"x-grpc-test-echo-useragent"]; - // Test the regex is correct - NSString *expectedUserAgent = @"Foo grpc-objc/"; - expectedUserAgent = - [expectedUserAgent stringByAppendingString:GRPC_OBJC_VERSION_STRING]; - expectedUserAgent = [expectedUserAgent stringByAppendingString:@" grpc-c/"]; - expectedUserAgent = - [expectedUserAgent stringByAppendingString:GRPC_C_VERSION_STRING]; - expectedUserAgent = - [expectedUserAgent stringByAppendingString:@" (ios; chttp2; "]; - expectedUserAgent = [expectedUserAgent - stringByAppendingString:[NSString - stringWithUTF8String:grpc_g_stands_for()]]; - expectedUserAgent = [expectedUserAgent stringByAppendingString:@")"]; - XCTAssertEqualObjects(userAgent, expectedUserAgent); - - NSError *error = nil; - // Change in format of user-agent field in a direction that does not match - // the regex will likely cause problem for certain gRPC users. For details, - // refer to internal doc https://goo.gl/c2diBc - NSRegularExpression *regex = [NSRegularExpression - regularExpressionWithPattern: - @" grpc-[a-zA-Z0-9]+(-[a-zA-Z0-9]+)?/[^ ,]+( \\([^)]*\\))?" - options:0 - error:&error]; - - NSString *customUserAgent = [regex - stringByReplacingMatchesInString:userAgent - options:0 - range:NSMakeRange(0, [userAgent length]) - withTemplate:@""]; - XCTAssertEqualObjects(customUserAgent, @"Foo"); - [recvInitialMd fulfill]; - } + NSString *userAgent = initialMetadata[@"x-grpc-test-echo-useragent"]; + // Test the regex is correct + NSString *expectedUserAgent = @"Foo grpc-objc/"; + expectedUserAgent = + [expectedUserAgent stringByAppendingString:GRPC_OBJC_VERSION_STRING]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@" grpc-c/"]; + expectedUserAgent = + [expectedUserAgent stringByAppendingString:GRPC_C_VERSION_STRING]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@" (ios; chttp2; "]; + expectedUserAgent = [expectedUserAgent + stringByAppendingString:[NSString stringWithUTF8String:grpc_g_stands_for()]]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@")"]; + XCTAssertEqualObjects(userAgent, expectedUserAgent); + + NSError *error = nil; + // Change in format of user-agent field in a direction that does not match + // the regex will likely cause problem for certain gRPC users. For details, + // refer to internal doc https://goo.gl/c2diBc + NSRegularExpression *regex = [NSRegularExpression + regularExpressionWithPattern: + @" grpc-[a-zA-Z0-9]+(-[a-zA-Z0-9]+)?/[^ ,]+( \\([^)]*\\))?" + options:0 + error:&error]; + + NSString *customUserAgent = + [regex stringByReplacingMatchesInString:userAgent + options:0 + range:NSMakeRange(0, [userAgent length]) + withTemplate:@""]; + XCTAssertEqualObjects(customUserAgent, @"Foo"); + [recvInitialMd fulfill]; + } messageCallback:^(id message) { XCTAssertNotNil(message); XCTAssertEqual([message length], 0, @@ -609,7 +607,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; options.transportType = GRPCTransportTypeInsecure; GRPCCall2 *call = [[GRPCCall2 alloc] initWithRequestOptions:requestOptions - responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil messageCallback:^(id message) { NSData *data = (NSData *)message; XCTAssertNotNil(data, @"nil value received as response."); @@ -739,19 +737,18 @@ static GRPCProtoMethod *kFullDuplexCallMethod; GRPCCall2 *call = [[GRPCCall2 alloc] initWithRequestOptions:requestOptions - responseHandler: - [[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil - messageCallback:^(id data) { - XCTFail( - @"Failure: response received; Expect: no response received."); - } - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - XCTAssertNotNil(error, - @"Failure: no error received; Expect: receive " - @"deadline exceeded."); - XCTAssertEqual(error.code, GRPCErrorCodeDeadlineExceeded); - [completion fulfill]; - }] + responseHandler: + [[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + messageCallback:^(id data) { + XCTFail(@"Failure: response received; Expect: no response received."); + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + XCTAssertNotNil(error, + @"Failure: no error received; Expect: receive " + @"deadline exceeded."); + XCTAssertEqual(error.code, GRPCErrorCodeDeadlineExceeded); + [completion fulfill]; + }] callOptions:options]; [call start]; @@ -837,7 +834,9 @@ static GRPCProtoMethod *kFullDuplexCallMethod; __weak XCTestExpectation *completion = [self expectationWithDescription:@"Timeout in a second."]; NSString *const kDummyAddress = [NSString stringWithFormat:@"127.0.0.1:10000"]; GRPCRequestOptions *requestOptions = - [[GRPCRequestOptions alloc] initWithHost:kDummyAddress path:@"/dummy/path" safety:GRPCCallSafetyDefault]; + [[GRPCRequestOptions alloc] initWithHost:kDummyAddress + path:@"/dummy/path" + safety:GRPCCallSafetyDefault]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; options.connectMinTimeout = timeout; options.connectInitialBackoff = backoff; @@ -846,7 +845,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; NSDate *startTime = [NSDate date]; GRPCCall2 *call = [[GRPCCall2 alloc] initWithRequestOptions:requestOptions - responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil messageCallback:^(id data) { XCTFail(@"Received message. Should not reach here."); } diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index ca49b5fc390..1188a75df77 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -483,7 +483,7 @@ BOOL isRemoteInteropTest(NSString *host) { id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] requestedResponseSize:responses[index]]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.transportType = [[self class] transportType ]; + options.transportType = [[self class] transportType]; options.PEMRootCertificates = [[self class] PEMRootCertificates]; options.hostNameOverride = [[self class] hostNameOverride]; From 6d8340847caf0634853818ff4b8745e83c5279d3 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 09:12:18 -0700 Subject: [PATCH 076/375] Name changes in compiler --- src/compiler/objective_c_generator.cc | 4 ++-- src/compiler/objective_c_plugin.cc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc index eb67e9bb88f..0a6b64f5952 100644 --- a/src/compiler/objective_c_generator.cc +++ b/src/compiler/objective_c_generator.cc @@ -127,11 +127,11 @@ void PrintV2Signature(Printer* printer, const MethodDescriptor* method, printer->Print(vars, "- ($return_type$)$method_name$With"); if (method->client_streaming()) { - printer->Print("ResponseHandler:(id)handler"); + printer->Print("ResponseHandler:(id)handler"); } else { printer->Print(vars, "Message:($request_class$ *)message " - "responseHandler:(id)handler"); + "responseHandler:(id)handler"); } printer->Print(" callOptions:(GRPCCallOptions *_Nullable)callOptions"); } diff --git a/src/compiler/objective_c_plugin.cc b/src/compiler/objective_c_plugin.cc index d0ef9ed0d62..87977095d05 100644 --- a/src/compiler/objective_c_plugin.cc +++ b/src/compiler/objective_c_plugin.cc @@ -98,7 +98,7 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { "@class GRPCUnaryProtoCall;\n" "@class GRPCStreamingProtoCall;\n" "@class GRPCCallOptions;\n" - "@protocol GRPCResponseHandler;\n" + "@protocol GRPCProtoResponseHandler;\n" "\n"; ::grpc::string class_declarations = From 82d91964493ceb5893b3874109bc4bbc7d87b821 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 09:12:59 -0700 Subject: [PATCH 077/375] One more obj.class->[obj class] --- .../InteropTestsMultipleChannels/InteropTestsMultipleChannels.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m b/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m index 237804d23de..b0d4e4883a3 100644 --- a/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m +++ b/src/objective-c/tests/InteropTestsMultipleChannels/InteropTestsMultipleChannels.m @@ -105,7 +105,7 @@ dispatch_once_t initCronet; // Local stack with SSL _localSSLService = [RMTTestService serviceWithHost:kLocalSSLHost]; - NSBundle *bundle = [NSBundle bundleForClass:self.class]; + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSString *certsPath = [bundle pathForResource:@"TestCertificates.bundle/test-certificates" ofType:@"pem"]; NSError *error = nil; From b9667c6c17590c1f63435ad8dab0554775299003 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 09:13:27 -0700 Subject: [PATCH 078/375] handle NULL case when parsing certificate --- .../private/GRPCSecureChannelFactory.m | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 13bca6c40d6..90482cad219 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -42,6 +42,9 @@ NS_ASSUME_NONNULL_BEGIN - (NSData *)nullTerminatedDataWithString:(NSString *)string { // dataUsingEncoding: does not return a null-terminated string. NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; + if (data == nil) { + return nil; + } NSMutableData *nullTerminated = [NSMutableData dataWithData:data]; [nullTerminated appendBytes:"\0" length:1]; return nullTerminated; @@ -51,7 +54,7 @@ NS_ASSUME_NONNULL_BEGIN privateKey:(nullable NSString *)privateKey certChain:(nullable NSString *)certChain error:(NSError **)errorPtr { - static NSData *kDefaultRootsASCII; + static NSData *defaultRootsASCII; static NSError *kDefaultRootsError; static dispatch_once_t loading; dispatch_once(&loading, ^{ @@ -68,14 +71,14 @@ NS_ASSUME_NONNULL_BEGIN kDefaultRootsError = error; return; } - kDefaultRootsASCII = [self nullTerminatedDataWithString:contentInUTF8]; + defaultRootsASCII = [self nullTerminatedDataWithString:contentInUTF8]; }); NSData *rootsASCII; if (rootCerts != nil) { rootsASCII = [self nullTerminatedDataWithString:rootCerts]; } else { - if (kDefaultRootsASCII == nil) { + if (defaultRootsASCII == nil) { if (errorPtr) { *errorPtr = kDefaultRootsError; } @@ -88,11 +91,11 @@ NS_ASSUME_NONNULL_BEGIN kDefaultRootsError); return nil; } - rootsASCII = kDefaultRootsASCII; + rootsASCII = defaultRootsASCII; } - grpc_channel_credentials *creds; - if (privateKey == nil && certChain == nil) { + grpc_channel_credentials *creds = NULL; + if (privateKey.length == 0 && certChain.length == 0) { creds = grpc_ssl_credentials_create(rootsASCII.bytes, NULL, NULL, NULL); } else { grpc_ssl_pem_key_cert_pair key_cert_pair; @@ -100,7 +103,11 @@ NS_ASSUME_NONNULL_BEGIN NSData *certChainASCII = [self nullTerminatedDataWithString:certChain]; 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, NULL); + if (key_cert_pair.private_key == NULL || key_cert_pair.cert_chain == NULL) { + creds = grpc_ssl_credentials_create(rootsASCII.bytes, NULL, NULL, NULL); + } else { + creds = grpc_ssl_credentials_create(rootsASCII.bytes, &key_cert_pair, NULL, NULL); + } } if ((self = [super init])) { From 56d605230f2d8c2ddb5670e8d0f2ede6c2aca4d1 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 09:17:11 -0700 Subject: [PATCH 079/375] nil->NULL --- src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 90482cad219..3f2769bf447 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -126,7 +126,7 @@ NS_ASSUME_NONNULL_BEGIN } - (void)dealloc { - if (_channelCreds != nil) { + if (_channelCreds != NULL) { grpc_channel_credentials_release(_channelCreds); } } From 75f8727a3e35ac3db8a3957d9318f2dfdd798e7f Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 09:26:38 -0700 Subject: [PATCH 080/375] NSString == nil -> NSString.length == 0 --- src/objective-c/GRPCClient/private/GRPCWrappedCall.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 1c03bc9efdd..a7c50a17519 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -247,7 +247,7 @@ - (instancetype)initWithHost:(NSString *)host path:(NSString *)path callOptions:(GRPCCallOptions *)callOptions { - if (!path || !host) { + if (host.length == 0 || path.length == 0) { [NSException raise:NSInvalidArgumentException format:@"path and host cannot be nil."]; } From 2a9efc3d1f0ddb42d0797dee5f82ca7abedc0936 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 09:50:33 -0700 Subject: [PATCH 081/375] polish cancel message of proto calls --- src/objective-c/ProtoRPC/ProtoRPC.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index f2ba5134952..663c1610bcf 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -71,7 +71,11 @@ callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; -/** Cancel the call at best effort. */ +/** + * Cancel the request of this call at best effort. It attempts to notify the server that the RPC + * should be cancelled, and issue closedWithTrailingMetadata:error: callback with error code + * CANCELED if no other error code has already been issued. + */ - (void)cancel; @end @@ -92,7 +96,11 @@ callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; -/** Cancel the call at best effort. */ +/** + * Cancel the request of this call at best effort. It attempts to notify the server that the RPC + * should be cancelled, and issue closedWithTrailingMetadata:error: callback with error code + * CANCELED if no other error code has already been issued. + */ - (void)cancel; /** From 9925c13b2710a313d489fd040f0d7f312af0f1fc Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 09:51:42 -0700 Subject: [PATCH 082/375] writeWithMessage->writeMessage --- src/objective-c/ProtoRPC/ProtoRPC.h | 2 +- src/objective-c/ProtoRPC/ProtoRPC.m | 4 ++-- src/objective-c/tests/InteropTests.m | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 663c1610bcf..4121d4f6af2 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -107,7 +107,7 @@ * Send a message to the server. The message should be a Protobuf message which will be serialized * internally. */ -- (void)writeWithMessage:(GPBMessage *)message; +- (void)writeMessage:(GPBMessage *)message; /** * Finish the RPC request and half-close the call. The server may still send messages and/or diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 238faa33437..b04b6aca67b 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -41,7 +41,7 @@ responseHandler:handler callOptions:callOptions responseClass:responseClass]; - [_call writeWithMessage:message]; + [_call writeMessage:message]; [_call finish]; } return self; @@ -132,7 +132,7 @@ }); } -- (void)writeWithMessage:(GPBMessage *)message { +- (void)writeMessage:(GPBMessage *)message { if (![message isKindOfClass:[GPBMessage class]]) { [NSException raise:NSInvalidArgumentException format:@"Data must be a valid protobuf type."]; } diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 1188a75df77..d38e1e0d972 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -501,7 +501,7 @@ BOOL isRemoteInteropTest(NSString *host) { id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] requestedResponseSize:responses[index]]; - [call writeWithMessage:request]; + [call writeMessage:request]; } else { [call finish]; } @@ -517,7 +517,7 @@ BOOL isRemoteInteropTest(NSString *host) { [expectation fulfill]; }] callOptions:options]; - [call writeWithMessage:request]; + [call writeMessage:request]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } @@ -651,7 +651,7 @@ BOOL isRemoteInteropTest(NSString *host) { }] callOptions:options]; - [call writeWithMessage:request]; + [call writeMessage:request]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } From 2d903f4732ee21c5c319c88aa738671b56b2e729 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 10:15:02 -0700 Subject: [PATCH 083/375] More specific typing in response handlers --- src/objective-c/GRPCClient/GRPCCall.h | 2 +- src/objective-c/ProtoRPC/ProtoRPC.h | 2 +- src/objective-c/ProtoRPC/ProtoRPC.m | 2 +- src/objective-c/tests/GRPCClientTests.m | 2 +- src/objective-c/tests/InteropTests.m | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index bd43a0a384b..d8d3e3cf629 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -160,7 +160,7 @@ extern id const kGRPCTrailersKey; * Issued when a message is received from the server. The message is the raw data received from the * server, with decompression and without proto deserialization. */ -- (void)receivedRawMessage:(id)message; +- (void)receivedRawMessage:(NSData *)message; /** * Issued when a call finished. If the call finished successfully, \a error is nil and \a diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 4121d4f6af2..34a519bee5d 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -34,7 +34,7 @@ /** * Issued when a message is received from the server. The message is the deserialized proto object. */ -- (void)receivedProtoMessage:(id)message; +- (void)receivedProtoMessage:(GPBMessage *)message; /** * Issued when a call finished. If the call finished successfully, \a error is nil and \a diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index b04b6aca67b..44e9bfde0ab 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -168,7 +168,7 @@ if (_handler) { id handler = _handler; NSError *error = nil; - id parsed = [_responseClass parseFromData:message error:&error]; + GPBMessage *parsed = [_responseClass parseFromData:message error:&error]; if (parsed) { if ([handler respondsToSelector:@selector(receivedProtoMessage:)]) { dispatch_async(handler.dispatchQueue, ^{ diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 387fcab7e9f..985e105b816 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -120,7 +120,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; } } -- (void)receivedProtoMessage:(id)message { +- (void)receivedProtoMessage:(GPBMessage *)message { if (_messageCallback) { _messageCallback(message); } diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index d38e1e0d972..a9f33aab6f1 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -108,7 +108,7 @@ BOOL isRemoteInteropTest(NSString *host) { } } -- (void)receivedProtoMessage:(id)message { +- (void)receivedProtoMessage:(GPBMessage *)message { if (_messageCallback) { _messageCallback(message); } From a6e35201b5a00949379fd04fb784f6b90d06a88a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 11:07:00 -0700 Subject: [PATCH 084/375] polish comments --- src/objective-c/GRPCClient/GRPCCallOptions.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 8864bcb8a2f..6e16cd56a93 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -26,8 +26,10 @@ typedef NS_ENUM(NSUInteger, GRPCCallSafety) { 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, }; @@ -39,14 +41,14 @@ typedef NS_ENUM(NSInteger, GRPCCompressAlgorithm) { GRPCStreamCompressGzip, }; -// The transport to be used by a gRPC call +/** The transport to be used by a gRPC call */ typedef NS_ENUM(NSInteger, GRPCTransportType) { GRPCTransportTypeDefault = 0, - // gRPC internal HTTP/2 stack with BoringSSL + /** gRPC internal HTTP/2 stack with BoringSSL */ GRPCTransportTypeChttp2BoringSSL = 0, - // Cronet stack + /** Cronet stack */ GRPCTransportTypeCronet, - // Insecure channel. FOR TEST ONLY! + /** Insecure channel. FOR TEST ONLY! */ GRPCTransportTypeInsecure, }; From 590ab392520c0216690bc2626e2c9b55e95fc0fa Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 11:24:04 -0700 Subject: [PATCH 085/375] GRPCCompressAlgorithm->GRPCCompressionAlgorithm --- src/objective-c/GRPCClient/GRPCCallOptions.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 6e16cd56a93..b8bbb8a22d3 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -33,14 +33,19 @@ typedef NS_ENUM(NSUInteger, GRPCCallSafety) { GRPCCallSafetyCacheableRequest = 2, }; + + // Compression algorithm to be used by a gRPC call -typedef NS_ENUM(NSInteger, GRPCCompressAlgorithm) { +typedef NS_ENUM(NSInteger, GRPCCompressionAlgorithm) { GRPCCompressNone = 0, GRPCCompressDeflate, GRPCCompressGzip, GRPCStreamCompressGzip, }; +// GRPCCompressAlgorithm is deprecated; use GRPCCompressionAlgorithm +typedef GRPCCompressionAlgorithm GRPCCompressAlgorithm; + /** The transport to be used by a gRPC call */ typedef NS_ENUM(NSInteger, GRPCTransportType) { GRPCTransportTypeDefault = 0, From cc9157a248e20a2f24972241ae1f2d41ea171a8b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 11:45:59 -0700 Subject: [PATCH 086/375] Polish comments --- src/objective-c/GRPCClient/GRPCCallOptions.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index b8bbb8a22d3..9a8362cbcca 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -67,7 +67,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { /** * The authority for the RPC. If nil, the default authority will be used. * - * Note: This property must be nil when Cronet transport is enabled. + * Note: This property does not have effect on Cronet transport and will be ignored. * Note: This property cannot be used to validate a self-signed server certificate. It control the * :authority header field of the call and performs an extra check that server's certificate * matches the :authority header. @@ -85,8 +85,8 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { /** * The OAuth2 access token string. The string is prefixed with "Bearer " then used as value of the - * request's "authorization" header field. This parameter should not be used simultaneously with - * \a authTokenProvider. + * request's "authorization" header field. This parameter takes precedence over \a + * oauth2AccessToken. */ @property(copy, readonly) NSString *oauth2AccessToken; @@ -213,7 +213,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { /** * The authority for the RPC. If nil, the default authority will be used. * - * Note: This property must be nil when Cronet transport is enabled. + * Note: This property does not have effect on Cronet transport and will be ignored. * Note: This property cannot be used to validate a self-signed server certificate. It control the * :authority header field of the call and performs an extra check that server's certificate * matches the :authority header. @@ -239,7 +239,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { /** * The interface to get the OAuth2 access token string. gRPC will attempt to acquire token when - * initiating the call. This parameter should not be used simultaneously with \a oauth2AccessToken. + * initiating the call. This parameter takes precedence over \a oauth2AccessToken. */ @property(readwrite) id authTokenProvider; From 9f9141082bcd4167488780f93eeec8d40c17e007 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 11:57:18 -0700 Subject: [PATCH 087/375] compressAlgorithm->compressionAlgorithm --- src/objective-c/GRPCClient/GRPCCallOptions.h | 4 +-- src/objective-c/GRPCClient/GRPCCallOptions.m | 32 +++++++++---------- .../GRPCClient/private/GRPCChannelPool.m | 4 +-- src/objective-c/GRPCClient/private/GRPCHost.m | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 9a8362cbcca..484f15fde6e 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -119,7 +119,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { * The compression algorithm to be used by the gRPC call. For more details refer to * https://github.com/grpc/grpc/blob/master/doc/compression.md */ -@property(readonly) GRPCCompressAlgorithm compressAlgorithm; +@property(readonly) GRPCCompressionAlgorithm compressionAlgorithm; /** * Enable/Disable gRPC call's retry feature. The default is enabled. For details of this feature @@ -266,7 +266,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { * The compression algorithm to be used by the gRPC call. For more details refer to * https://github.com/grpc/grpc/blob/master/doc/compression.md */ -@property(readwrite) GRPCCompressAlgorithm compressAlgorithm; +@property(readwrite) GRPCCompressionAlgorithm compressionAlgorithm; /** * Enable/Disable gRPC call's retry feature. The default is enabled. For details of this feature diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 37ed3ebd1d1..3dc21b72873 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -24,7 +24,7 @@ static const NSTimeInterval kDefaultTimeout = 0; static NSDictionary *const kDefaultInitialMetadata = nil; static NSString *const kDefaultUserAgentPrefix = nil; static const NSUInteger kDefaultResponseSizeLimit = 0; -static const GRPCCompressAlgorithm kDefaultCompressAlgorithm = GRPCCompressNone; +static const GRPCCompressionAlgorithm kDefaultCompressionAlgorithm = GRPCCompressNone; static const BOOL kDefaultEnableRetry = YES; static const NSTimeInterval kDefaultKeepaliveInterval = 0; static const NSTimeInterval kDefaultKeepaliveTimeout = 0; @@ -52,7 +52,7 @@ static NSUInteger kDefaultChannelID = 0; NSDictionary *_initialMetadata; NSString *_userAgentPrefix; NSUInteger _responseSizeLimit; - GRPCCompressAlgorithm _compressAlgorithm; + GRPCCompressionAlgorithm _compressionAlgorithm; BOOL _enableRetry; NSTimeInterval _keepaliveInterval; NSTimeInterval _keepaliveTimeout; @@ -77,7 +77,7 @@ static NSUInteger kDefaultChannelID = 0; @synthesize initialMetadata = _initialMetadata; @synthesize userAgentPrefix = _userAgentPrefix; @synthesize responseSizeLimit = _responseSizeLimit; -@synthesize compressAlgorithm = _compressAlgorithm; +@synthesize compressionAlgorithm = _compressionAlgorithm; @synthesize enableRetry = _enableRetry; @synthesize keepaliveInterval = _keepaliveInterval; @synthesize keepaliveTimeout = _keepaliveTimeout; @@ -102,7 +102,7 @@ static NSUInteger kDefaultChannelID = 0; initialMetadata:kDefaultInitialMetadata userAgentPrefix:kDefaultUserAgentPrefix responseSizeLimit:kDefaultResponseSizeLimit - compressAlgorithm:kDefaultCompressAlgorithm + compressionAlgorithm:kDefaultCompressionAlgorithm enableRetry:kDefaultEnableRetry keepaliveInterval:kDefaultKeepaliveInterval keepaliveTimeout:kDefaultKeepaliveTimeout @@ -127,7 +127,7 @@ static NSUInteger kDefaultChannelID = 0; initialMetadata:(NSDictionary *)initialMetadata userAgentPrefix:(NSString *)userAgentPrefix responseSizeLimit:(NSUInteger)responseSizeLimit - compressAlgorithm:(GRPCCompressAlgorithm)compressAlgorithm + compressionAlgorithm:(GRPCCompressionAlgorithm)compressionAlgorithm enableRetry:(BOOL)enableRetry keepaliveInterval:(NSTimeInterval)keepaliveInterval keepaliveTimeout:(NSTimeInterval)keepaliveTimeout @@ -151,7 +151,7 @@ static NSUInteger kDefaultChannelID = 0; _initialMetadata = [[NSDictionary alloc] initWithDictionary:initialMetadata copyItems:YES]; _userAgentPrefix = [userAgentPrefix copy]; _responseSizeLimit = responseSizeLimit; - _compressAlgorithm = compressAlgorithm; + _compressionAlgorithm = compressionAlgorithm; _enableRetry = enableRetry; _keepaliveInterval = keepaliveInterval; _keepaliveTimeout = keepaliveTimeout; @@ -181,7 +181,7 @@ static NSUInteger kDefaultChannelID = 0; initialMetadata:_initialMetadata userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit - compressAlgorithm:_compressAlgorithm + compressionAlgorithm:_compressionAlgorithm enableRetry:_enableRetry keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout @@ -209,7 +209,7 @@ static NSUInteger kDefaultChannelID = 0; initialMetadata:_initialMetadata userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit - compressAlgorithm:_compressAlgorithm + compressionAlgorithm:_compressionAlgorithm enableRetry:_enableRetry keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout @@ -233,7 +233,7 @@ static NSUInteger kDefaultChannelID = 0; [callOptions.userAgentPrefix isEqualToString:_userAgentPrefix])) return NO; if (!(callOptions.responseSizeLimit == _responseSizeLimit)) return NO; - if (!(callOptions.compressAlgorithm == _compressAlgorithm)) return NO; + if (!(callOptions.compressionAlgorithm == _compressionAlgorithm)) return NO; if (!(callOptions.enableRetry == _enableRetry)) return NO; if (!(callOptions.keepaliveInterval == _keepaliveInterval)) return NO; if (!(callOptions.keepaliveTimeout == _keepaliveTimeout)) return NO; @@ -270,7 +270,7 @@ static NSUInteger kDefaultChannelID = 0; NSUInteger result = 0; result ^= _userAgentPrefix.hash; result ^= _responseSizeLimit; - result ^= _compressAlgorithm; + result ^= _compressionAlgorithm; result ^= _enableRetry; result ^= (unsigned int)(_keepaliveInterval * 1000); result ^= (unsigned int)(_keepaliveTimeout * 1000); @@ -301,7 +301,7 @@ static NSUInteger kDefaultChannelID = 0; @dynamic initialMetadata; @dynamic userAgentPrefix; @dynamic responseSizeLimit; -@dynamic compressAlgorithm; +@dynamic compressionAlgorithm; @dynamic enableRetry; @dynamic keepaliveInterval; @dynamic keepaliveTimeout; @@ -326,7 +326,7 @@ static NSUInteger kDefaultChannelID = 0; initialMetadata:kDefaultInitialMetadata userAgentPrefix:kDefaultUserAgentPrefix responseSizeLimit:kDefaultResponseSizeLimit - compressAlgorithm:kDefaultCompressAlgorithm + compressionAlgorithm:kDefaultCompressionAlgorithm enableRetry:kDefaultEnableRetry keepaliveInterval:kDefaultKeepaliveInterval keepaliveTimeout:kDefaultKeepaliveTimeout @@ -353,7 +353,7 @@ static NSUInteger kDefaultChannelID = 0; initialMetadata:_initialMetadata userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit - compressAlgorithm:_compressAlgorithm + compressionAlgorithm:_compressionAlgorithm enableRetry:_enableRetry keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout @@ -381,7 +381,7 @@ static NSUInteger kDefaultChannelID = 0; initialMetadata:_initialMetadata userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit - compressAlgorithm:_compressAlgorithm + compressionAlgorithm:_compressionAlgorithm enableRetry:_enableRetry keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout @@ -432,8 +432,8 @@ static NSUInteger kDefaultChannelID = 0; _responseSizeLimit = responseSizeLimit; } -- (void)setCompressAlgorithm:(GRPCCompressAlgorithm)compressAlgorithm { - _compressAlgorithm = compressAlgorithm; +- (void)setCompressionAlgorithm:(GRPCCompressionAlgorithm)compressionAlgorithm { + _compressionAlgorithm = compressionAlgorithm; } - (void)setEnableRetry:(BOOL)enableRetry { diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 6659d193c68..4908b82feac 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -94,9 +94,9 @@ extern const char *kCFStreamVarName; [NSNumber numberWithUnsignedInteger:_callOptions.responseSizeLimit]; } - if (_callOptions.compressAlgorithm != GRPC_COMPRESS_NONE) { + if (_callOptions.compressionAlgorithm != GRPC_COMPRESS_NONE) { args[@GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM] = - [NSNumber numberWithInt:_callOptions.compressAlgorithm]; + [NSNumber numberWithInt:_callOptions.compressionAlgorithm]; } if (_callOptions.keepaliveInterval != 0) { diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 5fe022a1bae..41d3bec4efa 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -102,7 +102,7 @@ static NSMutableDictionary *gHostCache; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; options.userAgentPrefix = _userAgentPrefix; options.responseSizeLimit = _responseSizeLimitOverride; - options.compressAlgorithm = (GRPCCompressAlgorithm)_compressAlgorithm; + options.compressionAlgorithm = (GRPCCompressionAlgorithm)_compressAlgorithm; options.enableRetry = _retryEnabled; options.keepaliveInterval = (NSTimeInterval)_keepaliveInterval / 1000; options.keepaliveTimeout = (NSTimeInterval)_keepaliveTimeout / 1000; From 5eb9911a0eb13590fe558875df3512d6def20d3c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 13:55:31 -0700 Subject: [PATCH 088/375] Change extern type --- src/objective-c/GRPCClient/GRPCCall.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index d8d3e3cf629..7ce5a2faf2c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -145,8 +145,8 @@ typedef NS_ENUM(NSUInteger, GRPCErrorCode) { * 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; +extern NSString * const kGRPCHeadersKey; +extern NSString * const kGRPCTrailersKey; /** An object can implement this protocol to receive responses from server from a call. */ @protocol GRPCResponseHandler From 0242b022ccc804e498b2e631fd0e6c8478ac97c4 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 14:28:25 -0700 Subject: [PATCH 089/375] Typo fix --- src/objective-c/GRPCClient/GRPCCall.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 7ce5a2faf2c..b8fccc37dc8 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -221,7 +221,7 @@ extern NSString * const kGRPCTrailersKey; /** * Designated initializer for a call. * \param requestOptions Protobuf generated parameters for the call. - * \param responseHandler The object to which responses should be issed. + * \param responseHandler The object to which responses should be issued. * \param callOptions Options for the call. */ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions From e542e006eb4ffcd0c19488428a3cfe5605bf41e5 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 14:29:08 -0700 Subject: [PATCH 090/375] Format fix --- src/objective-c/GRPCClient/GRPCCall.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index b8fccc37dc8..9fdcd93a30c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -254,7 +254,8 @@ extern NSString * const kGRPCTrailersKey; /** * Finish the RPC request and half-close the call. The server may still send messages and/or * trailers to the client. - */ -(void)finish; + */ +- (void)finish; /** * Get a copy of the original call options. From 422d3296b2d4fb3f8aa0991c2ffa895251ad8e91 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 15:42:39 -0700 Subject: [PATCH 091/375] Annotate Nullability --- src/objective-c/GRPCClient/GRPCCall.h | 12 ++++++++---- src/objective-c/GRPCClient/GRPCCall.m | 2 +- src/objective-c/ProtoRPC/ProtoRPC.h | 14 +++++++++----- src/objective-c/ProtoRPC/ProtoRPC.m | 14 +++++++------- src/objective-c/tests/GRPCClientTests.m | 6 +++--- src/objective-c/tests/InteropTests.m | 6 +++--- 6 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 9fdcd93a30c..c862609b21c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -39,6 +39,8 @@ #include "GRPCCallOptions.h" +NS_ASSUME_NONNULL_BEGIN + #pragma mark gRPC errors /** Domain of NSError objects produced by gRPC. */ @@ -154,13 +156,13 @@ extern NSString * const kGRPCTrailersKey; @optional /** Issued when initial metadata is received from the server. */ -- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata; +- (void)receivedInitialMetadata:(NSDictionary * _Nullable)initialMetadata; /** * Issued when a message is received from the server. The message is the raw data received from the * server, with decompression and without proto deserialization. */ -- (void)receivedRawMessage:(NSData *)message; +- (void)receivedRawMessage:(NSData * _Nullable)message; /** * Issued when a call finished. If the call finished successfully, \a error is nil and \a @@ -168,7 +170,7 @@ extern NSString * const kGRPCTrailersKey; * is non-nil and contains the corresponding error information, including gRPC error codes and * error descriptions. */ -- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error; +- (void)closedWithTrailingMetadata:(NSDictionary * _Nullable)trailingMetadata error:(NSError * _Nullable)error; @required @@ -226,7 +228,7 @@ extern NSString * const kGRPCTrailersKey; */ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)responseHandler - callOptions:(GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; + callOptions:(GRPCCallOptions * _Nullable)callOptions NS_DESIGNATED_INITIALIZER; /** * Convenience initializer for a call that uses default call options (see GRPCCallOptions.m for * the default options). @@ -267,6 +269,8 @@ extern NSString * const kGRPCTrailersKey; @end +NS_ASSUME_NONNULL_END + /** * This interface is deprecated. Please use \a GRPCcall2. * diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index bd4b4e10f0f..1782078961d 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -97,7 +97,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)responseHandler - callOptions:(GRPCCallOptions *)callOptions { + callOptions:(GRPCCallOptions * _Nullable)callOptions { if (requestOptions.host.length == 0 || requestOptions.path.length == 0) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 34a519bee5d..3a7fd58fb16 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -21,6 +21,8 @@ #import "ProtoMethod.h" +NS_ASSUME_NONNULL_BEGIN + @class GPBMessage; /** An object can implement this protocol to receive responses from server from a call. */ @@ -29,12 +31,12 @@ @optional /** Issued when initial metadata is received from the server. */ -- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata; +- (void)receivedInitialMetadata:(NSDictionary * _Nullable)initialMetadata; /** * Issued when a message is received from the server. The message is the deserialized proto object. */ -- (void)receivedProtoMessage:(GPBMessage *)message; +- (void)receivedProtoMessage:(GPBMessage * _Nullable)message; /** * Issued when a call finished. If the call finished successfully, \a error is nil and \a @@ -42,7 +44,7 @@ * is non-nil and contains the corresponding error information, including gRPC error codes and * error descriptions. */ -- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error; +- (void)closedWithTrailingMetadata:(NSDictionary * _Nullable)trailingMetadata error:(NSError * _Nullable)error; @required @@ -68,7 +70,7 @@ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions message:(GPBMessage *)message responseHandler:(id)handler - callOptions:(GRPCCallOptions *)callOptions + callOptions:(GRPCCallOptions * _Nullable)callOptions responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; /** @@ -93,7 +95,7 @@ */ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)handler - callOptions:(GRPCCallOptions *)callOptions + callOptions:(GRPCCallOptions * _Nullable)callOptions responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; /** @@ -117,6 +119,8 @@ @end +NS_ASSUME_NONNULL_END + __attribute__((deprecated("Please use GRPCProtoCall."))) @interface ProtoRPC : GRPCCall diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 44e9bfde0ab..f6e3298f623 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -34,7 +34,7 @@ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions message:(GPBMessage *)message responseHandler:(id)handler - callOptions:(GRPCCallOptions *)callOptions + callOptions:(GRPCCallOptions * _Nullable)callOptions responseClass:(Class)responseClass { if ((self = [super init])) { _call = [[GRPCStreamingProtoCall alloc] initWithRequestOptions:requestOptions @@ -70,7 +70,7 @@ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)handler - callOptions:(GRPCCallOptions *)callOptions + callOptions:(GRPCCallOptions * _Nullable)callOptions responseClass:(Class)responseClass { if (requestOptions.host.length == 0 || requestOptions.path.length == 0) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; @@ -153,8 +153,8 @@ }); } -- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { - if (_handler) { +- (void)receivedInitialMetadata:(NSDictionary * _Nullable)initialMetadata { + if (_handler && initialMetadata != nil) { id handler = _handler; if ([handler respondsToSelector:@selector(initialMetadata:)]) { dispatch_async(handler.dispatchQueue, ^{ @@ -164,8 +164,8 @@ } } -- (void)receivedRawMessage:(NSData *)message { - if (_handler) { +- (void)receivedRawMessage:(NSData * _Nullable)message { + if (_handler && message != nil) { id handler = _handler; NSError *error = nil; GPBMessage *parsed = [_responseClass parseFromData:message error:&error]; @@ -188,7 +188,7 @@ } } -- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { +- (void)closedWithTrailingMetadata:(NSDictionary * _Nullable)trailingMetadata error:(NSError * _Nullable)error { if (_handler) { id handler = _handler; if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 985e105b816..0a9ec97c488 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -114,19 +114,19 @@ static GRPCProtoMethod *kFullDuplexCallMethod; return self; } -- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { +- (void)receivedInitialMetadata:(NSDictionary * _Nullable)initialMetadata { if (_initialMetadataCallback) { _initialMetadataCallback(initialMetadata); } } -- (void)receivedProtoMessage:(GPBMessage *)message { +- (void)receivedProtoMessage:(GPBMessage * _Nullable)message { if (_messageCallback) { _messageCallback(message); } } -- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { +- (void)closedWithTrailingMetadata:(NSDictionary * _Nullable)trailingMetadata error:(NSError * _Nullable)error { if (_closeCallback) { _closeCallback(trailingMetadata, error); } diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index a9f33aab6f1..fb49bb99e0a 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -102,19 +102,19 @@ BOOL isRemoteInteropTest(NSString *host) { return self; } -- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { +- (void)receivedInitialMetadata:(NSDictionary * _Nullable)initialMetadata { if (_initialMetadataCallback) { _initialMetadataCallback(initialMetadata); } } -- (void)receivedProtoMessage:(GPBMessage *)message { +- (void)receivedProtoMessage:(GPBMessage * _Nullable)message { if (_messageCallback) { _messageCallback(message); } } -- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { +- (void)closedWithTrailingMetadata:(NSDictionary * _Nullable)trailingMetadata error:(NSError * _Nullable)error { if (_closeCallback) { _closeCallback(trailingMetadata, error); } From 24d952b2b916030aa02f33afb7746b2582ca88e4 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 15:43:46 -0700 Subject: [PATCH 092/375] Add comments to ivars of GRPCCall2 --- src/objective-c/GRPCClient/GRPCCall.m | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 1782078961d..74b284d924c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -85,13 +85,24 @@ const char *kCFStreamVarName = "grpc_cfstream"; @end @implementation GRPCCall2 { + /** Options for the call. */ GRPCCallOptions *_callOptions; + /** The handler of responses. */ id _handler; + // Thread safety of ivars below are protected by _dispatcheQueue. + + /** + * Make use of legacy GRPCCall to make calls. Nullified when call is finished. + */ GRPCCall *_call; + /** Flags whether initial metadata has been published to response handler. */ BOOL _initialMetadataPublished; + /** Streaming call writeable to the underlying call. */ GRXBufferedPipe *_pipe; + /** Serial dispatch queue for tasks inside the call. */ dispatch_queue_t _dispatchQueue; + /** Flags whether call has started. */ bool _started; } From c6de16fc801b654ff1cbb697c36fafa5c2ff0528 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 15:44:07 -0700 Subject: [PATCH 093/375] Remove redundant variable --- src/objective-c/GRPCClient/GRPCCall.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 74b284d924c..daa7e8dd4a1 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -579,7 +579,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; callSafetyFlags = GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; break; } - uint32_t callFlag = callSafetyFlags; NSMutableDictionary *headers = _requestHeaders; if (_fetchedOauth2AccessToken != nil) { @@ -592,7 +591,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; // TODO(jcanizales): Add error handlers for async failures GRPCOpSendMetadata *op = [[GRPCOpSendMetadata alloc] initWithMetadata:headers - flags:callFlag + flags:callSafetyFlags handler:nil]; // No clean-up needed after SEND_INITIAL_METADATA if (!_unaryCall) { [_wrappedCall startBatchWithOperations:@[ op ]]; From cb745ceaf9f9ffd90447498a6e8a57d5ac600389 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 15:46:57 -0700 Subject: [PATCH 094/375] Synchronized access to fetchedOauth2AccessToken --- src/objective-c/GRPCClient/GRPCCall.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index daa7e8dd4a1..34a0e436eaa 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -581,8 +581,12 @@ const char *kCFStreamVarName = "grpc_cfstream"; } NSMutableDictionary *headers = _requestHeaders; - if (_fetchedOauth2AccessToken != nil) { - headers[@"authorization"] = [kBearerPrefix stringByAppendingString:_fetchedOauth2AccessToken]; + __block NSString *fetchedOauth2AccessToken; + @synchronized(self) { + fetchedOauth2AccessToken = _fetchedOauth2AccessToken; + } + if (fetchedOauth2AccessToken != nil) { + headers[@"authorization"] = [kBearerPrefix stringByAppendingString:fetchedOauth2AccessToken]; } else if (_callOptions.oauth2AccessToken != nil) { headers[@"authorization"] = [kBearerPrefix stringByAppendingString:_callOptions.oauth2AccessToken]; From 789108d16d72c61b6df4135796116d3cffce0a58 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 17:24:23 -0700 Subject: [PATCH 095/375] add const attribute to defaults --- src/objective-c/GRPCClient/GRPCCallOptions.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 3dc21b72873..e148664925c 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -40,8 +40,8 @@ static const id kDefaultAuthTokenProvider = nil; static const GRPCTransportType kDefaultTransportType = GRPCTransportTypeChttp2BoringSSL; static NSString *const kDefaultHostNameOverride = nil; static const id kDefaultLogContext = nil; -static NSString *kDefaultChannelPoolDomain = nil; -static NSUInteger kDefaultChannelID = 0; +static NSString *const kDefaultChannelPoolDomain = nil; +static const NSUInteger kDefaultChannelID = 0; @implementation GRPCCallOptions { @protected From 8cecb2a86dd5904c68f46d4b685b11c8cb0a8704 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 17:33:50 -0700 Subject: [PATCH 096/375] Write comments for functions in ChannelArgsUtil --- src/objective-c/GRPCClient/private/ChannelArgsUtil.h | 9 +++++++++ src/objective-c/GRPCClient/private/ChannelArgsUtil.m | 7 ------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/objective-c/GRPCClient/private/ChannelArgsUtil.h b/src/objective-c/GRPCClient/private/ChannelArgsUtil.h index d0be4849105..3fb876ecc4a 100644 --- a/src/objective-c/GRPCClient/private/ChannelArgsUtil.h +++ b/src/objective-c/GRPCClient/private/ChannelArgsUtil.h @@ -20,6 +20,15 @@ #include +/** Free resources in the grpc core struct grpc_channel_args */ void GRPCFreeChannelArgs(grpc_channel_args* channel_args); +/** + * Allocates a @c grpc_channel_args and populates it with the options specified in the + * @c dictionary. Keys must be @c NSString, @c NSNumber, or a pointer. If the value responds to + * @c @selector(UTF8String) then it will be mapped to @c GRPC_ARG_STRING. If the value responds to + * @c @selector(intValue), it will be mapped to @c GRPC_ARG_INTEGER. Otherwise, if the value is not + * nil, it is mapped as a pointer. The caller of this function is responsible for calling + * @c GRPCFreeChannelArgs to free the @c grpc_channel_args struct. + */ grpc_channel_args* GRPCBuildChannelArgs(NSDictionary* dictionary); diff --git a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m index 8669f79992c..b8342a79e79 100644 --- a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m +++ b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m @@ -51,13 +51,6 @@ void GRPCFreeChannelArgs(grpc_channel_args *channel_args) { gpr_free(channel_args); } -/** - * Allocates a @c grpc_channel_args and populates it with the options specified in the - * @c dictionary. Keys must be @c NSString. If the value responds to @c @selector(UTF8String) then - * it will be mapped to @c GRPC_ARG_STRING. If not, it will be mapped to @c GRPC_ARG_INTEGER if the - * value responds to @c @selector(intValue). Otherwise, an exception will be raised. The caller of - * this function is responsible for calling @c freeChannelArgs on a non-NULL returned value. - */ grpc_channel_args *GRPCBuildChannelArgs(NSDictionary *dictionary) { if (!dictionary) { return NULL; From b3cb4e17f76624e563e51165954ebaa6224d806c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 17:56:42 -0700 Subject: [PATCH 097/375] Comment and rename GRPCChannel:ref and :unref --- src/objective-c/GRPCClient/private/GRPCChannel.h | 14 ++++++++++++-- src/objective-c/GRPCClient/private/GRPCChannel.m | 4 ++-- .../GRPCClient/private/GRPCChannelPool.m | 2 +- .../GRPCClient/private/GRPCWrappedCall.m | 2 +- .../tests/ChannelTests/ChannelPoolTest.m | 2 +- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index 7a40638dc33..5f5fae04135 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -51,10 +51,20 @@ struct grpc_channel_credentials; completionQueue:(nonnull GRPCCompletionQueue *)queue callOptions:(nonnull GRPCCallOptions *)callOptions; -- (void)unmanagedCallRef; +/** + * Increase the refcount of the channel. If the channel was timed to be destroyed, cancel the timer. + */ +- (void)ref; -- (void)unmanagedCallUnref; +/** + * Decrease the refcount of the channel. If the refcount of the channel decrease to 0, start a timer + * to destroy the channel + */ +- (void)unref; +/** + * Force the channel to be disconnected and destroyed immediately. + */ - (void)disconnect; // TODO (mxyan): deprecate with GRPCCall:closeOpenConnections diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 63bc267a762..3e4db837658 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -180,7 +180,7 @@ NSTimeInterval kChannelDestroyDelay = 30; return call; } -- (void)unmanagedCallRef { +- (void)ref { dispatch_async(_dispatchQueue, ^{ if (self->_unmanagedChannel) { [self->_channelRef refChannel]; @@ -188,7 +188,7 @@ NSTimeInterval kChannelDestroyDelay = 30; }); } -- (void)unmanagedCallUnref { +- (void)unref { dispatch_async(_dispatchQueue, ^{ if (self->_unmanagedChannel) { [self->_channelRef unrefChannel]; diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 4908b82feac..8e0f6976cf9 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -191,7 +191,7 @@ extern const char *kCFStreamVarName; @synchronized(self) { if ([_channelPool objectForKey:configuration]) { channel = _channelPool[configuration]; - [channel unmanagedCallRef]; + [channel ref]; } else { channel = [GRPCChannel createChannelWithConfiguration:configuration]; if (channel != nil) { diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index a7c50a17519..4d5257aca79 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -311,7 +311,7 @@ - (void)dealloc { grpc_call_unref(_call); - [_channel unmanagedCallUnref]; + [_channel unref]; _channel = nil; } diff --git a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m index f4a9fb4a2c4..5c3f0edba0b 100644 --- a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m +++ b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m @@ -74,7 +74,7 @@ extern NSTimeInterval kChannelDestroyDelay; [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; GRPCChannel *channel1 = [pool channelWithConfiguration:config1]; - [channel1 unmanagedCallUnref]; + [channel1 unref]; sleep(1); GRPCChannel *channel2 = [pool channelWithConfiguration:config1]; XCTAssertEqual(channel1, channel2); From 17d178363dafe3aa03d348bdbbbd0c3daed9e06e Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 17:57:26 -0700 Subject: [PATCH 098/375] rename non-const variables --- .../GRPCClient/private/GRPCSecureChannelFactory.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 3f2769bf447..aa8b52e6b8f 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -55,7 +55,7 @@ NS_ASSUME_NONNULL_BEGIN certChain:(nullable NSString *)certChain error:(NSError **)errorPtr { static NSData *defaultRootsASCII; - static NSError *kDefaultRootsError; + static NSError *defaultRootsError; static dispatch_once_t loading; dispatch_once(&loading, ^{ NSString *defaultPath = @"gRPCCertificates.bundle/roots"; // .pem @@ -68,7 +68,7 @@ NS_ASSUME_NONNULL_BEGIN NSString *contentInUTF8 = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error]; if (contentInUTF8 == nil) { - kDefaultRootsError = error; + defaultRootsError = error; return; } defaultRootsASCII = [self nullTerminatedDataWithString:contentInUTF8]; @@ -80,15 +80,15 @@ NS_ASSUME_NONNULL_BEGIN } else { if (defaultRootsASCII == nil) { if (errorPtr) { - *errorPtr = kDefaultRootsError; + *errorPtr = defaultRootsError; } NSAssert( - kDefaultRootsASCII, + defaultRootsASCII, @"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); + defaultRootsError); return nil; } rootsASCII = defaultRootsASCII; From 5e3e744d448c8cd1271cae7e8d40d3bdeaff762f Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 19 Oct 2018 18:32:05 -0700 Subject: [PATCH 099/375] copy configuration --- src/objective-c/GRPCClient/private/GRPCChannel.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 3e4db837658..6bd852fd0d0 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -220,7 +220,7 @@ NSTimeInterval kChannelDestroyDelay = 30; configuration:(GRPCChannelConfiguration *)configuration { if ((self = [super init])) { _unmanagedChannel = unmanagedChannel; - _configuration = configuration; + _configuration = [configuration copy]; _channelRef = [[GRPCChannelRef alloc] initWithDestroyDelay:kChannelDestroyDelay destroyChannelCallback:^{ [self destroyChannel]; From 4186405287a6944e7b1eb59dcae5524ea2db674d Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sat, 20 Oct 2018 09:40:22 -0700 Subject: [PATCH 100/375] GRPCChannel input parameter sanity check --- src/objective-c/GRPCClient/private/GRPCChannel.m | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 6bd852fd0d0..6b5d1fe0719 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -150,14 +150,17 @@ NSTimeInterval kChannelDestroyDelay = 30; } - (grpc_call *)unmanagedCallWithPath:(NSString *)path - completionQueue:(nonnull GRPCCompletionQueue *)queue + completionQueue:(GRPCCompletionQueue *)queue callOptions:(GRPCCallOptions *)callOptions { + NSAssert(path.length, @"path must not be empty."); + NSAssert(queue, @"completionQueue must not be empty."); + NSAssert(callOptions, @"callOptions must not be empty."); __block grpc_call *call = nil; dispatch_sync(_dispatchQueue, ^{ if (self->_unmanagedChannel) { NSString *serverAuthority = callOptions.serverAuthority; NSTimeInterval timeout = callOptions.timeout; - GPR_ASSERT(timeout >= 0); + NSAssert(timeout >= 0, @"Invalid timeout"); grpc_slice host_slice = grpc_empty_slice(); if (serverAuthority) { host_slice = grpc_slice_from_copied_string(serverAuthority.UTF8String); @@ -216,8 +219,12 @@ NSTimeInterval kChannelDestroyDelay = 30; }); } -- (nullable instancetype)initWithUnmanagedChannel:(nullable grpc_channel *)unmanagedChannel +- (nullable instancetype)initWithUnmanagedChannel:(grpc_channel * _Nullable)unmanagedChannel configuration:(GRPCChannelConfiguration *)configuration { + NSAssert(configuration, @"Configuration must not be empty."); + if (!unmanagedChannel) { + return nil; + } if ((self = [super init])) { _unmanagedChannel = unmanagedChannel; _configuration = [configuration copy]; From 836640dc4a9e8d62fc0e1218e81076a06a3035a9 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sat, 20 Oct 2018 09:41:34 -0700 Subject: [PATCH 101/375] Mark GRPCChannel:new: unavailable --- src/objective-c/GRPCClient/GRPCCall.h | 2 +- src/objective-c/GRPCClient/private/GRPCChannel.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index c862609b21c..13dcfa07130 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -218,7 +218,7 @@ extern NSString * const kGRPCTrailersKey; - (instancetype)init NS_UNAVAILABLE; -+ (instancetype) new NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; /** * Designated initializer for a call. diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index 5f5fae04135..5fb18e0332e 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -32,6 +32,8 @@ struct grpc_channel_credentials; - (nullable instancetype)init NS_UNAVAILABLE; ++ (nullable instancetype)new NS_UNAVAILABLE; + /** * Returns a channel connecting to \a host with options as \a callOptions. The channel may be new * or a cached channel that is already connected. From c6fc07d384fe11ca4dc59111b61557053ed3dbac Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sat, 20 Oct 2018 09:44:44 -0700 Subject: [PATCH 102/375] Relocate global channel pool variables --- src/objective-c/GRPCClient/private/GRPCChannel.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 6b5d1fe0719..ac4b88f3049 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -32,9 +32,12 @@ #import #import -// When all calls of a channel are destroyed, destroy the channel after this much seconds. +/** When all calls of a channel are destroyed, destroy the channel after this much seconds. */ NSTimeInterval kChannelDestroyDelay = 30; +/** Global instance of channel pool. */ +static GRPCChannelPool *gChannelPool; + /** * Time the channel destroy when the channel's calls are unreffed. If there's new call, reset the * timer. @@ -268,11 +271,9 @@ NSTimeInterval kChannelDestroyDelay = 30; return [[GRPCChannel alloc] initWithUnmanagedChannel:unmanaged_channel configuration:config]; } -static dispatch_once_t initChannelPool; -static GRPCChannelPool *gChannelPool; - + (nullable instancetype)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { + static dispatch_once_t initChannelPool; dispatch_once(&initChannelPool, ^{ gChannelPool = [[GRPCChannelPool alloc] init]; }); From ef830758cc90924e9fdd5be6a451774fad326db0 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sat, 20 Oct 2018 09:50:36 -0700 Subject: [PATCH 103/375] Comments to methods of GRPCChannelConfiguration --- src/objective-c/GRPCClient/private/GRPCChannelPool.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index e9c2ef2bd14..43e07b98454 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -29,12 +29,22 @@ NS_ASSUME_NONNULL_BEGIN @class GRPCChannel; +/** Caching signature of a channel. */ @interface GRPCChannelConfiguration : NSObject +/** The host that this channel is connected to. */ @property(copy, readonly) NSString *host; + +/** + * Options of the corresponding call. Note that only the channel-related options are of interest to + * this class. + */ @property(strong, readonly) GRPCCallOptions *callOptions; +/** Acquire the factory to generate a new channel with current configurations. */ @property(readonly) id channelFactory; + +/** Acquire the dictionary of channel args with current configurations. */ @property(readonly) NSDictionary *channelArgs; - (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; From dcf5f1ff384da2cf0dd6b38bb9062caed58e35c0 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sat, 20 Oct 2018 10:03:59 -0700 Subject: [PATCH 104/375] Comments to GRPCChannelFactory --- src/objective-c/GRPCClient/private/GRPCChannelFactory.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h index 492145da80b..14dc7079ba3 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h @@ -22,8 +22,10 @@ NS_ASSUME_NONNULL_BEGIN +/** A factory interface which generates new channel. */ @protocol GRPCChannelFactory + /** Create a channel with specific channel args to a specific host. */ - (nullable grpc_channel *)createChannelWithHost:(NSString *)host channelArgs:(nullable NSDictionary *)args; From 4efa40d7cda4537e42adaa0dbd70097886d2c91c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sat, 20 Oct 2018 10:06:07 -0700 Subject: [PATCH 105/375] Validate parameters of GRPCChannelConfiguration:initWithHost: --- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 8e0f6976cf9..80fa9c9151f 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -35,6 +35,8 @@ extern const char *kCFStreamVarName; @implementation GRPCChannelConfiguration - (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { + NSAssert(host.length, @"Host must not be empty."); + NSAssert(callOptions, @"callOptions must not be empty."); if ((self = [super init])) { _host = [host copy]; _callOptions = [callOptions copy]; From ed1e6c48e05e510186303e430a800078128dfc89 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sat, 20 Oct 2018 12:09:19 -0700 Subject: [PATCH 106/375] More verbose channel destroy message --- src/objective-c/GRPCClient/private/GRPCChannel.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index 5fb18e0332e..7151dbb6e9c 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -59,8 +59,8 @@ struct grpc_channel_credentials; - (void)ref; /** - * Decrease the refcount of the channel. If the refcount of the channel decrease to 0, start a timer - * to destroy the channel + * Decrease the refcount of the channel. If the refcount of the channel decrease to 0, the channel + * is destroyed after 30 seconds. */ - (void)unref; From e667a3fb8f3465732926d44bc882dfaabc8dae54 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sat, 20 Oct 2018 12:25:25 -0700 Subject: [PATCH 107/375] Another copy --- src/objective-c/GRPCClient/private/GRPCChannel.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index ac4b88f3049..f3ac140599e 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -264,7 +264,7 @@ static GRPCChannelPool *gChannelPool; [args addEntriesFromDictionary:config.callOptions.additionalChannelArgs]; channelArgs = args; } else { - channelArgs = config.channelArgs; + channelArgs = [config.channelArgs copy]; } id factory = config.channelFactory; grpc_channel *unmanaged_channel = [factory createChannelWithHost:host channelArgs:channelArgs]; From ae99d3a5ed45e135f8b9bd9235b252fed56aa417 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sat, 20 Oct 2018 12:41:05 -0700 Subject: [PATCH 108/375] Document GRPCAuthorizationProtocol --- src/objective-c/GRPCClient/GRPCCallOptions.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 484f15fde6e..4a93db84bc2 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -57,7 +57,15 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { GRPCTransportTypeInsecure, }; +/** + * Implement this protocol to provide a token to gRPC when a call is initiated. + */ @protocol GRPCAuthorizationProtocol + +/** + * This method is called when gRPC is about to start the call. When OAuth token is acquired, + * \a handler is expected to be called with \a token being the new token to be used for this call. + */ - (void)getTokenWithHandler:(void (^)(NSString *token))hander; @end From 9a15b6a5cfa81ab31afb4945cc1ccd8fe5be5665 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sat, 20 Oct 2018 13:00:38 -0700 Subject: [PATCH 109/375] clang-format --- src/objective-c/GRPCClient/GRPCCall.h | 16 +++++++++------- src/objective-c/GRPCClient/GRPCCall.m | 2 +- src/objective-c/GRPCClient/GRPCCallOptions.h | 8 +++----- src/objective-c/GRPCClient/GRPCCallOptions.m | 14 +++++++------- .../GRPCClient/private/ChannelArgsUtil.h | 14 +++++++++----- src/objective-c/GRPCClient/private/GRPCChannel.h | 2 +- src/objective-c/GRPCClient/private/GRPCChannel.m | 2 +- .../GRPCClient/private/GRPCChannelFactory.h | 2 +- src/objective-c/ProtoRPC/ProtoRPC.h | 11 ++++++----- src/objective-c/ProtoRPC/ProtoRPC.m | 11 ++++++----- src/objective-c/tests/GRPCClientTests.m | 7 ++++--- src/objective-c/tests/InteropTests.m | 7 ++++--- 12 files changed, 52 insertions(+), 44 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 13dcfa07130..b3936ad8fc1 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -147,8 +147,8 @@ typedef NS_ENUM(NSUInteger, GRPCErrorCode) { * Keys used in |NSError|'s |userInfo| dictionary to store the response headers and trailers sent by * the server. */ -extern NSString * const kGRPCHeadersKey; -extern NSString * const kGRPCTrailersKey; +extern NSString *const kGRPCHeadersKey; +extern NSString *const kGRPCTrailersKey; /** An object can implement this protocol to receive responses from server from a call. */ @protocol GRPCResponseHandler @@ -156,13 +156,13 @@ extern NSString * const kGRPCTrailersKey; @optional /** Issued when initial metadata is received from the server. */ -- (void)receivedInitialMetadata:(NSDictionary * _Nullable)initialMetadata; +- (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata; /** * Issued when a message is received from the server. The message is the raw data received from the * server, with decompression and without proto deserialization. */ -- (void)receivedRawMessage:(NSData * _Nullable)message; +- (void)receivedRawMessage:(NSData *_Nullable)message; /** * Issued when a call finished. If the call finished successfully, \a error is nil and \a @@ -170,7 +170,8 @@ extern NSString * const kGRPCTrailersKey; * is non-nil and contains the corresponding error information, including gRPC error codes and * error descriptions. */ -- (void)closedWithTrailingMetadata:(NSDictionary * _Nullable)trailingMetadata error:(NSError * _Nullable)error; +- (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata + error:(NSError *_Nullable)error; @required @@ -218,7 +219,7 @@ extern NSString * const kGRPCTrailersKey; - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; ++ (instancetype) new NS_UNAVAILABLE; /** * Designated initializer for a call. @@ -228,7 +229,8 @@ extern NSString * const kGRPCTrailersKey; */ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)responseHandler - callOptions:(GRPCCallOptions * _Nullable)callOptions NS_DESIGNATED_INITIALIZER; + callOptions:(GRPCCallOptions *_Nullable)callOptions + NS_DESIGNATED_INITIALIZER; /** * Convenience initializer for a call that uses default call options (see GRPCCallOptions.m for * the default options). diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 34a0e436eaa..60a946a472c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -108,7 +108,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)responseHandler - callOptions:(GRPCCallOptions * _Nullable)callOptions { + callOptions:(GRPCCallOptions *_Nullable)callOptions { if (requestOptions.host.length == 0 || requestOptions.path.length == 0) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; } diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 4a93db84bc2..d1daaa1d822 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -27,14 +27,12 @@ typedef NS_ENUM(NSUInteger, GRPCCallSafety) { /** 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, }; - - // Compression algorithm to be used by a gRPC call typedef NS_ENUM(NSInteger, GRPCCompressionAlgorithm) { GRPCCompressNone = 0, diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index e148664925c..fe75c17b09a 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -102,7 +102,7 @@ static const NSUInteger kDefaultChannelID = 0; initialMetadata:kDefaultInitialMetadata userAgentPrefix:kDefaultUserAgentPrefix responseSizeLimit:kDefaultResponseSizeLimit - compressionAlgorithm:kDefaultCompressionAlgorithm + compressionAlgorithm:kDefaultCompressionAlgorithm enableRetry:kDefaultEnableRetry keepaliveInterval:kDefaultKeepaliveInterval keepaliveTimeout:kDefaultKeepaliveTimeout @@ -127,7 +127,7 @@ static const NSUInteger kDefaultChannelID = 0; initialMetadata:(NSDictionary *)initialMetadata userAgentPrefix:(NSString *)userAgentPrefix responseSizeLimit:(NSUInteger)responseSizeLimit - compressionAlgorithm:(GRPCCompressionAlgorithm)compressionAlgorithm + compressionAlgorithm:(GRPCCompressionAlgorithm)compressionAlgorithm enableRetry:(BOOL)enableRetry keepaliveInterval:(NSTimeInterval)keepaliveInterval keepaliveTimeout:(NSTimeInterval)keepaliveTimeout @@ -181,7 +181,7 @@ static const NSUInteger kDefaultChannelID = 0; initialMetadata:_initialMetadata userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit - compressionAlgorithm:_compressionAlgorithm + compressionAlgorithm:_compressionAlgorithm enableRetry:_enableRetry keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout @@ -209,7 +209,7 @@ static const NSUInteger kDefaultChannelID = 0; initialMetadata:_initialMetadata userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit - compressionAlgorithm:_compressionAlgorithm + compressionAlgorithm:_compressionAlgorithm enableRetry:_enableRetry keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout @@ -326,7 +326,7 @@ static const NSUInteger kDefaultChannelID = 0; initialMetadata:kDefaultInitialMetadata userAgentPrefix:kDefaultUserAgentPrefix responseSizeLimit:kDefaultResponseSizeLimit - compressionAlgorithm:kDefaultCompressionAlgorithm + compressionAlgorithm:kDefaultCompressionAlgorithm enableRetry:kDefaultEnableRetry keepaliveInterval:kDefaultKeepaliveInterval keepaliveTimeout:kDefaultKeepaliveTimeout @@ -353,7 +353,7 @@ static const NSUInteger kDefaultChannelID = 0; initialMetadata:_initialMetadata userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit - compressionAlgorithm:_compressionAlgorithm + compressionAlgorithm:_compressionAlgorithm enableRetry:_enableRetry keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout @@ -381,7 +381,7 @@ static const NSUInteger kDefaultChannelID = 0; initialMetadata:_initialMetadata userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit - compressionAlgorithm:_compressionAlgorithm + compressionAlgorithm:_compressionAlgorithm enableRetry:_enableRetry keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout diff --git a/src/objective-c/GRPCClient/private/ChannelArgsUtil.h b/src/objective-c/GRPCClient/private/ChannelArgsUtil.h index 3fb876ecc4a..f271e846f00 100644 --- a/src/objective-c/GRPCClient/private/ChannelArgsUtil.h +++ b/src/objective-c/GRPCClient/private/ChannelArgsUtil.h @@ -24,11 +24,15 @@ void GRPCFreeChannelArgs(grpc_channel_args* channel_args); /** - * Allocates a @c grpc_channel_args and populates it with the options specified in the - * @c dictionary. Keys must be @c NSString, @c NSNumber, or a pointer. If the value responds to - * @c @selector(UTF8String) then it will be mapped to @c GRPC_ARG_STRING. If the value responds to - * @c @selector(intValue), it will be mapped to @c GRPC_ARG_INTEGER. Otherwise, if the value is not - * nil, it is mapped as a pointer. The caller of this function is responsible for calling + * Allocates a @c grpc_channel_args and populates it with the options specified + * in the + * @c dictionary. Keys must be @c NSString, @c NSNumber, or a pointer. If the + * value responds to + * @c @selector(UTF8String) then it will be mapped to @c GRPC_ARG_STRING. If the + * value responds to + * @c @selector(intValue), it will be mapped to @c GRPC_ARG_INTEGER. Otherwise, + * if the value is not nil, it is mapped as a pointer. The caller of this + * function is responsible for calling * @c GRPCFreeChannelArgs to free the @c grpc_channel_args struct. */ grpc_channel_args* GRPCBuildChannelArgs(NSDictionary* dictionary); diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index 7151dbb6e9c..e1bf8fb1af4 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -32,7 +32,7 @@ struct grpc_channel_credentials; - (nullable instancetype)init NS_UNAVAILABLE; -+ (nullable instancetype)new NS_UNAVAILABLE; ++ (nullable instancetype) new NS_UNAVAILABLE; /** * Returns a channel connecting to \a host with options as \a callOptions. The channel may be new diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index f3ac140599e..018ed28a7ab 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -222,7 +222,7 @@ static GRPCChannelPool *gChannelPool; }); } -- (nullable instancetype)initWithUnmanagedChannel:(grpc_channel * _Nullable)unmanagedChannel +- (nullable instancetype)initWithUnmanagedChannel:(grpc_channel *_Nullable)unmanagedChannel configuration:(GRPCChannelConfiguration *)configuration { NSAssert(configuration, @"Configuration must not be empty."); if (!unmanagedChannel) { diff --git a/src/objective-c/GRPCClient/private/GRPCChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h index 14dc7079ba3..a934e966e9d 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h @@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN /** A factory interface which generates new channel. */ @protocol GRPCChannelFactory - /** Create a channel with specific channel args to a specific host. */ +/** Create a channel with specific channel args to a specific host. */ - (nullable grpc_channel *)createChannelWithHost:(NSString *)host channelArgs:(nullable NSDictionary *)args; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 3a7fd58fb16..960a9a12bd2 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -31,12 +31,12 @@ NS_ASSUME_NONNULL_BEGIN @optional /** Issued when initial metadata is received from the server. */ -- (void)receivedInitialMetadata:(NSDictionary * _Nullable)initialMetadata; +- (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata; /** * Issued when a message is received from the server. The message is the deserialized proto object. */ -- (void)receivedProtoMessage:(GPBMessage * _Nullable)message; +- (void)receivedProtoMessage:(GPBMessage *_Nullable)message; /** * Issued when a call finished. If the call finished successfully, \a error is nil and \a @@ -44,7 +44,8 @@ NS_ASSUME_NONNULL_BEGIN * is non-nil and contains the corresponding error information, including gRPC error codes and * error descriptions. */ -- (void)closedWithTrailingMetadata:(NSDictionary * _Nullable)trailingMetadata error:(NSError * _Nullable)error; +- (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata + error:(NSError *_Nullable)error; @required @@ -70,7 +71,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions message:(GPBMessage *)message responseHandler:(id)handler - callOptions:(GRPCCallOptions * _Nullable)callOptions + callOptions:(GRPCCallOptions *_Nullable)callOptions responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; /** @@ -95,7 +96,7 @@ NS_ASSUME_NONNULL_BEGIN */ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)handler - callOptions:(GRPCCallOptions * _Nullable)callOptions + callOptions:(GRPCCallOptions *_Nullable)callOptions responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; /** diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index f6e3298f623..28c037e6092 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -34,7 +34,7 @@ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions message:(GPBMessage *)message responseHandler:(id)handler - callOptions:(GRPCCallOptions * _Nullable)callOptions + callOptions:(GRPCCallOptions *_Nullable)callOptions responseClass:(Class)responseClass { if ((self = [super init])) { _call = [[GRPCStreamingProtoCall alloc] initWithRequestOptions:requestOptions @@ -70,7 +70,7 @@ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)handler - callOptions:(GRPCCallOptions * _Nullable)callOptions + callOptions:(GRPCCallOptions *_Nullable)callOptions responseClass:(Class)responseClass { if (requestOptions.host.length == 0 || requestOptions.path.length == 0) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; @@ -153,7 +153,7 @@ }); } -- (void)receivedInitialMetadata:(NSDictionary * _Nullable)initialMetadata { +- (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { if (_handler && initialMetadata != nil) { id handler = _handler; if ([handler respondsToSelector:@selector(initialMetadata:)]) { @@ -164,7 +164,7 @@ } } -- (void)receivedRawMessage:(NSData * _Nullable)message { +- (void)receivedRawMessage:(NSData *_Nullable)message { if (_handler && message != nil) { id handler = _handler; NSError *error = nil; @@ -188,7 +188,8 @@ } } -- (void)closedWithTrailingMetadata:(NSDictionary * _Nullable)trailingMetadata error:(NSError * _Nullable)error { +- (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata + error:(NSError *_Nullable)error { if (_handler) { id handler = _handler; if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 0a9ec97c488..0d1b80e33c8 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -114,19 +114,20 @@ static GRPCProtoMethod *kFullDuplexCallMethod; return self; } -- (void)receivedInitialMetadata:(NSDictionary * _Nullable)initialMetadata { +- (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { if (_initialMetadataCallback) { _initialMetadataCallback(initialMetadata); } } -- (void)receivedProtoMessage:(GPBMessage * _Nullable)message { +- (void)receivedProtoMessage:(GPBMessage *_Nullable)message { if (_messageCallback) { _messageCallback(message); } } -- (void)closedWithTrailingMetadata:(NSDictionary * _Nullable)trailingMetadata error:(NSError * _Nullable)error { +- (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata + error:(NSError *_Nullable)error { if (_closeCallback) { _closeCallback(trailingMetadata, error); } diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index fb49bb99e0a..d67dc0743e8 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -102,19 +102,20 @@ BOOL isRemoteInteropTest(NSString *host) { return self; } -- (void)receivedInitialMetadata:(NSDictionary * _Nullable)initialMetadata { +- (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { if (_initialMetadataCallback) { _initialMetadataCallback(initialMetadata); } } -- (void)receivedProtoMessage:(GPBMessage * _Nullable)message { +- (void)receivedProtoMessage:(GPBMessage *_Nullable)message { if (_messageCallback) { _messageCallback(message); } } -- (void)closedWithTrailingMetadata:(NSDictionary * _Nullable)trailingMetadata error:(NSError * _Nullable)error { +- (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata + error:(NSError *_Nullable)error { if (_closeCallback) { _closeCallback(trailingMetadata, error); } From 2b0470dcb3bd8306adb1c63a81c931482e86c5fa Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sat, 20 Oct 2018 13:07:02 -0700 Subject: [PATCH 110/375] Ignore serverAuthority when using Cronet transport --- src/objective-c/GRPCClient/private/GRPCChannel.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 018ed28a7ab..60c2e29a6ec 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -161,7 +161,8 @@ static GRPCChannelPool *gChannelPool; __block grpc_call *call = nil; dispatch_sync(_dispatchQueue, ^{ if (self->_unmanagedChannel) { - NSString *serverAuthority = callOptions.serverAuthority; + NSString *serverAuthority = + callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; NSTimeInterval timeout = callOptions.timeout; NSAssert(timeout >= 0, @"Invalid timeout"); grpc_slice host_slice = grpc_empty_slice(); From 5c7ab989bed8e8b757db0de077571eeec66d3f2f Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 22 Oct 2018 11:13:39 -0700 Subject: [PATCH 111/375] bool->BOOL --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 60a946a472c..7e0640e8ae1 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -103,7 +103,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; /** Serial dispatch queue for tasks inside the call. */ dispatch_queue_t _dispatchQueue; /** Flags whether call has started. */ - bool _started; + BOOL _started; } - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions From b03adfbf067cc4f7ef05eb7fa8cbf49c08b3bf6b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 22 Oct 2018 12:14:43 -0700 Subject: [PATCH 112/375] More nullability specifier --- src/objective-c/GRPCClient/GRPCCall.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index b3936ad8fc1..2f23b879f13 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -304,7 +304,7 @@ NS_ASSUME_NONNULL_END * * The property is initialized to an empty NSMutableDictionary. */ -@property(atomic, readonly) NSMutableDictionary *requestHeaders; +@property(null_unspecified, atomic, readonly) NSMutableDictionary * requestHeaders; /** * This dictionary is populated with the HTTP headers received from the server. This happens before @@ -315,7 +315,7 @@ NS_ASSUME_NONNULL_END * 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; +@property(null_unspecified, atomic, readonly) NSDictionary *responseHeaders; /** * Same as responseHeaders, but populated with the HTTP trailers received from the server before the @@ -324,7 +324,7 @@ NS_ASSUME_NONNULL_END * 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; +@property(null_unspecified, atomic, readonly) NSDictionary *responseTrailers; /** * The request writer has to write NSData objects into the provided Writeable. The server will @@ -337,9 +337,9 @@ NS_ASSUME_NONNULL_END * 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 *)requestWriter; +- (instancetype _Null_unspecified)initWithHost:(NSString * _Null_unspecified)host + path:(NSString * _Null_unspecified)path + requestsWriter:(GRXWriter * _Null_unspecified)requestWriter; /** * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and @@ -350,10 +350,10 @@ NS_ASSUME_NONNULL_END /** * The following methods are deprecated. */ -+ (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString *)host path:(NSString *)path; -@property(atomic, copy, readwrite) NSString *serverName; ++ (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString * _Null_unspecified)host path:(NSString * _Null_unspecified)path; +@property(null_unspecified, atomic, copy, readwrite) NSString *serverName; @property NSTimeInterval timeout; -- (void)setResponseDispatchQueue:(dispatch_queue_t)queue; +- (void)setResponseDispatchQueue:(dispatch_queue_t _Null_unspecified)queue; @end @@ -364,11 +364,11 @@ DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.") @protocol GRPCRequestHeaders @property(nonatomic, readonly) NSUInteger count; -- (id)objectForKeyedSubscript:(id)key; -- (void)setObject:(id)obj forKeyedSubscript:(id)key; +- (id _Null_unspecified)objectForKeyedSubscript:(id _Null_unspecified)key; +- (void)setObject:(id _Null_unspecified)obj forKeyedSubscript:(id _Null_unspecified)key; - (void)removeAllObjects; -- (void)removeObjectForKey:(id)key; +- (void)removeObjectForKey:(id _Null_unspecified)key; @end #pragma clang diagnostic push From fb1ebfef00e5153e30c1a008a350c53dde4335c3 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 22 Oct 2018 13:56:10 -0700 Subject: [PATCH 113/375] Fix test flake --- src/objective-c/tests/GRPCClientTests.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 0d1b80e33c8..2021540f28d 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -120,7 +120,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; } } -- (void)receivedProtoMessage:(GPBMessage *_Nullable)message { +- (void)receivedRawMessage:(GPBMessage *_Nullable)message { if (_messageCallback) { _messageCallback(message); } @@ -803,7 +803,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; __weak XCTestExpectation *completion = [self expectationWithDescription:@"Timeout in a second."]; NSString *const kDummyAddress = [NSString stringWithFormat:@"8.8.8.8:1"]; GRPCCall *call = [[GRPCCall alloc] initWithHost:kDummyAddress - path:@"" + path:@"/dummyPath" requestsWriter:[GRXWriter writerWithValue:[NSData data]]]; [GRPCCall setMinConnectTimeout:timeout * 1000 initialBackoff:backoff * 1000 From 3566540f16451ea87aff980b5de13c41a8debeb6 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 22 Oct 2018 14:45:38 -0700 Subject: [PATCH 114/375] nit: group includes --- src/objective-c/GRPCClient/private/GRPCHost.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 41d3bec4efa..c0d75c0f319 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -20,11 +20,11 @@ #import #import +#import #include #include -#import #import "GRPCChannelFactory.h" #import "GRPCCompletionQueue.h" #import "GRPCConnectivityMonitor.h" From e13c8678264d85353bb2ce49ae829c03f6c9493f Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 22 Oct 2018 18:25:16 -0700 Subject: [PATCH 115/375] Do not issue more message when the call is canceled --- src/objective-c/GRPCClient/GRPCCall.m | 61 ++++++++++++++++++++------- src/objective-c/ProtoRPC/ProtoRPC.m | 43 ++++++++++++++----- 2 files changed, 78 insertions(+), 26 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 7e0640e8ae1..23c8d0f2d71 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -104,6 +104,11 @@ const char *kCFStreamVarName = "grpc_cfstream"; dispatch_queue_t _dispatchQueue; /** Flags whether call has started. */ BOOL _started; + /** + * Flags that the call has been canceled. When this is true, pending initial metadata and message + * should not be issued to \a _handler. This ivar must be accessed with lock to self. + */ + BOOL _canceled; } - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions @@ -135,6 +140,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } dispatch_set_target_queue(responseHandler.dispatchQueue, _dispatchQueue); _started = NO; + _canceled = NO; } return self; @@ -217,6 +223,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; self->_pipe = nil; } if (self->_handler) { + @synchronized(self) { + self->_canceled = YES; + } id handler = self->_handler; dispatch_async(handler.dispatchQueue, ^{ if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { @@ -252,30 +261,50 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)issueInitialMetadata:(NSDictionary *)initialMetadata { - id handler = _handler; - if ([handler respondsToSelector:@selector(receivedInitialMetadata:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler receivedInitialMetadata:initialMetadata]; - }); + if (_handler != nil && initialMetadata != nil) { + id handler = _handler; + if ([handler respondsToSelector:@selector(receivedInitialMetadata:)]) { + dispatch_async(handler.dispatchQueue, ^{ + // Do not issue initial metadata if the call is already canceled. + __block BOOL canceled = NO; + @synchronized(self) { + canceled = self->_canceled; + } + if (!canceled) { + [handler receivedInitialMetadata:initialMetadata]; + } + }); + } } } - (void)issueMessage:(id)message { - id handler = _handler; - if ([handler respondsToSelector:@selector(receivedRawMessage:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler receivedRawMessage:message]; - }); + if (_handler != nil && message != nil) { + id handler = _handler; + if ([handler respondsToSelector:@selector(receivedRawMessage:)]) { + dispatch_async(handler.dispatchQueue, ^{ + // Do not issue message if the call is already canceled. + __block BOOL canceled = NO; + @synchronized(self) { + canceled = self->_canceled; + } + if (!canceled) { + [handler receivedRawMessage:message]; + } + }); + } } } - (void)issueClosedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { - id handler = _handler; - NSDictionary *trailers = _call.responseTrailers; - if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:trailers error:error]; - }); + if (_handler != nil) { + id handler = _handler; + NSDictionary *trailers = _call.responseTrailers; + if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + dispatch_async(handler.dispatchQueue, ^{ + [handler closedWithTrailingMetadata:trailers error:error]; + }); + } } } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 28c037e6092..a6c88488fc2 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -66,6 +66,11 @@ GRPCCall2 *_call; dispatch_queue_t _dispatchQueue; + /** + * Flags that the call has been canceled. When this is true, pending initial metadata and message + * should not be issued to \a _handler. This ivar must be accessed with lock to self. + */ + BOOL _canceled; } - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions @@ -95,6 +100,7 @@ _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); } dispatch_set_target_queue(handler.dispatchQueue, _dispatchQueue); + _canceled = NO; [self start]; } @@ -110,12 +116,15 @@ - (void)cancel { dispatch_async(_dispatchQueue, ^{ - if (_call) { - [_call cancel]; - _call = nil; + if (self->_call) { + [self->_call cancel]; + self->_call = nil; } - if (_handler) { - id handler = _handler; + if (self->_handler) { + @synchronized(self) { + self->_canceled = YES; + } + id handler = self->_handler; if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { dispatch_async(handler.dispatchQueue, ^{ [handler closedWithTrailingMetadata:nil @@ -127,7 +136,7 @@ }]]; }); } - _handler = nil; + self->_handler = nil; } }); } @@ -155,10 +164,17 @@ - (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { if (_handler && initialMetadata != nil) { - id handler = _handler; + __block id handler = _handler; if ([handler respondsToSelector:@selector(initialMetadata:)]) { dispatch_async(handler.dispatchQueue, ^{ - [handler receivedInitialMetadata:initialMetadata]; + // Do not issue initial metadata if the call is already canceled. + __block BOOL canceled = NO; + @synchronized(self) { + canceled = self->_canceled; + } + if (!canceled) { + [handler receivedInitialMetadata:initialMetadata]; + } }); } } @@ -166,13 +182,20 @@ - (void)receivedRawMessage:(NSData *_Nullable)message { if (_handler && message != nil) { - id handler = _handler; + __block id handler = _handler; NSError *error = nil; GPBMessage *parsed = [_responseClass parseFromData:message error:&error]; if (parsed) { if ([handler respondsToSelector:@selector(receivedProtoMessage:)]) { dispatch_async(handler.dispatchQueue, ^{ - [handler receivedProtoMessage:parsed]; + // Do not issue message if the call is already canceled. + __block BOOL canceled = NO; + @synchronized(self) { + canceled = self->_canceled; + } + if (!canceled) { + [handler receivedProtoMessage:parsed]; + } }); } } else { From 76ddfcb6cb87611addcbc68b01264e37a4705d27 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 22 Oct 2018 18:36:59 -0700 Subject: [PATCH 116/375] Propagate internal error when failed parsing proto --- src/objective-c/ProtoRPC/ProtoRPC.m | 35 ++++++++++++++++------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index a6c88488fc2..6085f893560 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -27,6 +27,24 @@ #import #import +/** + * Generate an NSError object that represents a failure in parsing a proto class. + */ +static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsingError) { + NSDictionary *info = @{ + NSLocalizedDescriptionKey : @"Unable to parse response from the server", + NSLocalizedRecoverySuggestionErrorKey : + @"If this RPC is idempotent, retry " + @"with exponential backoff. Otherwise, query the server status before " + @"retrying.", + NSUnderlyingErrorKey : parsingError, + @"Expected class" : expectedClass, + @"Received value" : proto, + }; + // TODO(jcanizales): Use kGRPCErrorDomain and GRPCErrorCodeInternal when they're public. + return [NSError errorWithDomain:@"io.grpc" code:13 userInfo:info]; +} + @implementation GRPCUnaryProtoCall { GRPCStreamingProtoCall *_call; } @@ -201,7 +219,7 @@ } else { if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:nil error:error]; + [handler closedWithTrailingMetadata:nil error:ErrorForBadProto(message, _responseClass, error)]; }); } _handler = nil; @@ -232,21 +250,6 @@ @end -static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsingError) { - NSDictionary *info = @{ - NSLocalizedDescriptionKey : @"Unable to parse response from the server", - NSLocalizedRecoverySuggestionErrorKey : - @"If this RPC is idempotent, retry " - @"with exponential backoff. Otherwise, query the server status before " - @"retrying.", - NSUnderlyingErrorKey : parsingError, - @"Expected class" : expectedClass, - @"Received value" : proto, - }; - // TODO(jcanizales): Use kGRPCErrorDomain and GRPCErrorCodeInternal when they're public. - return [NSError errorWithDomain:@"io.grpc" code:13 userInfo:info]; -} - #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-implementations" @implementation ProtoRPC { From e39c146f0f7f1a56e0cd65ec5d707c8bb091366e Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 23 Oct 2018 10:03:48 -0700 Subject: [PATCH 117/375] Revert "Do not issue more message when the call is canceled" This reverts commit e13c8678264d85353bb2ce49ae829c03f6c9493f. --- src/objective-c/GRPCClient/GRPCCall.m | 61 +++++++-------------------- src/objective-c/ProtoRPC/ProtoRPC.m | 43 +++++-------------- 2 files changed, 26 insertions(+), 78 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 23c8d0f2d71..7e0640e8ae1 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -104,11 +104,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; dispatch_queue_t _dispatchQueue; /** Flags whether call has started. */ BOOL _started; - /** - * Flags that the call has been canceled. When this is true, pending initial metadata and message - * should not be issued to \a _handler. This ivar must be accessed with lock to self. - */ - BOOL _canceled; } - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions @@ -140,7 +135,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; } dispatch_set_target_queue(responseHandler.dispatchQueue, _dispatchQueue); _started = NO; - _canceled = NO; } return self; @@ -223,9 +217,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; self->_pipe = nil; } if (self->_handler) { - @synchronized(self) { - self->_canceled = YES; - } id handler = self->_handler; dispatch_async(handler.dispatchQueue, ^{ if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { @@ -261,50 +252,30 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)issueInitialMetadata:(NSDictionary *)initialMetadata { - if (_handler != nil && initialMetadata != nil) { - id handler = _handler; - if ([handler respondsToSelector:@selector(receivedInitialMetadata:)]) { - dispatch_async(handler.dispatchQueue, ^{ - // Do not issue initial metadata if the call is already canceled. - __block BOOL canceled = NO; - @synchronized(self) { - canceled = self->_canceled; - } - if (!canceled) { - [handler receivedInitialMetadata:initialMetadata]; - } - }); - } + id handler = _handler; + if ([handler respondsToSelector:@selector(receivedInitialMetadata:)]) { + dispatch_async(handler.dispatchQueue, ^{ + [handler receivedInitialMetadata:initialMetadata]; + }); } } - (void)issueMessage:(id)message { - if (_handler != nil && message != nil) { - id handler = _handler; - if ([handler respondsToSelector:@selector(receivedRawMessage:)]) { - dispatch_async(handler.dispatchQueue, ^{ - // Do not issue message if the call is already canceled. - __block BOOL canceled = NO; - @synchronized(self) { - canceled = self->_canceled; - } - if (!canceled) { - [handler receivedRawMessage:message]; - } - }); - } + id handler = _handler; + if ([handler respondsToSelector:@selector(receivedRawMessage:)]) { + dispatch_async(handler.dispatchQueue, ^{ + [handler receivedRawMessage:message]; + }); } } - (void)issueClosedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { - if (_handler != nil) { - id handler = _handler; - NSDictionary *trailers = _call.responseTrailers; - if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:trailers error:error]; - }); - } + id handler = _handler; + NSDictionary *trailers = _call.responseTrailers; + if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + dispatch_async(handler.dispatchQueue, ^{ + [handler closedWithTrailingMetadata:trailers error:error]; + }); } } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 6085f893560..294f3a4cf5c 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -84,11 +84,6 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing GRPCCall2 *_call; dispatch_queue_t _dispatchQueue; - /** - * Flags that the call has been canceled. When this is true, pending initial metadata and message - * should not be issued to \a _handler. This ivar must be accessed with lock to self. - */ - BOOL _canceled; } - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions @@ -118,7 +113,6 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); } dispatch_set_target_queue(handler.dispatchQueue, _dispatchQueue); - _canceled = NO; [self start]; } @@ -134,15 +128,12 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing - (void)cancel { dispatch_async(_dispatchQueue, ^{ - if (self->_call) { - [self->_call cancel]; - self->_call = nil; + if (_call) { + [_call cancel]; + _call = nil; } - if (self->_handler) { - @synchronized(self) { - self->_canceled = YES; - } - id handler = self->_handler; + if (_handler) { + id handler = _handler; if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { dispatch_async(handler.dispatchQueue, ^{ [handler closedWithTrailingMetadata:nil @@ -154,7 +145,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing }]]; }); } - self->_handler = nil; + _handler = nil; } }); } @@ -182,17 +173,10 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing - (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { if (_handler && initialMetadata != nil) { - __block id handler = _handler; + id handler = _handler; if ([handler respondsToSelector:@selector(initialMetadata:)]) { dispatch_async(handler.dispatchQueue, ^{ - // Do not issue initial metadata if the call is already canceled. - __block BOOL canceled = NO; - @synchronized(self) { - canceled = self->_canceled; - } - if (!canceled) { - [handler receivedInitialMetadata:initialMetadata]; - } + [handler receivedInitialMetadata:initialMetadata]; }); } } @@ -200,20 +184,13 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing - (void)receivedRawMessage:(NSData *_Nullable)message { if (_handler && message != nil) { - __block id handler = _handler; + id handler = _handler; NSError *error = nil; GPBMessage *parsed = [_responseClass parseFromData:message error:&error]; if (parsed) { if ([handler respondsToSelector:@selector(receivedProtoMessage:)]) { dispatch_async(handler.dispatchQueue, ^{ - // Do not issue message if the call is already canceled. - __block BOOL canceled = NO; - @synchronized(self) { - canceled = self->_canceled; - } - if (!canceled) { - [handler receivedProtoMessage:parsed]; - } + [handler receivedProtoMessage:parsed]; }); } } else { From f3e9224f0b34a6265830600c67293d96964a4c5c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 23 Oct 2018 10:22:18 -0700 Subject: [PATCH 118/375] Remove retain of handler in callbacks and dispatch to dispatchQueue --- src/objective-c/GRPCClient/GRPCCall.h | 11 +++-- src/objective-c/GRPCClient/GRPCCall.m | 21 +++------ src/objective-c/ProtoRPC/ProtoRPC.h | 8 +++- src/objective-c/ProtoRPC/ProtoRPC.m | 63 +++++++++++-------------- src/objective-c/tests/GRPCClientTests.m | 24 ++++++---- src/objective-c/tests/InteropTests.m | 24 ++++++---- 6 files changed, 77 insertions(+), 74 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 2f23b879f13..85d0a302d17 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -155,12 +155,16 @@ extern NSString *const kGRPCTrailersKey; @optional -/** Issued when initial metadata is received from the server. */ +/** + * Issued when initial metadata is received from the server. The task must be scheduled onto the + * dispatch queue in property \a dispatchQueue. + */ - (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata; /** * Issued when a message is received from the server. The message is the raw data received from the - * server, with decompression and without proto deserialization. + * server, with decompression and without proto deserialization. The task must be scheduled onto the + * dispatch queue in property \a dispatchQueue. */ - (void)receivedRawMessage:(NSData *_Nullable)message; @@ -168,7 +172,8 @@ extern NSString *const kGRPCTrailersKey; * Issued when a call finished. If the call finished successfully, \a error is nil and \a * trainingMetadata consists any trailing metadata received from the server. Otherwise, \a error * is non-nil and contains the corresponding error information, including gRPC error codes and - * error descriptions. + * error descriptions. The task must be scheduled onto the dispatch queue in property + * \a dispatchQueue. */ - (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata error:(NSError *_Nullable)error; diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 7e0640e8ae1..29a0ed4e106 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -252,30 +252,21 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)issueInitialMetadata:(NSDictionary *)initialMetadata { - id handler = _handler; - if ([handler respondsToSelector:@selector(receivedInitialMetadata:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler receivedInitialMetadata:initialMetadata]; - }); + if (initialMetadata != nil && [_handler respondsToSelector:@selector(receivedInitialMetadata:)]) { + [_handler receivedInitialMetadata:initialMetadata]; } } - (void)issueMessage:(id)message { - id handler = _handler; - if ([handler respondsToSelector:@selector(receivedRawMessage:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler receivedRawMessage:message]; - }); + if (message != nil && [_handler respondsToSelector:@selector(receivedRawMessage:)]) { + [_handler receivedRawMessage:message]; } } - (void)issueClosedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { - id handler = _handler; NSDictionary *trailers = _call.responseTrailers; - if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:trailers error:error]; - }); + if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + [_handler closedWithTrailingMetadata:trailers error:error]; } } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 960a9a12bd2..6f4b9eed759 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -30,11 +30,14 @@ NS_ASSUME_NONNULL_BEGIN @optional -/** Issued when initial metadata is received from the server. */ +/** + * Issued when initial metadata is received from the server. The task must be scheduled onto the + * dispatch queue in property \a dispatchQueue. */ - (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata; /** * Issued when a message is received from the server. The message is the deserialized proto object. + * The task must be scheduled onto the dispatch queue in property \a dispatchQueue. */ - (void)receivedProtoMessage:(GPBMessage *_Nullable)message; @@ -42,7 +45,8 @@ NS_ASSUME_NONNULL_BEGIN * Issued when a call finished. If the call finished successfully, \a error is nil and \a * trainingMetadata consists any trailing metadata received from the server. Otherwise, \a error * is non-nil and contains the corresponding error information, including gRPC error codes and - * error descriptions. + * error descriptions. The task must be scheduled onto the dispatch queue in property + * \a dispatchQueue. */ - (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata error:(NSError *_Nullable)error; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 294f3a4cf5c..27070a891d5 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -172,53 +172,44 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } - (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { - if (_handler && initialMetadata != nil) { - id handler = _handler; - if ([handler respondsToSelector:@selector(initialMetadata:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler receivedInitialMetadata:initialMetadata]; - }); + dispatch_async(_dispatchQueue, ^{ + if (initialMetadata != nil && [self->_handler respondsToSelector:@selector(initialMetadata:)]) { + [self->_handler receivedInitialMetadata:initialMetadata]; } - } + }); } - (void)receivedRawMessage:(NSData *_Nullable)message { - if (_handler && message != nil) { - id handler = _handler; - NSError *error = nil; - GPBMessage *parsed = [_responseClass parseFromData:message error:&error]; - if (parsed) { - if ([handler respondsToSelector:@selector(receivedProtoMessage:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler receivedProtoMessage:parsed]; - }); - } - } else { - if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:nil error:ErrorForBadProto(message, _responseClass, error)]; - }); + dispatch_async(_dispatchQueue, ^{ + if (self->_handler && message != nil) { + NSError *error = nil; + GPBMessage *parsed = [self->_responseClass parseFromData:message error:&error]; + if (parsed) { + if ([self->_handler respondsToSelector:@selector(receivedProtoMessage:)]) { + [self->_handler receivedProtoMessage:parsed]; + } + } else { + if ([self->_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + [self->_handler closedWithTrailingMetadata:nil error:ErrorForBadProto(message, _responseClass, error)]; + } + self->_handler = nil; + [self->_call cancel]; + self->_call = nil; } - _handler = nil; - [_call cancel]; - _call = nil; } - } + }); } - (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata error:(NSError *_Nullable)error { - if (_handler) { - id handler = _handler; - if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - dispatch_async(handler.dispatchQueue, ^{ - [handler closedWithTrailingMetadata:trailingMetadata error:error]; - }); + dispatch_async(_dispatchQueue, ^{ + if ([self->_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + [self->_handler closedWithTrailingMetadata:trailingMetadata error:error]; } - _handler = nil; - } - [_call cancel]; - _call = nil; + self->_handler = nil; + [self->_call cancel]; + self->_call = nil; + }); } - (dispatch_queue_t)dispatchQueue { diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 2021540f28d..bbe81502dcf 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -115,22 +115,28 @@ static GRPCProtoMethod *kFullDuplexCallMethod; } - (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { - if (_initialMetadataCallback) { - _initialMetadataCallback(initialMetadata); - } + dispatch_async(_dispatchQueue, ^{ + if (_initialMetadataCallback) { + _initialMetadataCallback(initialMetadata); + } + }); } - (void)receivedRawMessage:(GPBMessage *_Nullable)message { - if (_messageCallback) { - _messageCallback(message); - } + dispatch_async(_dispatchQueue, ^{ + if (_messageCallback) { + _messageCallback(message); + } + }); } - (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata error:(NSError *_Nullable)error { - if (_closeCallback) { - _closeCallback(trailingMetadata, error); - } + dispatch_async(_dispatchQueue, ^{ + if (_closeCallback) { + _closeCallback(trailingMetadata, error); + } + }); } - (dispatch_queue_t)dispatchQueue { diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index d67dc0743e8..c42718f15ee 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -103,22 +103,28 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { - if (_initialMetadataCallback) { - _initialMetadataCallback(initialMetadata); - } + dispatch_async(_dispatchQueue, ^{ + if (_initialMetadataCallback) { + _initialMetadataCallback(initialMetadata); + } + }); } - (void)receivedProtoMessage:(GPBMessage *_Nullable)message { - if (_messageCallback) { - _messageCallback(message); - } + dispatch_async(_dispatchQueue, ^{ + if (_messageCallback) { + _messageCallback(message); + } + }); } - (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata error:(NSError *_Nullable)error { - if (_closeCallback) { - _closeCallback(trailingMetadata, error); - } + dispatch_async(_dispatchQueue, ^{ + if (_closeCallback) { + _closeCallback(trailingMetadata, error); + } + }); } - (dispatch_queue_t)dispatchQueue { From 351b5d0f13138690b8ce75a7675306caec5c9e62 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 23 Oct 2018 10:28:04 -0700 Subject: [PATCH 119/375] enableRetry->retryEnabled --- src/objective-c/GRPCClient/GRPCCallOptions.h | 4 +-- src/objective-c/GRPCClient/GRPCCallOptions.m | 32 +++++++++---------- .../GRPCClient/private/GRPCChannelPool.m | 4 +-- src/objective-c/GRPCClient/private/GRPCHost.m | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index d1daaa1d822..4c8bb605eab 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -132,7 +132,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { * refer to * https://github.com/grpc/proposal/blob/master/A6-client-retries.md */ -@property(readonly) BOOL enableRetry; +@property(readonly) BOOL retryEnabled; // HTTP/2 keep-alive feature. The parameter \a keepaliveInterval specifies the interval between two // PING frames. The parameter \a keepaliveTimeout specifies the length of the period for which the @@ -279,7 +279,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { * refer to * https://github.com/grpc/proposal/blob/master/A6-client-retries.md */ -@property(readwrite) BOOL enableRetry; +@property(readwrite) BOOL retryEnabled; // HTTP/2 keep-alive feature. The parameter \a keepaliveInterval specifies the interval between two // PING frames. The parameter \a keepaliveTimeout specifies the length of the period for which the diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index fe75c17b09a..85a5a9ac89e 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -25,7 +25,7 @@ static NSDictionary *const kDefaultInitialMetadata = nil; static NSString *const kDefaultUserAgentPrefix = nil; static const NSUInteger kDefaultResponseSizeLimit = 0; static const GRPCCompressionAlgorithm kDefaultCompressionAlgorithm = GRPCCompressNone; -static const BOOL kDefaultEnableRetry = YES; +static const BOOL kDefaultRetryEnabled = YES; static const NSTimeInterval kDefaultKeepaliveInterval = 0; static const NSTimeInterval kDefaultKeepaliveTimeout = 0; static const NSTimeInterval kDefaultConnectMinTimeout = 0; @@ -53,7 +53,7 @@ static const NSUInteger kDefaultChannelID = 0; NSString *_userAgentPrefix; NSUInteger _responseSizeLimit; GRPCCompressionAlgorithm _compressionAlgorithm; - BOOL _enableRetry; + BOOL _retryEnabled; NSTimeInterval _keepaliveInterval; NSTimeInterval _keepaliveTimeout; NSTimeInterval _connectMinTimeout; @@ -78,7 +78,7 @@ static const NSUInteger kDefaultChannelID = 0; @synthesize userAgentPrefix = _userAgentPrefix; @synthesize responseSizeLimit = _responseSizeLimit; @synthesize compressionAlgorithm = _compressionAlgorithm; -@synthesize enableRetry = _enableRetry; +@synthesize retryEnabled = _retryEnabled; @synthesize keepaliveInterval = _keepaliveInterval; @synthesize keepaliveTimeout = _keepaliveTimeout; @synthesize connectMinTimeout = _connectMinTimeout; @@ -103,7 +103,7 @@ static const NSUInteger kDefaultChannelID = 0; userAgentPrefix:kDefaultUserAgentPrefix responseSizeLimit:kDefaultResponseSizeLimit compressionAlgorithm:kDefaultCompressionAlgorithm - enableRetry:kDefaultEnableRetry + retryEnabled:kDefaultRetryEnabled keepaliveInterval:kDefaultKeepaliveInterval keepaliveTimeout:kDefaultKeepaliveTimeout connectMinTimeout:kDefaultConnectMinTimeout @@ -128,7 +128,7 @@ static const NSUInteger kDefaultChannelID = 0; userAgentPrefix:(NSString *)userAgentPrefix responseSizeLimit:(NSUInteger)responseSizeLimit compressionAlgorithm:(GRPCCompressionAlgorithm)compressionAlgorithm - enableRetry:(BOOL)enableRetry + retryEnabled:(BOOL)retryEnabled keepaliveInterval:(NSTimeInterval)keepaliveInterval keepaliveTimeout:(NSTimeInterval)keepaliveTimeout connectMinTimeout:(NSTimeInterval)connectMinTimeout @@ -152,7 +152,7 @@ static const NSUInteger kDefaultChannelID = 0; _userAgentPrefix = [userAgentPrefix copy]; _responseSizeLimit = responseSizeLimit; _compressionAlgorithm = compressionAlgorithm; - _enableRetry = enableRetry; + _retryEnabled = retryEnabled; _keepaliveInterval = keepaliveInterval; _keepaliveTimeout = keepaliveTimeout; _connectMinTimeout = connectMinTimeout; @@ -182,7 +182,7 @@ static const NSUInteger kDefaultChannelID = 0; userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit compressionAlgorithm:_compressionAlgorithm - enableRetry:_enableRetry + retryEnabled:_retryEnabled keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout connectMinTimeout:_connectMinTimeout @@ -210,7 +210,7 @@ static const NSUInteger kDefaultChannelID = 0; userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit compressionAlgorithm:_compressionAlgorithm - enableRetry:_enableRetry + retryEnabled:_retryEnabled keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout connectMinTimeout:_connectMinTimeout @@ -234,7 +234,7 @@ static const NSUInteger kDefaultChannelID = 0; return NO; if (!(callOptions.responseSizeLimit == _responseSizeLimit)) return NO; if (!(callOptions.compressionAlgorithm == _compressionAlgorithm)) return NO; - if (!(callOptions.enableRetry == _enableRetry)) return NO; + if (!(callOptions.retryEnabled == _retryEnabled)) return NO; if (!(callOptions.keepaliveInterval == _keepaliveInterval)) return NO; if (!(callOptions.keepaliveTimeout == _keepaliveTimeout)) return NO; if (!(callOptions.connectMinTimeout == _connectMinTimeout)) return NO; @@ -271,7 +271,7 @@ static const NSUInteger kDefaultChannelID = 0; result ^= _userAgentPrefix.hash; result ^= _responseSizeLimit; result ^= _compressionAlgorithm; - result ^= _enableRetry; + result ^= _retryEnabled; result ^= (unsigned int)(_keepaliveInterval * 1000); result ^= (unsigned int)(_keepaliveTimeout * 1000); result ^= (unsigned int)(_connectMinTimeout * 1000); @@ -302,7 +302,7 @@ static const NSUInteger kDefaultChannelID = 0; @dynamic userAgentPrefix; @dynamic responseSizeLimit; @dynamic compressionAlgorithm; -@dynamic enableRetry; +@dynamic retryEnabled; @dynamic keepaliveInterval; @dynamic keepaliveTimeout; @dynamic connectMinTimeout; @@ -327,7 +327,7 @@ static const NSUInteger kDefaultChannelID = 0; userAgentPrefix:kDefaultUserAgentPrefix responseSizeLimit:kDefaultResponseSizeLimit compressionAlgorithm:kDefaultCompressionAlgorithm - enableRetry:kDefaultEnableRetry + retryEnabled:kDefaultRetryEnabled keepaliveInterval:kDefaultKeepaliveInterval keepaliveTimeout:kDefaultKeepaliveTimeout connectMinTimeout:kDefaultConnectMinTimeout @@ -354,7 +354,7 @@ static const NSUInteger kDefaultChannelID = 0; userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit compressionAlgorithm:_compressionAlgorithm - enableRetry:_enableRetry + retryEnabled:_retryEnabled keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout connectMinTimeout:_connectMinTimeout @@ -382,7 +382,7 @@ static const NSUInteger kDefaultChannelID = 0; userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit compressionAlgorithm:_compressionAlgorithm - enableRetry:_enableRetry + retryEnabled:_retryEnabled keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout connectMinTimeout:_connectMinTimeout @@ -436,8 +436,8 @@ static const NSUInteger kDefaultChannelID = 0; _compressionAlgorithm = compressionAlgorithm; } -- (void)setEnableRetry:(BOOL)enableRetry { - _enableRetry = enableRetry; +- (void)setRetryEnabled:(BOOL)retryEnabled { + _retryEnabled = retryEnabled; } - (void)setKeepaliveInterval:(NSTimeInterval)keepaliveInterval { diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 80fa9c9151f..1dfae32342d 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -108,8 +108,8 @@ extern const char *kCFStreamVarName; [NSNumber numberWithUnsignedInteger:(unsigned int)(_callOptions.keepaliveTimeout * 1000)]; } - if (_callOptions.enableRetry == NO) { - args[@GRPC_ARG_ENABLE_RETRIES] = [NSNumber numberWithInt:_callOptions.enableRetry]; + if (_callOptions.retryEnabled == NO) { + args[@GRPC_ARG_ENABLE_RETRIES] = [NSNumber numberWithInt:_callOptions.retryEnabled]; } if (_callOptions.connectMinTimeout > 0) { diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index c0d75c0f319..38b31c2ebcb 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -103,7 +103,7 @@ static NSMutableDictionary *gHostCache; options.userAgentPrefix = _userAgentPrefix; options.responseSizeLimit = _responseSizeLimitOverride; options.compressionAlgorithm = (GRPCCompressionAlgorithm)_compressAlgorithm; - options.enableRetry = _retryEnabled; + options.retryEnabled = _retryEnabled; options.keepaliveInterval = (NSTimeInterval)_keepaliveInterval / 1000; options.keepaliveTimeout = (NSTimeInterval)_keepaliveTimeout / 1000; options.connectMinTimeout = (NSTimeInterval)_minConnectTimeout / 1000; From 8986cfe6259fe7efc6ad438abb9e904f190c0515 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 23 Oct 2018 10:39:39 -0700 Subject: [PATCH 120/375] Assert mutual exclusion of authTokenProvider and oauth2AccessToken --- src/objective-c/GRPCClient/GRPCCall.m | 3 +++ src/objective-c/GRPCClient/GRPCCallOptions.h | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 29a0ed4e106..85a2837336d 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -781,6 +781,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; } _callOptions = callOptions; } + + NSAssert(_callOptions.authTokenProvider != nil || _callOptions.oauth2AccessToken != nil, + @"authTokenProvider and oauth2AccessToken cannot be set at the same time"); if (_callOptions.authTokenProvider != nil) { @synchronized(self) { self.isWaitingForToken = YES; diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 4c8bb605eab..27834b20088 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -91,8 +91,8 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { /** * The OAuth2 access token string. The string is prefixed with "Bearer " then used as value of the - * request's "authorization" header field. This parameter takes precedence over \a - * oauth2AccessToken. + * request's "authorization" header field. This parameter should not be used simultaneously with + * \a authTokenProvider. */ @property(copy, readonly) NSString *oauth2AccessToken; @@ -245,7 +245,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { /** * The interface to get the OAuth2 access token string. gRPC will attempt to acquire token when - * initiating the call. This parameter takes precedence over \a oauth2AccessToken. + * initiating the call. This parameter should not be used simultaneously with \a oauth2AccessToken. */ @property(readwrite) id authTokenProvider; From 3c8e9886aca311ee2b26e7f7ef827ac7efb42716 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 23 Oct 2018 10:53:11 -0700 Subject: [PATCH 121/375] Mark channelArg as copy --- src/objective-c/GRPCClient/private/GRPCChannel.m | 2 +- src/objective-c/GRPCClient/private/GRPCChannelPool.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 60c2e29a6ec..777cbab8092 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -265,7 +265,7 @@ static GRPCChannelPool *gChannelPool; [args addEntriesFromDictionary:config.callOptions.additionalChannelArgs]; channelArgs = args; } else { - channelArgs = [config.channelArgs copy]; + channelArgs = config.channelArgs; } id factory = config.channelFactory; grpc_channel *unmanaged_channel = [factory createChannelWithHost:host channelArgs:channelArgs]; diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 43e07b98454..2244361df2c 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -45,7 +45,7 @@ NS_ASSUME_NONNULL_BEGIN @property(readonly) id channelFactory; /** Acquire the dictionary of channel args with current configurations. */ -@property(readonly) NSDictionary *channelArgs; +@property(copy, readonly) NSDictionary *channelArgs; - (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; From 647e24c190465e9547583a631ac5b33de98ae812 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 23 Oct 2018 11:31:36 -0700 Subject: [PATCH 122/375] Put logContext in class extension --- gRPC.podspec | 2 +- src/objective-c/GRPCClient/GRPCCallOptions.h | 10 ----- src/objective-c/GRPCClient/GRPCCallOptions.m | 1 + .../internal/GRPCCallOptions+internal.h | 37 +++++++++++++++++++ .../GRPCClient/private/GRPCChannelPool.m | 1 + src/objective-c/GRPCClient/private/GRPCHost.m | 1 + templates/gRPC.podspec.template | 2 +- 7 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 src/objective-c/GRPCClient/internal/GRPCCallOptions+internal.h diff --git a/gRPC.podspec b/gRPC.podspec index 5e513cb1276..47a130d12d1 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -58,7 +58,7 @@ Pod::Spec.new do |s| ss.source_files = "#{src_dir}/*.{h,m}", "#{src_dir}/**/*.{h,m}" ss.exclude_files = "#{src_dir}/GRPCCall+GID.{h,m}" - ss.private_header_files = "#{src_dir}/private/*.h" + ss.private_header_files = "#{src_dir}/private/*.h", "#{src_dir}/internal/GRPCCallOptions+Internal.h" ss.dependency 'gRPC-Core', version end diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 27834b20088..4f02b344b15 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -182,11 +182,6 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { */ @property(copy, readonly) NSString *hostNameOverride; -/** - * Parameter used for internal logging. - */ -@property(readonly) id logContext; - /** * A string that specify the domain where channel is being cached. Channels with different domains * will not get cached to the same connection. @@ -331,11 +326,6 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { */ @property(copy, readwrite) NSString *hostNameOverride; -/** - * Parameter used for internal logging. - */ -@property(copy, readwrite) id logContext; - /** * A string that specify the domain where channel is being cached. Channels with different domains * will not get cached to the same channel. For example, a gRPC example app may use the channel pool diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 85a5a9ac89e..cd90bc68933 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -17,6 +17,7 @@ */ #import "GRPCCallOptions.h" +#import "internal/GRPCCallOptions+internal.h" // The default values for the call options. static NSString *const kDefaultServerAuthority = nil; diff --git a/src/objective-c/GRPCClient/internal/GRPCCallOptions+internal.h b/src/objective-c/GRPCClient/internal/GRPCCallOptions+internal.h new file mode 100644 index 00000000000..406f268ef21 --- /dev/null +++ b/src/objective-c/GRPCClient/internal/GRPCCallOptions+internal.h @@ -0,0 +1,37 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import + +@interface GRPCCallOptions () + +/** + * Parameter used for internal logging. + */ +@property(readonly) id logContext; + +@end + +@interface GRPCMutableCallOptions () + +/** + * Parameter used for internal logging. + */ +@property(readwrite) id logContext; + +@end diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 1dfae32342d..86f76678518 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -26,6 +26,7 @@ #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" #import "version.h" +#import "../internal/GRPCCallOptions+internal.h" #import #include diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 38b31c2ebcb..592e8fe776d 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -32,6 +32,7 @@ #import "GRPCSecureChannelFactory.h" #import "NSDictionary+GRPC.h" #import "version.h" +#import "../internal/GRPCCallOptions+internal.h" NS_ASSUME_NONNULL_BEGIN diff --git a/templates/gRPC.podspec.template b/templates/gRPC.podspec.template index a3190c2d8e6..a3ed1d78584 100644 --- a/templates/gRPC.podspec.template +++ b/templates/gRPC.podspec.template @@ -60,7 +60,7 @@ ss.source_files = "#{src_dir}/*.{h,m}", "#{src_dir}/**/*.{h,m}" ss.exclude_files = "#{src_dir}/GRPCCall+GID.{h,m}" - ss.private_header_files = "#{src_dir}/private/*.h" + ss.private_header_files = "#{src_dir}/private/*.h", "#{src_dir}/internal/GRPCCallOptions+Internal.h" ss.dependency 'gRPC-Core', version end From 35f6ab959e7f3d05d35aa7baeeeddeba559969f6 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 23 Oct 2018 13:10:44 -0700 Subject: [PATCH 123/375] unsigned int -> NSUInteger --- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 86f76678518..7b800686d01 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -104,9 +104,9 @@ extern const char *kCFStreamVarName; if (_callOptions.keepaliveInterval != 0) { args[@GRPC_ARG_KEEPALIVE_TIME_MS] = - [NSNumber numberWithUnsignedInteger:(unsigned int)(_callOptions.keepaliveInterval * 1000)]; + [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.keepaliveInterval * 1000)]; args[@GRPC_ARG_KEEPALIVE_TIMEOUT_MS] = - [NSNumber numberWithUnsignedInteger:(unsigned int)(_callOptions.keepaliveTimeout * 1000)]; + [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.keepaliveTimeout * 1000)]; } if (_callOptions.retryEnabled == NO) { @@ -115,15 +115,15 @@ extern const char *kCFStreamVarName; if (_callOptions.connectMinTimeout > 0) { args[@GRPC_ARG_MIN_RECONNECT_BACKOFF_MS] = - [NSNumber numberWithUnsignedInteger:(unsigned int)(_callOptions.connectMinTimeout * 1000)]; + [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectMinTimeout * 1000)]; } if (_callOptions.connectInitialBackoff > 0) { args[@GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS] = [NSNumber - numberWithUnsignedInteger:(unsigned int)(_callOptions.connectInitialBackoff * 1000)]; + numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectInitialBackoff * 1000)]; } if (_callOptions.connectMaxBackoff > 0) { args[@GRPC_ARG_MAX_RECONNECT_BACKOFF_MS] = - [NSNumber numberWithUnsignedInteger:(unsigned int)(_callOptions.connectMaxBackoff * 1000)]; + [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectMaxBackoff * 1000)]; } if (_callOptions.logContext != nil) { From cc58524994eddfbbc7cd800efe1462a7ec28d4f0 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 23 Oct 2018 13:11:06 -0700 Subject: [PATCH 124/375] isChannelOptionsEqualTo->hasChannelOptionsEqualTo --- src/objective-c/GRPCClient/GRPCCallOptions.h | 2 +- src/objective-c/GRPCClient/GRPCCallOptions.m | 2 +- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 4f02b344b15..9683bd3c638 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -199,7 +199,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { /** * Return if the channel options are equal to another object. */ -- (BOOL)isChannelOptionsEqualTo:(GRPCCallOptions *)callOptions; +- (BOOL)hasChannelOptionsEqualTo:(GRPCCallOptions *)callOptions; /** * Hash for channel options. diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index cd90bc68933..ba3255f0e4f 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -229,7 +229,7 @@ static const NSUInteger kDefaultChannelID = 0; return newOptions; } -- (BOOL)isChannelOptionsEqualTo:(GRPCCallOptions *)callOptions { +- (BOOL)hasChannelOptionsEqualTo:(GRPCCallOptions *)callOptions { if (!(callOptions.userAgentPrefix == _userAgentPrefix || [callOptions.userAgentPrefix isEqualToString:_userAgentPrefix])) return NO; diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 7b800686d01..61f5a55077a 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -150,7 +150,7 @@ extern const char *kCFStreamVarName; NSAssert([object isKindOfClass:[GRPCChannelConfiguration class]], @"Illegal :isEqual"); GRPCChannelConfiguration *obj = (GRPCChannelConfiguration *)object; if (!(obj.host == _host || [obj.host isEqualToString:_host])) return NO; - if (!(obj.callOptions == _callOptions || [obj.callOptions isChannelOptionsEqualTo:_callOptions])) + if (!(obj.callOptions == _callOptions || [obj.callOptions hasChannelOptionsEqualTo:_callOptions])) return NO; return YES; From 26108e1106cffd1767f0b7fb6ff4b0672ed6a640 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 23 Oct 2018 13:14:24 -0700 Subject: [PATCH 125/375] clang-format --- src/objective-c/GRPCClient/GRPCCall.h | 18 +++++++------ src/objective-c/GRPCClient/GRPCCallOptions.m | 10 +++---- .../GRPCClient/private/GRPCChannelPool.m | 2 +- src/objective-c/GRPCClient/private/GRPCHost.m | 2 +- src/objective-c/ProtoRPC/ProtoRPC.h | 4 +-- src/objective-c/ProtoRPC/ProtoRPC.m | 26 ++++++++++--------- 6 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 85d0a302d17..a1f139fc186 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -156,9 +156,9 @@ extern NSString *const kGRPCTrailersKey; @optional /** - * Issued when initial metadata is received from the server. The task must be scheduled onto the - * dispatch queue in property \a dispatchQueue. - */ + * Issued when initial metadata is received from the server. The task must be scheduled onto the + * dispatch queue in property \a dispatchQueue. + */ - (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata; /** @@ -309,7 +309,7 @@ NS_ASSUME_NONNULL_END * * The property is initialized to an empty NSMutableDictionary. */ -@property(null_unspecified, atomic, readonly) NSMutableDictionary * requestHeaders; +@property(null_unspecified, atomic, readonly) NSMutableDictionary *requestHeaders; /** * This dictionary is populated with the HTTP headers received from the server. This happens before @@ -342,9 +342,9 @@ NS_ASSUME_NONNULL_END * 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 _Null_unspecified)initWithHost:(NSString * _Null_unspecified)host - path:(NSString * _Null_unspecified)path - requestsWriter:(GRXWriter * _Null_unspecified)requestWriter; +- (instancetype _Null_unspecified)initWithHost:(NSString *_Null_unspecified)host + path:(NSString *_Null_unspecified)path + requestsWriter:(GRXWriter *_Null_unspecified)requestWriter; /** * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and @@ -355,7 +355,9 @@ NS_ASSUME_NONNULL_END /** * The following methods are deprecated. */ -+ (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString * _Null_unspecified)host path:(NSString * _Null_unspecified)path; ++ (void)setCallSafety:(GRPCCallSafety)callSafety + host:(NSString *_Null_unspecified)host + path:(NSString *_Null_unspecified)path; @property(null_unspecified, atomic, copy, readwrite) NSString *serverName; @property NSTimeInterval timeout; - (void)setResponseDispatchQueue:(dispatch_queue_t _Null_unspecified)queue; diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index ba3255f0e4f..0977a4ccdbc 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -183,7 +183,7 @@ static const NSUInteger kDefaultChannelID = 0; userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit compressionAlgorithm:_compressionAlgorithm - retryEnabled:_retryEnabled + retryEnabled:_retryEnabled keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout connectMinTimeout:_connectMinTimeout @@ -211,7 +211,7 @@ static const NSUInteger kDefaultChannelID = 0; userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit compressionAlgorithm:_compressionAlgorithm - retryEnabled:_retryEnabled + retryEnabled:_retryEnabled keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout connectMinTimeout:_connectMinTimeout @@ -328,7 +328,7 @@ static const NSUInteger kDefaultChannelID = 0; userAgentPrefix:kDefaultUserAgentPrefix responseSizeLimit:kDefaultResponseSizeLimit compressionAlgorithm:kDefaultCompressionAlgorithm - retryEnabled:kDefaultRetryEnabled + retryEnabled:kDefaultRetryEnabled keepaliveInterval:kDefaultKeepaliveInterval keepaliveTimeout:kDefaultKeepaliveTimeout connectMinTimeout:kDefaultConnectMinTimeout @@ -355,7 +355,7 @@ static const NSUInteger kDefaultChannelID = 0; userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit compressionAlgorithm:_compressionAlgorithm - retryEnabled:_retryEnabled + retryEnabled:_retryEnabled keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout connectMinTimeout:_connectMinTimeout @@ -383,7 +383,7 @@ static const NSUInteger kDefaultChannelID = 0; userAgentPrefix:_userAgentPrefix responseSizeLimit:_responseSizeLimit compressionAlgorithm:_compressionAlgorithm - retryEnabled:_retryEnabled + retryEnabled:_retryEnabled keepaliveInterval:_keepaliveInterval keepaliveTimeout:_keepaliveTimeout connectMinTimeout:_connectMinTimeout diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 61f5a55077a..56f76450b22 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -18,6 +18,7 @@ #import +#import "../internal/GRPCCallOptions+internal.h" #import "GRPCChannel.h" #import "GRPCChannelFactory.h" #import "GRPCChannelPool.h" @@ -26,7 +27,6 @@ #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" #import "version.h" -#import "../internal/GRPCCallOptions+internal.h" #import #include diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 592e8fe776d..ab5b69cc4e9 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -25,6 +25,7 @@ #include #include +#import "../internal/GRPCCallOptions+internal.h" #import "GRPCChannelFactory.h" #import "GRPCCompletionQueue.h" #import "GRPCConnectivityMonitor.h" @@ -32,7 +33,6 @@ #import "GRPCSecureChannelFactory.h" #import "NSDictionary+GRPC.h" #import "version.h" -#import "../internal/GRPCCallOptions+internal.h" NS_ASSUME_NONNULL_BEGIN diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 6f4b9eed759..635ba0c90ee 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -31,8 +31,8 @@ NS_ASSUME_NONNULL_BEGIN @optional /** - * Issued when initial metadata is received from the server. The task must be scheduled onto the - * dispatch queue in property \a dispatchQueue. */ + * Issued when initial metadata is received from the server. The task must be scheduled onto the + * dispatch queue in property \a dispatchQueue. */ - (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata; /** diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 27070a891d5..34891e8953b 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -28,19 +28,19 @@ #import /** - * Generate an NSError object that represents a failure in parsing a proto class. - */ + * Generate an NSError object that represents a failure in parsing a proto class. + */ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsingError) { NSDictionary *info = @{ - NSLocalizedDescriptionKey : @"Unable to parse response from the server", - NSLocalizedRecoverySuggestionErrorKey : - @"If this RPC is idempotent, retry " - @"with exponential backoff. Otherwise, query the server status before " - @"retrying.", - NSUnderlyingErrorKey : parsingError, - @"Expected class" : expectedClass, - @"Received value" : proto, - }; + NSLocalizedDescriptionKey : @"Unable to parse response from the server", + NSLocalizedRecoverySuggestionErrorKey : + @"If this RPC is idempotent, retry " + @"with exponential backoff. Otherwise, query the server status before " + @"retrying.", + NSUnderlyingErrorKey : parsingError, + @"Expected class" : expectedClass, + @"Received value" : proto, + }; // TODO(jcanizales): Use kGRPCErrorDomain and GRPCErrorCodeInternal when they're public. return [NSError errorWithDomain:@"io.grpc" code:13 userInfo:info]; } @@ -190,7 +190,9 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } } else { if ([self->_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - [self->_handler closedWithTrailingMetadata:nil error:ErrorForBadProto(message, _responseClass, error)]; + [self->_handler + closedWithTrailingMetadata:nil + error:ErrorForBadProto(message, _responseClass, error)]; } self->_handler = nil; [self->_call cancel]; From 1cbb484729706cf89b140b8a746562a53d916e8b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 24 Oct 2018 10:45:07 -0700 Subject: [PATCH 126/375] Fix build failure --- .../GRPCClient/internal/GRPCCallOptions+internal.h | 2 ++ .../GRPCClient/private/GRPCCronetChannelFactory.m | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/internal/GRPCCallOptions+internal.h b/src/objective-c/GRPCClient/internal/GRPCCallOptions+internal.h index 406f268ef21..eb691b3acb1 100644 --- a/src/objective-c/GRPCClient/internal/GRPCCallOptions+internal.h +++ b/src/objective-c/GRPCClient/internal/GRPCCallOptions+internal.h @@ -18,6 +18,8 @@ #import +#import "../GRPCCallOptions.h" + @interface GRPCCallOptions () /** diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m index 70675784678..f976e1e06a9 100644 --- a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m @@ -53,14 +53,14 @@ NS_ASSUME_NONNULL_BEGIN } - (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSDictionary *)args { + channelArgs:(NSDictionary *)args { // Remove client authority filter since that is not supported args[@GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER] = [NSNumber numberWithInt:1]; - grpc_channel_args *channelArgs = BuildChannelArgs(args); + grpc_channel_args *channelArgs = GRPCBuildChannelArgs(args); grpc_channel *unmanagedChannel = grpc_cronet_secure_channel_create(_cronetEngine, host.UTF8String, channelArgs, NULL); - FreeChannelArgs(channelArgs); + GRPCFreeChannelArgs(channelArgs); return unmanagedChannel; } From 3c33020357e58202a9909d739353f4c20f78e817 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 24 Oct 2018 13:31:45 -0700 Subject: [PATCH 127/375] Polish nullabitily --- .../GRPCClient/private/GRPCChannelFactory.h | 4 ++-- .../private/GRPCCronetChannelFactory.h | 8 ++++---- .../private/GRPCCronetChannelFactory.m | 14 +++++++------- .../private/GRPCInsecureChannelFactory.h | 8 ++++---- .../private/GRPCInsecureChannelFactory.m | 6 +++--- .../private/GRPCSecureChannelFactory.h | 12 ++++++------ .../private/GRPCSecureChannelFactory.m | 18 +++++++++--------- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h index a934e966e9d..287233f246c 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h @@ -26,8 +26,8 @@ NS_ASSUME_NONNULL_BEGIN @protocol GRPCChannelFactory /** Create a channel with specific channel args to a specific host. */ -- (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSDictionary *)args; +- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary * _Nullable)args; @end diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h index 738dfdb7370..18e84b81fa2 100644 --- a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h @@ -24,12 +24,12 @@ NS_ASSUME_NONNULL_BEGIN @interface GRPCCronetChannelFactory : NSObject -+ (nullable instancetype)sharedInstance; ++ (instancetype _Nullable)sharedInstance; -- (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSDictionary *)args; +- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary * _Nullable)args; -- (nullable instancetype)init NS_UNAVAILABLE; +- (instancetype _Nullable)init NS_UNAVAILABLE; @end diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m index f976e1e06a9..b2ab03b6488 100644 --- a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m @@ -32,7 +32,7 @@ NS_ASSUME_NONNULL_BEGIN stream_engine *_cronetEngine; } -+ (nullable instancetype)sharedInstance { ++ (instancetype _Nullable)sharedInstance { static GRPCCronetChannelFactory *instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -41,7 +41,7 @@ NS_ASSUME_NONNULL_BEGIN return instance; } -- (nullable instancetype)initWithEngine:(stream_engine *)engine { +- (instancetype _Nullable)initWithEngine:(stream_engine *)engine { if (!engine) { [NSException raise:NSInvalidArgumentException format:@"Cronet engine is NULL. Set it first."]; return nil; @@ -52,8 +52,8 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *)args { +- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary * _Nullable)args { // Remove client authority filter since that is not supported args[@GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER] = [NSNumber numberWithInt:1]; @@ -74,14 +74,14 @@ NS_ASSUME_NONNULL_BEGIN @implementation GRPCCronetChannelFactory -+ (nullable instancetype)sharedInstance { ++ (instancetype _Nullable)sharedInstance { [NSException raise:NSInvalidArgumentException format:@"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."]; return nil; } -- (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSDictionary *)args { +- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary * _Nullable)args { [NSException raise:NSInvalidArgumentException format:@"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."]; return NULL; diff --git a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h index 2d471aebed6..1175483c680 100644 --- a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h @@ -23,12 +23,12 @@ NS_ASSUME_NONNULL_BEGIN @interface GRPCInsecureChannelFactory : NSObject -+ (nullable instancetype)sharedInstance; ++ (instancetype _Nullable)sharedInstance; -- (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSDictionary *)args; +- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary * _Nullable)args; -- (nullable instancetype)init NS_UNAVAILABLE; +- (instancetype _Nullable)init NS_UNAVAILABLE; @end diff --git a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m index 5773f2d9af1..44e94831e95 100644 --- a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m @@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN @implementation GRPCInsecureChannelFactory -+ (nullable instancetype)sharedInstance { ++ (instancetype _Nullable)sharedInstance { static GRPCInsecureChannelFactory *instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -34,8 +34,8 @@ NS_ASSUME_NONNULL_BEGIN return instance; } -- (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSDictionary *)args { +- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary * _Nullable)args { grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs([args copy]); grpc_channel *unmanagedChannel = grpc_insecure_channel_create(host.UTF8String, coreChannelArgs, NULL); diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h index 588239b7064..565f58a4fab 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h @@ -23,15 +23,15 @@ NS_ASSUME_NONNULL_BEGIN @interface GRPCSecureChannelFactory : NSObject -+ (nullable instancetype)factoryWithPEMRootCertificates:(nullable NSString *)rootCerts - privateKey:(nullable NSString *)privateKey - certChain:(nullable NSString *)certChain ++ (instancetype _Nullable)factoryWithPEMRootCertificates:(NSString * _Nullable)rootCerts + privateKey:(NSString * _Nullable)privateKey + certChain:(NSString * _Nullable)certChain error:(NSError **)errorPtr; -- (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSDictionary *)args; +- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary * _Nullable)args; -- (nullable instancetype)init NS_UNAVAILABLE; +- (instancetype _Nullable)init NS_UNAVAILABLE; @end diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index aa8b52e6b8f..03cfff2ed4a 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -29,9 +29,9 @@ NS_ASSUME_NONNULL_BEGIN grpc_channel_credentials *_channelCreds; } -+ (nullable instancetype)factoryWithPEMRootCertificates:(nullable NSString *)rootCerts - privateKey:(nullable NSString *)privateKey - certChain:(nullable NSString *)certChain ++ (instancetype _Nullable)factoryWithPEMRootCertificates:(NSString * _Nullable)rootCerts + privateKey:(NSString * _Nullable)privateKey + certChain:(NSString * _Nullable)certChain error:(NSError **)errorPtr { return [[self alloc] initWithPEMRootCerts:rootCerts privateKey:privateKey @@ -39,7 +39,7 @@ NS_ASSUME_NONNULL_BEGIN error:errorPtr]; } -- (NSData *)nullTerminatedDataWithString:(NSString *)string { +- (NSData * _Nullable)nullTerminatedDataWithString:(NSString * _Nullable)string { // dataUsingEncoding: does not return a null-terminated string. NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; if (data == nil) { @@ -50,9 +50,9 @@ NS_ASSUME_NONNULL_BEGIN return nullTerminated; } -- (nullable instancetype)initWithPEMRootCerts:(nullable NSString *)rootCerts - privateKey:(nullable NSString *)privateKey - certChain:(nullable NSString *)certChain +- (instancetype _Nullable)initWithPEMRootCerts:(NSString * _Nullable)rootCerts + privateKey:(NSString * _Nullable)privateKey + certChain:(NSString * _Nullable)certChain error:(NSError **)errorPtr { static NSData *defaultRootsASCII; static NSError *defaultRootsError; @@ -116,8 +116,8 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (nullable grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(nullable NSDictionary *)args { +- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary * _Nullable)args { grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs([args copy]); grpc_channel *unmanagedChannel = grpc_secure_channel_create(_channelCreds, host.UTF8String, coreChannelArgs, NULL); From c2bb7550377898e6985662d0ca9048c07bde6810 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 24 Oct 2018 16:55:23 -0700 Subject: [PATCH 128/375] Move GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER into core --- .../cronet/client/secure/cronet_channel_create.cc | 14 ++++++++++++-- .../GRPCClient/private/GRPCCronetChannelFactory.m | 3 --- .../GRPCClient/private/GRPCWrappedCall.m | 4 +++- .../CoreCronetEnd2EndTests.mm | 6 ------ .../tests/CronetUnitTests/CronetUnitTests.m | 13 +------------ 5 files changed, 16 insertions(+), 24 deletions(-) diff --git a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc index 40a30e4a31d..dffb61b082d 100644 --- a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc +++ b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc @@ -46,9 +46,19 @@ GRPCAPI grpc_channel* grpc_cronet_secure_channel_create( "grpc_create_cronet_transport: stream_engine = %p, target=%s", engine, target); + // Disable client authority filter when using Cronet + grpc_arg arg; + arg.key = const_cast(GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER); + arg.type = GRPC_ARG_INTEGER; + arg.value.integer = 1; + grpc_channel_args* new_args = grpc_channel_args_copy_and_add(args, &arg, 1); + grpc_transport* ct = - grpc_create_cronet_transport(engine, target, args, reserved); + grpc_create_cronet_transport(engine, target, new_args, reserved); grpc_core::ExecCtx exec_ctx; - return grpc_channel_create(target, args, GRPC_CLIENT_DIRECT_CHANNEL, ct); + grpc_channel* channel = + grpc_channel_create(target, new_args, GRPC_CLIENT_DIRECT_CHANNEL, ct); + grpc_channel_args_destroy(new_args); + return channel; } diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m index b2ab03b6488..51d8df0fb71 100644 --- a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m @@ -54,9 +54,6 @@ NS_ASSUME_NONNULL_BEGIN - (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host channelArgs:(NSDictionary * _Nullable)args { - // Remove client authority filter since that is not supported - args[@GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER] = [NSNumber numberWithInt:1]; - grpc_channel_args *channelArgs = GRPCBuildChannelArgs(args); grpc_channel *unmanagedChannel = grpc_cronet_secure_channel_create(_cronetEngine, host.UTF8String, channelArgs, NULL); diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 4d5257aca79..100d4cf2914 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -310,7 +310,9 @@ } - (void)dealloc { - grpc_call_unref(_call); + if (_call) { + grpc_call_unref(_call); + } [_channel unref]; _channel = nil; } diff --git a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm index 80fa0f47852..fe85e915d4d 100644 --- a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm +++ b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm @@ -81,13 +81,7 @@ static void cronet_init_client_secure_fullstack(grpc_end2end_test_fixture *f, grpc_channel_args *client_args, stream_engine *cronetEngine) { fullstack_secure_fixture_data *ffd = (fullstack_secure_fixture_data *)f->fixture_data; - grpc_arg arg; - arg.key = const_cast(GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER); - arg.type = GRPC_ARG_INTEGER; - arg.value.integer = 1; - client_args = grpc_channel_args_copy_and_add(client_args, &arg, 1); f->client = grpc_cronet_secure_channel_create(cronetEngine, ffd->localaddr, client_args, NULL); - grpc_channel_args_destroy(client_args); GPR_ASSERT(f->client != NULL); } diff --git a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m index 84893b92c1a..d732bc6ba99 100644 --- a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m +++ b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m @@ -124,14 +124,6 @@ unsigned int parse_h2_length(const char *field) { ((unsigned int)(unsigned char)(field[2])); } -grpc_channel_args *add_disable_client_authority_filter_args(grpc_channel_args *args) { - grpc_arg arg; - arg.key = const_cast(GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER); - arg.type = GRPC_ARG_INTEGER; - arg.value.integer = 1; - return grpc_channel_args_copy_and_add(args, &arg, 1); -} - - (void)testInternalError { grpc_call *c; grpc_slice request_payload_slice = grpc_slice_from_copied_string("hello world"); @@ -151,9 +143,7 @@ grpc_channel_args *add_disable_client_authority_filter_args(grpc_channel_args *a gpr_join_host_port(&addr, "127.0.0.1", port); grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); stream_engine *cronetEngine = [Cronet getGlobalEngine]; - grpc_channel_args *client_args = add_disable_client_authority_filter_args(NULL); - grpc_channel *client = grpc_cronet_secure_channel_create(cronetEngine, addr, client_args, NULL); - grpc_channel_args_destroy(client_args); + grpc_channel *client = grpc_cronet_secure_channel_create(cronetEngine, addr, NULL, NULL); cq_verifier *cqv = cq_verifier_create(cq); grpc_op ops[6]; @@ -265,7 +255,6 @@ grpc_channel_args *add_disable_client_authority_filter_args(grpc_channel_args *a arg.type = GRPC_ARG_INTEGER; arg.value.integer = useCoalescing ? 1 : 0; grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1); - args = add_disable_client_authority_filter_args(args); grpc_call *c; grpc_slice request_payload_slice = grpc_slice_from_copied_string("hello world"); From a8a7c2bdd10eb7dc9e072327da2ddb70e5785cf7 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 24 Oct 2018 17:05:38 -0700 Subject: [PATCH 129/375] clang-format --- .../GRPCClient/private/GRPCChannelFactory.h | 4 ++-- .../private/GRPCCronetChannelFactory.h | 4 ++-- .../private/GRPCCronetChannelFactory.m | 8 +++---- .../private/GRPCInsecureChannelFactory.h | 4 ++-- .../private/GRPCInsecureChannelFactory.m | 4 ++-- .../private/GRPCSecureChannelFactory.h | 12 +++++----- .../private/GRPCSecureChannelFactory.m | 22 +++++++++---------- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h index 287233f246c..3a3500fc95e 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h @@ -26,8 +26,8 @@ NS_ASSUME_NONNULL_BEGIN @protocol GRPCChannelFactory /** Create a channel with specific channel args to a specific host. */ -- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary * _Nullable)args; +- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary *_Nullable)args; @end diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h index 18e84b81fa2..5e35576ea10 100644 --- a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h @@ -26,8 +26,8 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype _Nullable)sharedInstance; -- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary * _Nullable)args; +- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary *_Nullable)args; - (instancetype _Nullable)init NS_UNAVAILABLE; diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m index 51d8df0fb71..781881d211b 100644 --- a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m @@ -52,8 +52,8 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary * _Nullable)args { +- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary *_Nullable)args { grpc_channel_args *channelArgs = GRPCBuildChannelArgs(args); grpc_channel *unmanagedChannel = grpc_cronet_secure_channel_create(_cronetEngine, host.UTF8String, channelArgs, NULL); @@ -77,8 +77,8 @@ NS_ASSUME_NONNULL_BEGIN return nil; } -- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary * _Nullable)args { +- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary *_Nullable)args { [NSException raise:NSInvalidArgumentException format:@"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."]; return NULL; diff --git a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h index 1175483c680..98a985fe84d 100644 --- a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h @@ -25,8 +25,8 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype _Nullable)sharedInstance; -- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary * _Nullable)args; +- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary *_Nullable)args; - (instancetype _Nullable)init NS_UNAVAILABLE; diff --git a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m index 44e94831e95..99698877124 100644 --- a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m @@ -34,8 +34,8 @@ NS_ASSUME_NONNULL_BEGIN return instance; } -- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary * _Nullable)args { +- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary *_Nullable)args { grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs([args copy]); grpc_channel *unmanagedChannel = grpc_insecure_channel_create(host.UTF8String, coreChannelArgs, NULL); diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h index 565f58a4fab..02e7052996d 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h @@ -23,13 +23,13 @@ NS_ASSUME_NONNULL_BEGIN @interface GRPCSecureChannelFactory : NSObject -+ (instancetype _Nullable)factoryWithPEMRootCertificates:(NSString * _Nullable)rootCerts - privateKey:(NSString * _Nullable)privateKey - certChain:(NSString * _Nullable)certChain - error:(NSError **)errorPtr; ++ (instancetype _Nullable)factoryWithPEMRootCertificates:(NSString *_Nullable)rootCerts + privateKey:(NSString *_Nullable)privateKey + certChain:(NSString *_Nullable)certChain + error:(NSError **)errorPtr; -- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary * _Nullable)args; +- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary *_Nullable)args; - (instancetype _Nullable)init NS_UNAVAILABLE; diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 03cfff2ed4a..1f6458c5247 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -29,17 +29,17 @@ NS_ASSUME_NONNULL_BEGIN grpc_channel_credentials *_channelCreds; } -+ (instancetype _Nullable)factoryWithPEMRootCertificates:(NSString * _Nullable)rootCerts - privateKey:(NSString * _Nullable)privateKey - certChain:(NSString * _Nullable)certChain - error:(NSError **)errorPtr { ++ (instancetype _Nullable)factoryWithPEMRootCertificates:(NSString *_Nullable)rootCerts + privateKey:(NSString *_Nullable)privateKey + certChain:(NSString *_Nullable)certChain + error:(NSError **)errorPtr { return [[self alloc] initWithPEMRootCerts:rootCerts privateKey:privateKey certChain:certChain error:errorPtr]; } -- (NSData * _Nullable)nullTerminatedDataWithString:(NSString * _Nullable)string { +- (NSData *_Nullable)nullTerminatedDataWithString:(NSString *_Nullable)string { // dataUsingEncoding: does not return a null-terminated string. NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; if (data == nil) { @@ -50,10 +50,10 @@ NS_ASSUME_NONNULL_BEGIN return nullTerminated; } -- (instancetype _Nullable)initWithPEMRootCerts:(NSString * _Nullable)rootCerts - privateKey:(NSString * _Nullable)privateKey - certChain:(NSString * _Nullable)certChain - error:(NSError **)errorPtr { +- (instancetype _Nullable)initWithPEMRootCerts:(NSString *_Nullable)rootCerts + privateKey:(NSString *_Nullable)privateKey + certChain:(NSString *_Nullable)certChain + error:(NSError **)errorPtr { static NSData *defaultRootsASCII; static NSError *defaultRootsError; static dispatch_once_t loading; @@ -116,8 +116,8 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (grpc_channel * _Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary * _Nullable)args { +- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary *_Nullable)args { grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs([args copy]); grpc_channel *unmanagedChannel = grpc_secure_channel_create(_channelCreds, host.UTF8String, coreChannelArgs, NULL); From f9d2510d8f655badea3dea14493b6d4d3882705a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 26 Oct 2018 11:15:16 -0700 Subject: [PATCH 130/375] Specify nullability in ProtoRPC --- src/objective-c/ProtoRPC/ProtoRPC.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 635ba0c90ee..b0f4ced99e8 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -134,10 +134,11 @@ __attribute__((deprecated("Please use GRPCProtoCall."))) @interface ProtoRPC * addr and the port number, for example @"localhost:5050". */ - - (instancetype)initWithHost : (NSString *)host method - : (GRPCProtoMethod *)method requestsWriter : (GRXWriter *)requestsWriter responseClass - : (Class)responseClass responsesWriteable - : (id)responsesWriteable NS_DESIGNATED_INITIALIZER; + (instancetype _Null_unspecified)initWithHost : (NSString *_Null_unspecified)host method + : (GRPCProtoMethod *_Null_unspecified)method requestsWriter + : (GRXWriter *_Null_unspecified)requestsWriter responseClass + : (Class _Null_unspecified)responseClass responsesWriteable + : (id _Null_unspecified)responsesWriteable NS_DESIGNATED_INITIALIZER; - (void)start; @end From a8c4eb7d2742eb3ba370d9801cc1b83e35d551a9 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 29 Oct 2018 14:15:26 -0700 Subject: [PATCH 131/375] Bug fix --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 85a2837336d..44432a120ac 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -782,7 +782,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; _callOptions = callOptions; } - NSAssert(_callOptions.authTokenProvider != nil || _callOptions.oauth2AccessToken != nil, + NSAssert(_callOptions.authTokenProvider == nil || _callOptions.oauth2AccessToken == nil, @"authTokenProvider and oauth2AccessToken cannot be set at the same time"); if (_callOptions.authTokenProvider != nil) { @synchronized(self) { From abe4aae40049ca73fb29ccf325cc3734408d9aae Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 29 Oct 2018 15:21:05 -0700 Subject: [PATCH 132/375] Remove length check in GRPCCall for backwards compatibility --- src/objective-c/GRPCClient/GRPCCall.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 44432a120ac..ca2cdd6b312 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -391,7 +391,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; callSafety:(GRPCCallSafety)safety requestsWriter:(GRXWriter *)requestWriter callOptions:(GRPCCallOptions *)callOptions { - if (host.length == 0 || path.length == 0) { + // Purposely using pointer rather than length ([host length] == 0) for backwards compatibility. + if (!host || !path) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil or empty."]; } From aec84416a4308e547736569f2bc815a8bbd9c80f Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 29 Oct 2018 15:48:16 -0700 Subject: [PATCH 133/375] Remove NS_UNAVAILABLE for backwards compatibility --- src/objective-c/ProtoRPC/ProtoService.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h index 3a16ab24026..2105de78a38 100644 --- a/src/objective-c/ProtoRPC/ProtoService.h +++ b/src/objective-c/ProtoRPC/ProtoService.h @@ -31,14 +31,9 @@ __attribute__((deprecated("Please use GRPCProtoService."))) @interface ProtoServ : NSObject - - (instancetype)init NS_UNAVAILABLE; - -+ (instancetype) new NS_UNAVAILABLE; - -- (instancetype)initWithHost:(NSString *)host - packageName:(NSString *)packageName - serviceName:(NSString *)serviceName - callOptions:(GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; + (instancetype)initWithHost : (NSString *)host packageName + : (NSString *)packageName serviceName : (NSString *)serviceName callOptions + : (GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; - (instancetype)initWithHost:(NSString *)host packageName:(NSString *)packageName From 0cabf27fa3e5afc4918a6aaf7d51825d7c0eb8e0 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 31 Oct 2018 18:25:49 -0700 Subject: [PATCH 134/375] Clean codes --- src/objective-c/GRPCClient/GRPCCall.m | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index ca2cdd6b312..505d84a954c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -167,13 +167,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; id responseWriteable = [[GRXWriteable alloc] initWithValueHandler:^(id value) { dispatch_async(self->_dispatchQueue, ^{ if (self->_handler) { - NSDictionary *headers = nil; if (!self->_initialMetadataPublished) { - headers = self->_call.responseHeaders; self->_initialMetadataPublished = YES; - } - if (headers) { - [self issueInitialMetadata:headers]; + [self issueInitialMetadata:self->_call.responseHeaders]; } if (value) { [self issueMessage:value]; @@ -184,13 +180,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; completionHandler:^(NSError *errorOrNil) { dispatch_async(self->_dispatchQueue, ^{ if (self->_handler) { - NSDictionary *headers = nil; if (!self->_initialMetadataPublished) { - headers = self->_call.responseHeaders; self->_initialMetadataPublished = YES; - } - if (headers) { - [self issueInitialMetadata:headers]; + [self issueInitialMetadata:self->_call.responseHeaders]; } [self issueClosedWithTrailingMetadata:self->_call.responseTrailers error:errorOrNil]; From a37ec5e3e6f7184458108bd5419ce6b832061975 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 31 Oct 2018 18:26:02 -0700 Subject: [PATCH 135/375] Polish error message --- src/objective-c/GRPCClient/GRPCCall.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 505d84a954c..5aeedba9a7d 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -385,8 +385,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; callOptions:(GRPCCallOptions *)callOptions { // Purposely using pointer rather than length ([host length] == 0) for backwards compatibility. if (!host || !path) { - [NSException raise:NSInvalidArgumentException - format:@"Neither host nor path can be nil or empty."]; + [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; } if (safety > GRPCCallSafetyCacheableRequest) { [NSException raise:NSInvalidArgumentException format:@"Invalid call safety value."]; From 16fd5a758c2418dcf0be3a0985e68b1e15582387 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 31 Oct 2018 18:26:39 -0700 Subject: [PATCH 136/375] Remove __block for synchronized blocks --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 2 +- src/objective-c/GRPCClient/private/GRPCHost.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 5aeedba9a7d..8e7d5a5f94b 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -564,7 +564,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } NSMutableDictionary *headers = _requestHeaders; - __block NSString *fetchedOauth2AccessToken; + NSString *fetchedOauth2AccessToken; @synchronized(self) { fetchedOauth2AccessToken = _fetchedOauth2AccessToken; } diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 56f76450b22..7aac077e773 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -190,7 +190,7 @@ extern const char *kCFStreamVarName; } - (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration { - __block GRPCChannel *channel; + GRPCChannel *channel; @synchronized(self) { if ([_channelPool objectForKey:configuration]) { channel = _channelPool[configuration]; diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index ab5b69cc4e9..480e4621845 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -141,7 +141,7 @@ static NSMutableDictionary *gHostCache; host = [hostURL.host stringByAppendingString:@":443"]; } - __block GRPCCallOptions *callOptions = nil; + GRPCCallOptions *callOptions = nil; @synchronized(gHostCache) { if ([gHostCache objectForKey:host]) { callOptions = [gHostCache[host] callOptions]; From 73251477bc4f7cb10bf40c9f56df8a65d58689f1 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 1 Nov 2018 09:03:23 -0700 Subject: [PATCH 137/375] clamp positive NSTimeInterval in initializer --- src/objective-c/GRPCClient/GRPCCallOptions.m | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 0977a4ccdbc..8bb2ad29fc6 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -146,7 +146,7 @@ static const NSUInteger kDefaultChannelID = 0; channelID:(NSUInteger)channelID { if ((self = [super init])) { _serverAuthority = [serverAuthority copy]; - _timeout = timeout; + _timeout = timeout < 0 ? 0 : timeout; _oauth2AccessToken = [oauth2AccessToken copy]; _authTokenProvider = authTokenProvider; _initialMetadata = [[NSDictionary alloc] initWithDictionary:initialMetadata copyItems:YES]; @@ -154,11 +154,11 @@ static const NSUInteger kDefaultChannelID = 0; _responseSizeLimit = responseSizeLimit; _compressionAlgorithm = compressionAlgorithm; _retryEnabled = retryEnabled; - _keepaliveInterval = keepaliveInterval; - _keepaliveTimeout = keepaliveTimeout; - _connectMinTimeout = connectMinTimeout; - _connectInitialBackoff = connectInitialBackoff; - _connectMaxBackoff = connectMaxBackoff; + _keepaliveInterval = keepaliveInterval < 0 ? 0 : keepaliveInterval; + _keepaliveTimeout = keepaliveTimeout < 0 ? 0 : keepaliveTimeout; + _connectMinTimeout = connectMinTimeout < 0 ? 0 : connectMinTimeout; + _connectInitialBackoff = connectInitialBackoff < 0 ? 0 : connectInitialBackoff; + _connectMaxBackoff = connectMaxBackoff < 0 ? 0 : connectMaxBackoff; _additionalChannelArgs = [[NSDictionary alloc] initWithDictionary:additionalChannelArgs copyItems:YES]; _PEMRootCertificates = [PEMRootCertificates copy]; From 790adca8e397d78affef7589e1ddf94b80b052f1 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 1 Nov 2018 09:18:50 -0700 Subject: [PATCH 138/375] copy items in GRPCCallOptions:mutableCopy: --- src/objective-c/GRPCClient/GRPCCallOptions.m | 22 +++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 8bb2ad29fc6..c7096cf1cfb 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -203,12 +203,13 @@ static const NSUInteger kDefaultChannelID = 0; - (nonnull id)mutableCopyWithZone:(NSZone *)zone { GRPCMutableCallOptions *newOptions = [[GRPCMutableCallOptions allocWithZone:zone] - initWithServerAuthority:_serverAuthority + initWithServerAuthority:[_serverAuthority copy] timeout:_timeout - oauth2AccessToken:_oauth2AccessToken + oauth2AccessToken:[_oauth2AccessToken copy] authTokenProvider:_authTokenProvider - initialMetadata:_initialMetadata - userAgentPrefix:_userAgentPrefix + initialMetadata:[[NSDictionary alloc] initWithDictionary:_initialMetadata + copyItems:YES] + userAgentPrefix:[_userAgentPrefix copy] responseSizeLimit:_responseSizeLimit compressionAlgorithm:_compressionAlgorithm retryEnabled:_retryEnabled @@ -217,14 +218,15 @@ static const NSUInteger kDefaultChannelID = 0; connectMinTimeout:_connectMinTimeout connectInitialBackoff:_connectInitialBackoff connectMaxBackoff:_connectMaxBackoff - additionalChannelArgs:[_additionalChannelArgs copy] - PEMRootCertificates:_PEMRootCertificates - PEMPrivateKey:_PEMPrivateKey - PEMCertChain:_PEMCertChain + additionalChannelArgs:[[NSDictionary alloc] initWithDictionary:_additionalChannelArgs + copyItems:YES] + PEMRootCertificates:[_PEMRootCertificates copy] + PEMPrivateKey:[_PEMPrivateKey copy] + PEMCertChain:[_PEMCertChain copy] transportType:_transportType - hostNameOverride:_hostNameOverride + hostNameOverride:[_hostNameOverride copy] logContext:_logContext - channelPoolDomain:_channelPoolDomain + channelPoolDomain:[_channelPoolDomain copy] channelID:_channelID]; return newOptions; } From ce53ba74746248ef914986bc5fe8a2f89f42ceda Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 1 Nov 2018 09:27:40 -0700 Subject: [PATCH 139/375] kChannelDestroyDelay->_destroyDelay in GRPCChannelRef --- src/objective-c/GRPCClient/private/GRPCChannel.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 777cbab8092..67a3ac12749 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -109,7 +109,7 @@ static GRPCChannelPool *gChannelPool; if (self->_refCount == 0) { self->_lastDispatch = [NSDate date]; dispatch_time_t delay = - dispatch_time(DISPATCH_TIME_NOW, (int64_t)kChannelDestroyDelay * 1e9); + dispatch_time(DISPATCH_TIME_NOW, (int64_t)_destroyDelay * 1e9); dispatch_after(delay, self->_timerQueue, ^{ [self timerFire]; }); @@ -132,7 +132,7 @@ static GRPCChannelPool *gChannelPool; - (void)timerFire { dispatch_async(_dispatchQueue, ^{ if (self->_disconnected || self->_lastDispatch == nil || - -[self->_lastDispatch timeIntervalSinceNow] < -kChannelDestroyDelay) { + -[self->_lastDispatch timeIntervalSinceNow] < -_destroyDelay) { return; } self->_lastDispatch = nil; From dc4fc1ce38f9060c10ae639173d106c5a7d2bece Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 1 Nov 2018 09:29:15 -0700 Subject: [PATCH 140/375] Use NSEC_PER_SEC --- src/objective-c/GRPCClient/private/GRPCChannel.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 67a3ac12749..377900fd9e1 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -109,7 +109,7 @@ static GRPCChannelPool *gChannelPool; if (self->_refCount == 0) { self->_lastDispatch = [NSDate date]; dispatch_time_t delay = - dispatch_time(DISPATCH_TIME_NOW, (int64_t)_destroyDelay * 1e9); + dispatch_time(DISPATCH_TIME_NOW, (int64_t)self->_destroyDelay * NSEC_PER_SEC); dispatch_after(delay, self->_timerQueue, ^{ [self timerFire]; }); @@ -132,7 +132,7 @@ static GRPCChannelPool *gChannelPool; - (void)timerFire { dispatch_async(_dispatchQueue, ^{ if (self->_disconnected || self->_lastDispatch == nil || - -[self->_lastDispatch timeIntervalSinceNow] < -_destroyDelay) { + -[self->_lastDispatch timeIntervalSinceNow] < -self->_destroyDelay) { return; } self->_lastDispatch = nil; From 601475b57105f0aff3e96043e6399b621cfc5b84 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 1 Nov 2018 11:43:09 -0700 Subject: [PATCH 141/375] Easier check if timer is canceled --- src/objective-c/GRPCClient/private/GRPCChannel.m | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 377900fd9e1..1d7fb421e5e 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -66,6 +66,12 @@ static GRPCChannelPool *gChannelPool; BOOL _disconnected; dispatch_queue_t _dispatchQueue; dispatch_queue_t _timerQueue; + + /** + * Date and time when last timer is scheduled. When a timer is fired, if + * _lastDispatch + _destroyDelay < now, it can be determined that another timer is scheduled after + * schedule of the current timer, hence the current one should be discarded. + */ NSDate *_lastDispatch; } @@ -107,11 +113,12 @@ static GRPCChannelPool *gChannelPool; if (!self->_disconnected) { self->_refCount--; if (self->_refCount == 0) { - self->_lastDispatch = [NSDate date]; + NSDate *now = [NSDate date]; + self->_lastDispatch = now; dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)self->_destroyDelay * NSEC_PER_SEC); dispatch_after(delay, self->_timerQueue, ^{ - [self timerFire]; + [self timerFireWithScheduleDate:now]; }); } } @@ -129,10 +136,9 @@ static GRPCChannelPool *gChannelPool; }); } -- (void)timerFire { +- (void)timerFireWithScheduleDate:(NSDate *)scheduleDate { dispatch_async(_dispatchQueue, ^{ - if (self->_disconnected || self->_lastDispatch == nil || - -[self->_lastDispatch timeIntervalSinceNow] < -self->_destroyDelay) { + if (self->_disconnected || self->_lastDispatch != scheduleDate) { return; } self->_lastDispatch = nil; From 29bf3864d1a3d00b2199adb0d56298c3a32178fb Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 1 Nov 2018 12:44:48 -0700 Subject: [PATCH 142/375] Remove object after finish iterating in loop --- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 7aac077e773..56de8a0d6f5 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -147,7 +147,9 @@ extern const char *kCFStreamVarName; } - (BOOL)isEqual:(id)object { - NSAssert([object isKindOfClass:[GRPCChannelConfiguration class]], @"Illegal :isEqual"); + if (![object isKindOfClass:[GRPCChannelConfiguration class]]) { + return NO; + } GRPCChannelConfiguration *obj = (GRPCChannelConfiguration *)object; if (!(obj.host == _host || [obj.host isEqualToString:_host])) return NO; if (!(obj.callOptions == _callOptions || [obj.callOptions hasChannelOptionsEqualTo:_callOptions])) @@ -207,13 +209,16 @@ extern const char *kCFStreamVarName; - (void)removeChannel:(GRPCChannel *)channel { @synchronized(self) { + __block GRPCChannelConfiguration *keyToDelete = nil; [_channelPool enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration *_Nonnull key, GRPCChannel *_Nonnull obj, BOOL *_Nonnull stop) { if (obj == channel) { - [self->_channelPool removeObjectForKey:key]; + keyToDelete = key; + *stop = YES; } }]; + [self->_channelPool removeObjectForKey:keyToDelete]; } } From 395fc1226f1225b267f912f4a860ad52ef6f4e0a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 1 Nov 2018 12:54:38 -0700 Subject: [PATCH 143/375] Cleaner code using nil messaging --- src/objective-c/GRPCClient/private/GRPCHost.m | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 480e4621845..8a59bd43d74 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -143,9 +143,7 @@ static NSMutableDictionary *gHostCache; GRPCCallOptions *callOptions = nil; @synchronized(gHostCache) { - if ([gHostCache objectForKey:host]) { - callOptions = [gHostCache[host] callOptions]; - } + callOptions = [gHostCache[host] callOptions]; } if (callOptions == nil) { callOptions = [[GRPCCallOptions alloc] init]; From c827fbc1d044f31a1f925e52e07c843f88094a74 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 1 Nov 2018 13:06:31 -0700 Subject: [PATCH 144/375] Log failures when unable to create call or channel --- src/objective-c/GRPCClient/private/GRPCWrappedCall.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 100d4cf2914..577002e7a85 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -257,8 +257,13 @@ // queue. Currently we use a singleton queue. _queue = [GRPCCompletionQueue completionQueue]; _channel = [GRPCChannel channelWithHost:host callOptions:callOptions]; + if (_channel == nil) { + NSLog(@"Failed to get a channel for the host."); + return nil; + } _call = [_channel unmanagedCallWithPath:path completionQueue:_queue callOptions:callOptions]; if (_call == NULL) { + NSLog(@"Failed to create a call."); return nil; } } From bc0ce06951b091e81e8bc1c71dc660dc3168e75f Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 1 Nov 2018 15:05:58 -0700 Subject: [PATCH 145/375] use _dispatchQueue for timer --- src/objective-c/GRPCClient/private/GRPCChannel.m | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 1d7fb421e5e..0ca2a359926 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -65,7 +65,6 @@ static GRPCChannelPool *gChannelPool; NSUInteger _refCount; BOOL _disconnected; dispatch_queue_t _dispatchQueue; - dispatch_queue_t _timerQueue; /** * Date and time when last timer is scheduled. When a timer is fired, if @@ -87,12 +86,8 @@ static GRPCChannelPool *gChannelPool; _dispatchQueue = dispatch_queue_create( NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); - _timerQueue = - dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class( - DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_DEFAULT, -1)); } else { _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); - _timerQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_CONCURRENT); } _lastDispatch = nil; } @@ -117,7 +112,7 @@ static GRPCChannelPool *gChannelPool; self->_lastDispatch = now; dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)self->_destroyDelay * NSEC_PER_SEC); - dispatch_after(delay, self->_timerQueue, ^{ + dispatch_after(delay, self->_dispatchQueue, ^{ [self timerFireWithScheduleDate:now]; }); } From 17a67fdb0fb01fe34c75d2c6bf34e24214222a89 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 2 Nov 2018 14:48:56 -0700 Subject: [PATCH 146/375] Aggregate v2 api tests --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- src/objective-c/GRPCClient/GRPCCallOptions.h | 2 +- src/objective-c/tests/APIv2Tests/APIv2Tests.m | 482 ++++++++++++++++++ src/objective-c/tests/APIv2Tests/Info.plist | 22 + src/objective-c/tests/GRPCClientTests.m | 291 ----------- src/objective-c/tests/Podfile | 1 + .../tests/Tests.xcodeproj/project.pbxproj | 263 ++++++++++ .../xcschemes/APIv2Tests.xcscheme | 90 ++++ src/objective-c/tests/run_tests.sh | 10 + 9 files changed, 870 insertions(+), 293 deletions(-) create mode 100644 src/objective-c/tests/APIv2Tests/APIv2Tests.m create mode 100644 src/objective-c/tests/APIv2Tests/Info.plist create mode 100644 src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/APIv2Tests.xcscheme diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 8e7d5a5f94b..2abc0fe8f3b 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -780,7 +780,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; @synchronized(self) { self.isWaitingForToken = YES; } - [self.tokenProvider getTokenWithHandler:^(NSString *token) { + [_callOptions.authTokenProvider getTokenWithHandler:^(NSString *token) { @synchronized(self) { if (self.isWaitingForToken) { if (token) { diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 9683bd3c638..77fde371bc0 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -64,7 +64,7 @@ typedef NS_ENUM(NSInteger, GRPCTransportType) { * This method is called when gRPC is about to start the call. When OAuth token is acquired, * \a handler is expected to be called with \a token being the new token to be used for this call. */ -- (void)getTokenWithHandler:(void (^)(NSString *token))hander; +- (void)getTokenWithHandler:(void (^)(NSString *token))handler; @end @interface GRPCCallOptions : NSObject diff --git a/src/objective-c/tests/APIv2Tests/APIv2Tests.m b/src/objective-c/tests/APIv2Tests/APIv2Tests.m new file mode 100644 index 00000000000..7fc353391f3 --- /dev/null +++ b/src/objective-c/tests/APIv2Tests/APIv2Tests.m @@ -0,0 +1,482 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import +#import +#import +#import + +#include + +#import "../version.h" + +// The server address is derived from preprocessor macro, which is +// in turn derived from environment variable of the same name. +#define NSStringize_helper(x) #x +#define NSStringize(x) @NSStringize_helper(x) +static NSString *const kHostAddress = NSStringize(HOST_PORT_LOCAL); +static NSString *const kRemoteSSLHost = NSStringize(HOST_PORT_REMOTE); + +// Package and service name of test server +static NSString *const kPackage = @"grpc.testing"; +static NSString *const kService = @"TestService"; + +static GRPCProtoMethod *kInexistentMethod; +static GRPCProtoMethod *kEmptyCallMethod; +static GRPCProtoMethod *kUnaryCallMethod; +static GRPCProtoMethod *kFullDuplexCallMethod; + +static const int kSimpleDataLength = 100; + +static const NSTimeInterval kTestTimeout = 16; + +// Reveal the _class ivar for testing access +@interface GRPCCall2 () { + @public + GRPCCall *_call; +} + +@end + +// Convenience class to use blocks as callbacks +@interface ClientTestsBlockCallbacks : NSObject + +- (instancetype)initWithInitialMetadataCallback:(void (^)(NSDictionary *))initialMetadataCallback + messageCallback:(void (^)(id))messageCallback + closeCallback:(void (^)(NSDictionary *, NSError *))closeCallback; + +@end + +@implementation ClientTestsBlockCallbacks { + void (^_initialMetadataCallback)(NSDictionary *); + void (^_messageCallback)(id); + void (^_closeCallback)(NSDictionary *, NSError *); + dispatch_queue_t _dispatchQueue; +} + +- (instancetype)initWithInitialMetadataCallback:(void (^)(NSDictionary *))initialMetadataCallback + messageCallback:(void (^)(id))messageCallback + closeCallback:(void (^)(NSDictionary *, NSError *))closeCallback { + if ((self = [super init])) { + _initialMetadataCallback = initialMetadataCallback; + _messageCallback = messageCallback; + _closeCallback = closeCallback; + _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); + } + return self; +} + +- (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { + dispatch_async(_dispatchQueue, ^{ + if (self->_initialMetadataCallback) { + self->_initialMetadataCallback(initialMetadata); + } + }); +} + +- (void)receivedRawMessage:(GPBMessage *_Nullable)message { + dispatch_async(_dispatchQueue, ^{ + if (self->_messageCallback) { + self->_messageCallback(message); + } + }); +} + +- (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata + error:(NSError *_Nullable)error { + dispatch_async(_dispatchQueue, ^{ + if (self->_closeCallback) { + self->_closeCallback(trailingMetadata, error); + } + }); +} + +- (dispatch_queue_t)dispatchQueue { + return _dispatchQueue; +} + +@end + +@interface CallAPIv2Tests : XCTestCase + +@end + +@implementation CallAPIv2Tests + +- (void)setUp { + // This method isn't implemented by the remote server. + kInexistentMethod = + [[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"Inexistent"]; + kEmptyCallMethod = + [[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"EmptyCall"]; + kUnaryCallMethod = + [[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"UnaryCall"]; + kFullDuplexCallMethod = + [[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"FullDuplexCall"]; +} + +- (void)testMetadata { + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"RPC unauthorized."]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + request.fillUsername = YES; + request.fillOauthScope = YES; + + GRPCRequestOptions *callRequest = + [[GRPCRequestOptions alloc] initWithHost:(NSString *)kRemoteSSLHost + path:kUnaryCallMethod.HTTPPath + safety:GRPCCallSafetyDefault]; + __block NSDictionary *init_md; + __block NSDictionary *trailing_md; + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.oauth2AccessToken = @"bogusToken"; + GRPCCall2 *call = [[GRPCCall2 alloc] + initWithRequestOptions:callRequest + responseHandler:[[ClientTestsBlockCallbacks alloc] + initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { + init_md = initialMetadata; + } + messageCallback:^(id message) { + XCTFail(@"Received unexpected response."); + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + trailing_md = trailingMetadata; + if (error) { + XCTAssertEqual(error.code, 16, + @"Finished with unexpected error: %@", error); + XCTAssertEqualObjects(init_md, + error.userInfo[kGRPCHeadersKey]); + XCTAssertEqualObjects(trailing_md, + error.userInfo[kGRPCTrailersKey]); + NSString *challengeHeader = init_md[@"www-authenticate"]; + XCTAssertGreaterThan(challengeHeader.length, 0, + @"No challenge in response headers %@", + init_md); + [expectation fulfill]; + } + }] + callOptions:options]; + + [call start]; + [call writeData:[request data]]; + [call finish]; + + [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; +} + +- (void)testUserAgentPrefix { + __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."]; + __weak XCTestExpectation *recvInitialMd = + [self expectationWithDescription:@"Did not receive initial md."]; + + GRPCRequestOptions *request = [[GRPCRequestOptions alloc] initWithHost:kHostAddress + path:kEmptyCallMethod.HTTPPath + safety:GRPCCallSafetyDefault]; + NSDictionary *headers = + [NSDictionary dictionaryWithObjectsAndKeys:@"", @"x-grpc-test-echo-useragent", nil]; + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.transportType = GRPCTransportTypeInsecure; + options.userAgentPrefix = @"Foo"; + options.initialMetadata = headers; + GRPCCall2 *call = [[GRPCCall2 alloc] + initWithRequestOptions:request + responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:^( + NSDictionary *initialMetadata) { + NSString *userAgent = initialMetadata[@"x-grpc-test-echo-useragent"]; + // Test the regex is correct + NSString *expectedUserAgent = @"Foo grpc-objc/"; + expectedUserAgent = + [expectedUserAgent stringByAppendingString:GRPC_OBJC_VERSION_STRING]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@" grpc-c/"]; + expectedUserAgent = + [expectedUserAgent stringByAppendingString:GRPC_C_VERSION_STRING]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@" (ios; chttp2; "]; + expectedUserAgent = [expectedUserAgent + stringByAppendingString:[NSString stringWithUTF8String:grpc_g_stands_for()]]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@")"]; + XCTAssertEqualObjects(userAgent, expectedUserAgent); + + NSError *error = nil; + // Change in format of user-agent field in a direction that does not match + // the regex will likely cause problem for certain gRPC users. For details, + // refer to internal doc https://goo.gl/c2diBc + NSRegularExpression *regex = [NSRegularExpression + regularExpressionWithPattern: + @" grpc-[a-zA-Z0-9]+(-[a-zA-Z0-9]+)?/[^ ,]+( \\([^)]*\\))?" + options:0 + error:&error]; + + NSString *customUserAgent = + [regex stringByReplacingMatchesInString:userAgent + options:0 + range:NSMakeRange(0, [userAgent length]) + withTemplate:@""]; + XCTAssertEqualObjects(customUserAgent, @"Foo"); + [recvInitialMd fulfill]; + } + messageCallback:^(id message) { + XCTAssertNotNil(message); + XCTAssertEqual([message length], 0, + @"Non-empty response received: %@", message); + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + if (error) { + XCTFail(@"Finished with unexpected error: %@", error); + } else { + [completion fulfill]; + } + }] + callOptions:options]; + [call writeData:[NSData data]]; + [call start]; + + [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; +} + +- (void)getTokenWithHandler:(void (^)(NSString *token))handler { + dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + dispatch_sync(queue, ^{ + handler(@"test-access-token"); + }); +} + +- (void)testOAuthToken { + __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; + + GRPCRequestOptions *requestOptions = + [[GRPCRequestOptions alloc] initWithHost:kHostAddress + path:kEmptyCallMethod.HTTPPath + safety:GRPCCallSafetyDefault]; + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.transportType = GRPCTransportTypeInsecure; + options.authTokenProvider = self; + __block GRPCCall2 *call = [[GRPCCall2 alloc] + initWithRequestOptions:requestOptions + responseHandler:[[ClientTestsBlockCallbacks alloc] + initWithInitialMetadataCallback:nil + messageCallback:nil + closeCallback:^(NSDictionary *trailingMetadata, + NSError *error) { + [completion fulfill]; + }] + callOptions:options]; + [call writeData:[NSData data]]; + [call start]; + + [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; +} + +- (void)testResponseSizeLimitExceeded { + __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; + + GRPCRequestOptions *requestOptions = + [[GRPCRequestOptions alloc] initWithHost:kHostAddress + path:kUnaryCallMethod.HTTPPath + safety:GRPCCallSafetyDefault]; + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.responseSizeLimit = kSimpleDataLength; + options.transportType = GRPCTransportTypeInsecure; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + request.payload.body = [NSMutableData dataWithLength:options.responseSizeLimit]; + request.responseSize = (int32_t)(options.responseSizeLimit * 2); + + GRPCCall2 *call = [[GRPCCall2 alloc] + initWithRequestOptions:requestOptions + responseHandler:[[ClientTestsBlockCallbacks alloc] + initWithInitialMetadataCallback:nil + messageCallback:nil + closeCallback:^(NSDictionary *trailingMetadata, + NSError *error) { + XCTAssertNotNil(error, + @"Expecting non-nil error"); + XCTAssertEqual(error.code, + GRPCErrorCodeResourceExhausted); + [completion fulfill]; + }] + callOptions:options]; + [call writeData:[request data]]; + [call start]; + + [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; +} + +- (void)testIdempotentProtoRPC { + __weak XCTestExpectation *response = [self expectationWithDescription:@"Expected response."]; + __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + request.responseSize = kSimpleDataLength; + request.fillUsername = YES; + request.fillOauthScope = YES; + GRPCRequestOptions *requestOptions = + [[GRPCRequestOptions alloc] initWithHost:kHostAddress + path:kUnaryCallMethod.HTTPPath + safety:GRPCCallSafetyIdempotentRequest]; + + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.transportType = GRPCTransportTypeInsecure; + GRPCCall2 *call = [[GRPCCall2 alloc] + initWithRequestOptions:requestOptions + responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + messageCallback:^(id message) { + NSData *data = (NSData *)message; + XCTAssertNotNil(data, @"nil value received as response."); + XCTAssertGreaterThan(data.length, 0, + @"Empty response received."); + RMTSimpleResponse *responseProto = + [RMTSimpleResponse parseFromData:data error:NULL]; + // We expect empty strings, not nil: + XCTAssertNotNil(responseProto.username, + @"Response's username is nil."); + XCTAssertNotNil(responseProto.oauthScope, + @"Response's OAuth scope is nil."); + [response fulfill]; + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + XCTAssertNil(error, @"Finished with unexpected error: %@", + error); + [completion fulfill]; + }] + callOptions:options]; + + [call start]; + [call writeData:[request data]]; + [call finish]; + + [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; +} + +- (void)testTimeout { + __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; + + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.timeout = 0.001; + GRPCRequestOptions *requestOptions = + [[GRPCRequestOptions alloc] initWithHost:kHostAddress + path:kFullDuplexCallMethod.HTTPPath + safety:GRPCCallSafetyDefault]; + + GRPCCall2 *call = [[GRPCCall2 alloc] + initWithRequestOptions:requestOptions + responseHandler: + [[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + messageCallback:^(NSData *data) { + XCTFail(@"Failure: response received; Expect: no response received."); + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + XCTAssertNotNil(error, + @"Failure: no error received; Expect: receive " + @"deadline exceeded."); + XCTAssertEqual(error.code, GRPCErrorCodeDeadlineExceeded); + [completion fulfill]; + }] + callOptions:options]; + + [call start]; + + [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; +} + +- (void)testTimeoutBackoffWithTimeout:(double)timeout Backoff:(double)backoff { + const double maxConnectTime = timeout > backoff ? timeout : backoff; + const double kMargin = 0.1; + + __weak XCTestExpectation *completion = [self expectationWithDescription:@"Timeout in a second."]; + NSString *const kDummyAddress = [NSString stringWithFormat:@"127.0.0.1:10000"]; + GRPCRequestOptions *requestOptions = + [[GRPCRequestOptions alloc] initWithHost:kDummyAddress + path:@"/dummy/path" + safety:GRPCCallSafetyDefault]; + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.connectMinTimeout = timeout; + options.connectInitialBackoff = backoff; + options.connectMaxBackoff = 0; + + NSDate *startTime = [NSDate date]; + GRPCCall2 *call = [[GRPCCall2 alloc] + initWithRequestOptions:requestOptions + responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + messageCallback:^(NSData *data) { + XCTFail(@"Received message. Should not reach here."); + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + XCTAssertNotNil(error, + @"Finished with no error; expecting error"); + XCTAssertLessThan( + [[NSDate date] timeIntervalSinceDate:startTime], + maxConnectTime + kMargin); + [completion fulfill]; + }] + callOptions:options]; + + [call start]; + + [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; +} + +- (void)testTimeoutBackoff1 { + [self testTimeoutBackoffWithTimeout:0.7 Backoff:0.4]; +} + +- (void)testTimeoutBackoff2 { + [self testTimeoutBackoffWithTimeout:0.3 Backoff:0.8]; +} + +- (void)testCompression { + __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + request.expectCompressed = [RMTBoolValue message]; + request.expectCompressed.value = YES; + request.responseCompressed = [RMTBoolValue message]; + request.expectCompressed.value = YES; + request.responseSize = kSimpleDataLength; + request.payload.body = [NSMutableData dataWithLength:kSimpleDataLength]; + GRPCRequestOptions *requestOptions = + [[GRPCRequestOptions alloc] initWithHost:kHostAddress + path:kUnaryCallMethod.HTTPPath + safety:GRPCCallSafetyDefault]; + + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.transportType = GRPCTransportTypeInsecure; + options.compressionAlgorithm = GRPCCompressGzip; + GRPCCall2 *call = [[GRPCCall2 alloc] + initWithRequestOptions:requestOptions + responseHandler: [[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + messageCallback:^(NSData *data) { + NSError *error; + RMTSimpleResponse *response = [RMTSimpleResponse parseFromData:data error:&error]; + XCTAssertNil(error, @"Error when parsing response: %@", error); + XCTAssertEqual(response.payload.body.length, kSimpleDataLength); + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + XCTAssertNil(error, @"Received failure: %@", error); + [completion fulfill]; + }] + + callOptions:options]; + + [call start]; + [call writeData:[request data]]; + [call finish]; + + [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; +} + +@end diff --git a/src/objective-c/tests/APIv2Tests/Info.plist b/src/objective-c/tests/APIv2Tests/Info.plist new file mode 100644 index 00000000000..6c40a6cd0c4 --- /dev/null +++ b/src/objective-c/tests/APIv2Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index bbe81502dcf..727dc59ca11 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -86,65 +86,6 @@ static GRPCProtoMethod *kFullDuplexCallMethod; @end -// Convenience class to use blocks as callbacks -@interface ClientTestsBlockCallbacks : NSObject - -- (instancetype)initWithInitialMetadataCallback:(void (^)(NSDictionary *))initialMetadataCallback - messageCallback:(void (^)(id))messageCallback - closeCallback:(void (^)(NSDictionary *, NSError *))closeCallback; - -@end - -@implementation ClientTestsBlockCallbacks { - void (^_initialMetadataCallback)(NSDictionary *); - void (^_messageCallback)(id); - void (^_closeCallback)(NSDictionary *, NSError *); - dispatch_queue_t _dispatchQueue; -} - -- (instancetype)initWithInitialMetadataCallback:(void (^)(NSDictionary *))initialMetadataCallback - messageCallback:(void (^)(id))messageCallback - closeCallback:(void (^)(NSDictionary *, NSError *))closeCallback { - if ((self = [super init])) { - _initialMetadataCallback = initialMetadataCallback; - _messageCallback = messageCallback; - _closeCallback = closeCallback; - _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); - } - return self; -} - -- (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { - dispatch_async(_dispatchQueue, ^{ - if (_initialMetadataCallback) { - _initialMetadataCallback(initialMetadata); - } - }); -} - -- (void)receivedRawMessage:(GPBMessage *_Nullable)message { - dispatch_async(_dispatchQueue, ^{ - if (_messageCallback) { - _messageCallback(message); - } - }); -} - -- (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata - error:(NSError *_Nullable)error { - dispatch_async(_dispatchQueue, ^{ - if (_closeCallback) { - _closeCallback(trailingMetadata, error); - } - }); -} - -- (dispatch_queue_t)dispatchQueue { - return _dispatchQueue; -} - -@end - #pragma mark Tests /** @@ -296,55 +237,6 @@ static GRPCProtoMethod *kFullDuplexCallMethod; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } -- (void)testMetadataWithV2API { - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"RPC unauthorized."]; - - RMTSimpleRequest *request = [RMTSimpleRequest message]; - request.fillUsername = YES; - request.fillOauthScope = YES; - - GRPCRequestOptions *callRequest = - [[GRPCRequestOptions alloc] initWithHost:(NSString *)kRemoteSSLHost - path:kUnaryCallMethod.HTTPPath - safety:GRPCCallSafetyDefault]; - __block NSDictionary *init_md; - __block NSDictionary *trailing_md; - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.oauth2AccessToken = @"bogusToken"; - GRPCCall2 *call = [[GRPCCall2 alloc] - initWithRequestOptions:callRequest - responseHandler:[[ClientTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:^(NSDictionary *initialMetadata) { - init_md = initialMetadata; - } - messageCallback:^(id message) { - XCTFail(@"Received unexpected response."); - } - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - trailing_md = trailingMetadata; - if (error) { - XCTAssertEqual(error.code, 16, - @"Finished with unexpected error: %@", error); - XCTAssertEqualObjects(init_md, - error.userInfo[kGRPCHeadersKey]); - XCTAssertEqualObjects(trailing_md, - error.userInfo[kGRPCTrailersKey]); - NSString *challengeHeader = init_md[@"www-authenticate"]; - XCTAssertGreaterThan(challengeHeader.length, 0, - @"No challenge in response headers %@", - init_md); - [expectation fulfill]; - } - }] - callOptions:options]; - - [call start]; - [call writeData:[request data]]; - [call finish]; - - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - - (void)testResponseMetadataKVO { __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."]; @@ -437,75 +329,6 @@ static GRPCProtoMethod *kFullDuplexCallMethod; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } -- (void)testUserAgentPrefixWithV2API { - __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."]; - __weak XCTestExpectation *recvInitialMd = - [self expectationWithDescription:@"Did not receive initial md."]; - - GRPCRequestOptions *request = [[GRPCRequestOptions alloc] initWithHost:kHostAddress - path:kEmptyCallMethod.HTTPPath - safety:GRPCCallSafetyDefault]; - NSDictionary *headers = - [NSDictionary dictionaryWithObjectsAndKeys:@"", @"x-grpc-test-echo-useragent", nil]; - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.transportType = GRPCTransportTypeInsecure; - options.userAgentPrefix = @"Foo"; - options.initialMetadata = headers; - GRPCCall2 *call = [[GRPCCall2 alloc] - initWithRequestOptions:request - responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:^( - NSDictionary *initialMetadata) { - NSString *userAgent = initialMetadata[@"x-grpc-test-echo-useragent"]; - // Test the regex is correct - NSString *expectedUserAgent = @"Foo grpc-objc/"; - expectedUserAgent = - [expectedUserAgent stringByAppendingString:GRPC_OBJC_VERSION_STRING]; - expectedUserAgent = [expectedUserAgent stringByAppendingString:@" grpc-c/"]; - expectedUserAgent = - [expectedUserAgent stringByAppendingString:GRPC_C_VERSION_STRING]; - expectedUserAgent = [expectedUserAgent stringByAppendingString:@" (ios; chttp2; "]; - expectedUserAgent = [expectedUserAgent - stringByAppendingString:[NSString stringWithUTF8String:grpc_g_stands_for()]]; - expectedUserAgent = [expectedUserAgent stringByAppendingString:@")"]; - XCTAssertEqualObjects(userAgent, expectedUserAgent); - - NSError *error = nil; - // Change in format of user-agent field in a direction that does not match - // the regex will likely cause problem for certain gRPC users. For details, - // refer to internal doc https://goo.gl/c2diBc - NSRegularExpression *regex = [NSRegularExpression - regularExpressionWithPattern: - @" grpc-[a-zA-Z0-9]+(-[a-zA-Z0-9]+)?/[^ ,]+( \\([^)]*\\))?" - options:0 - error:&error]; - - NSString *customUserAgent = - [regex stringByReplacingMatchesInString:userAgent - options:0 - range:NSMakeRange(0, [userAgent length]) - withTemplate:@""]; - XCTAssertEqualObjects(customUserAgent, @"Foo"); - [recvInitialMd fulfill]; - } - messageCallback:^(id message) { - XCTAssertNotNil(message); - XCTAssertEqual([message length], 0, - @"Non-empty response received: %@", message); - } - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - if (error) { - XCTFail(@"Finished with unexpected error: %@", error); - } else { - [completion fulfill]; - } - }] - callOptions:options]; - [call writeData:[NSData data]]; - [call start]; - - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - - (void)testTrailers { __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."]; @@ -597,52 +420,6 @@ static GRPCProtoMethod *kFullDuplexCallMethod; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } -- (void)testIdempotentProtoRPCWithV2API { - __weak XCTestExpectation *response = [self expectationWithDescription:@"Expected response."]; - __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; - - RMTSimpleRequest *request = [RMTSimpleRequest message]; - request.responseSize = 100; - request.fillUsername = YES; - request.fillOauthScope = YES; - GRPCRequestOptions *requestOptions = - [[GRPCRequestOptions alloc] initWithHost:kHostAddress - path:kUnaryCallMethod.HTTPPath - safety:GRPCCallSafetyIdempotentRequest]; - - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.transportType = GRPCTransportTypeInsecure; - GRPCCall2 *call = [[GRPCCall2 alloc] - initWithRequestOptions:requestOptions - responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil - messageCallback:^(id message) { - NSData *data = (NSData *)message; - XCTAssertNotNil(data, @"nil value received as response."); - XCTAssertGreaterThan(data.length, 0, - @"Empty response received."); - RMTSimpleResponse *responseProto = - [RMTSimpleResponse parseFromData:data error:NULL]; - // We expect empty strings, not nil: - XCTAssertNotNil(responseProto.username, - @"Response's username is nil."); - XCTAssertNotNil(responseProto.oauthScope, - @"Response's OAuth scope is nil."); - [response fulfill]; - } - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - XCTAssertNil(error, @"Finished with unexpected error: %@", - error); - [completion fulfill]; - }] - callOptions:options]; - - [call start]; - [call writeData:[request data]]; - [call finish]; - - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - - (void)testAlternateDispatchQueue { const int32_t kPayloadSize = 100; RMTSimpleRequest *request = [RMTSimpleRequest message]; @@ -732,37 +509,6 @@ static GRPCProtoMethod *kFullDuplexCallMethod; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } -- (void)testTimeoutWithV2API { - __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; - - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.timeout = 0.001; - GRPCRequestOptions *requestOptions = - [[GRPCRequestOptions alloc] initWithHost:kHostAddress - path:kFullDuplexCallMethod.HTTPPath - safety:GRPCCallSafetyDefault]; - - GRPCCall2 *call = [[GRPCCall2 alloc] - initWithRequestOptions:requestOptions - responseHandler: - [[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil - messageCallback:^(id data) { - XCTFail(@"Failure: response received; Expect: no response received."); - } - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - XCTAssertNotNil(error, - @"Failure: no error received; Expect: receive " - @"deadline exceeded."); - XCTAssertEqual(error.code, GRPCErrorCodeDeadlineExceeded); - [completion fulfill]; - }] - callOptions:options]; - - [call start]; - - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - - (int)findFreePort { struct sockaddr_in addr; unsigned int addr_len = sizeof(addr); @@ -834,43 +580,6 @@ static GRPCProtoMethod *kFullDuplexCallMethod; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } -- (void)testTimeoutBackoffWithOptionsWithTimeout:(double)timeout Backoff:(double)backoff { - const double maxConnectTime = timeout > backoff ? timeout : backoff; - const double kMargin = 0.1; - - __weak XCTestExpectation *completion = [self expectationWithDescription:@"Timeout in a second."]; - NSString *const kDummyAddress = [NSString stringWithFormat:@"127.0.0.1:10000"]; - GRPCRequestOptions *requestOptions = - [[GRPCRequestOptions alloc] initWithHost:kDummyAddress - path:@"/dummy/path" - safety:GRPCCallSafetyDefault]; - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.connectMinTimeout = timeout; - options.connectInitialBackoff = backoff; - options.connectMaxBackoff = 0; - - NSDate *startTime = [NSDate date]; - GRPCCall2 *call = [[GRPCCall2 alloc] - initWithRequestOptions:requestOptions - responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil - messageCallback:^(id data) { - XCTFail(@"Received message. Should not reach here."); - } - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - XCTAssertNotNil(error, - @"Finished with no error; expecting error"); - XCTAssertLessThan( - [[NSDate date] timeIntervalSinceDate:startTime], - maxConnectTime + kMargin); - [completion fulfill]; - }] - callOptions:options]; - - [call start]; - - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; -} - // The numbers of the following three tests are selected to be smaller than the default values of // initial backoff (1s) and min_connect_timeout (20s), so that if they fail we know the default // values fail to be overridden by the channel args. diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile index e87aba235ad..5df9d4e85bd 100644 --- a/src/objective-c/tests/Podfile +++ b/src/objective-c/tests/Podfile @@ -17,6 +17,7 @@ GRPC_LOCAL_SRC = '../../..' InteropTestsMultipleChannels InteropTestsCallOptions UnitTests + APIv2Tests ).each do |target_name| target target_name do pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj index 104fd0a4ea0..6d1932b0215 100644 --- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj +++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 333E8FC01C8285B7C547D799 /* libPods-InteropTestsLocalCleartext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD346DB2C23F676C4842F3FF /* libPods-InteropTestsLocalCleartext.a */; }; 5E0282E9215AA697007AC99D /* UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E0282E8215AA697007AC99D /* UnitTests.m */; }; 5E0282EB215AA697007AC99D /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; + 5E10F5AA218CB0D2008BAB68 /* APIv2Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E10F5A9218CB0D2008BAB68 /* APIv2Tests.m */; }; 5E7D71AD210954A8001EA6BA /* TestCertificates.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */; }; 5E7D71B5210B9EC9001EA6BA /* InteropTestsCallOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E7D71B4210B9EC9001EA6BA /* InteropTestsCallOptions.m */; }; 5E7D71B7210B9EC9001EA6BA /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; @@ -68,6 +69,7 @@ BC111C80CBF7068B62869352 /* libPods-InteropTestsRemoteCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F44AC3F44E3491A8C0D890FE /* libPods-InteropTestsRemoteCFStream.a */; }; C3D6F4270A2FFF634D8849ED /* libPods-InteropTestsLocalCleartextCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BDA4BA011779D5D25B5618C /* libPods-InteropTestsLocalCleartextCFStream.a */; }; CCF5C0719EF608276AE16374 /* libPods-UnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */; }; + E7F4C80FC8FC667B7447BFE7 /* libPods-APIv2Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6AD69CACF67505B0F028E92 /* libPods-APIv2Tests.a */; }; F15EF7852DC70770EFDB1D2C /* libPods-AllTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAE086D5B470DA367D415AB0 /* libPods-AllTests.a */; }; /* End PBXBuildFile section */ @@ -176,7 +178,9 @@ 0A4F89D9C90E9C30990218F0 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 0BDA4BA011779D5D25B5618C /* libPods-InteropTestsLocalCleartextCFStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalCleartextCFStream.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 0D2284C3DF7E57F0ED504E39 /* Pods-CoreCronetEnd2EndTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.debug.xcconfig"; sourceTree = ""; }; + 1286B30AD74CB64CD91FB17D /* Pods-APIv2Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APIv2Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests.debug.xcconfig"; sourceTree = ""; }; 1295CCBD1082B4A7CFCED95F /* Pods-InteropTestsMultipleChannels.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsMultipleChannels.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsMultipleChannels/Pods-InteropTestsMultipleChannels.cronet.xcconfig"; sourceTree = ""; }; + 12B238CD1702393C2BA5DE80 /* Pods-APIv2Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APIv2Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests.release.xcconfig"; sourceTree = ""; }; 14B09A58FEE53A7A6B838920 /* Pods-InteropTestsLocalSSL.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.cronet.xcconfig"; sourceTree = ""; }; 1588C85DEAF7FC0ACDEA4C02 /* Pods-InteropTestsLocalCleartext.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.test.xcconfig"; sourceTree = ""; }; 17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; sourceTree = ""; }; @@ -200,6 +204,7 @@ 4AD97096D13D7416DC91A72A /* Pods-CoreCronetEnd2EndTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.release.xcconfig"; sourceTree = ""; }; 4ADEA1C8BBE10D90940AC68E /* Pods-InteropTestsRemote.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.cronet.xcconfig"; sourceTree = ""; }; 51A275E86C141416ED63FF76 /* Pods-InteropTestsLocalCleartext.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.release.xcconfig"; sourceTree = ""; }; + 51F2A64B7AADBA1B225B132E /* Pods-APIv2Tests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APIv2Tests.test.xcconfig"; path = "Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests.test.xcconfig"; sourceTree = ""; }; 553BBBED24E4162D1F769D65 /* Pods-InteropTestsLocalSSL.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.debug.xcconfig"; sourceTree = ""; }; 55B630C1FF8C36D1EFC4E0A4 /* Pods-InteropTestsLocalSSLCFStream.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSLCFStream.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSLCFStream/Pods-InteropTestsLocalSSLCFStream.cronet.xcconfig"; sourceTree = ""; }; 573450F334B331D0BED8B961 /* Pods-CoreCronetEnd2EndTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.cronet.xcconfig"; sourceTree = ""; }; @@ -207,6 +212,9 @@ 5E0282E6215AA697007AC99D /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5E0282E8215AA697007AC99D /* UnitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UnitTests.m; sourceTree = ""; }; 5E0282EA215AA697007AC99D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5E10F5A7218CB0D1008BAB68 /* APIv2Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = APIv2Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 5E10F5A9218CB0D2008BAB68 /* APIv2Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = APIv2Tests.m; sourceTree = ""; }; + 5E10F5AB218CB0D2008BAB68 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 5E7D71B2210B9EC8001EA6BA /* InteropTestsCallOptions.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsCallOptions.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5E7D71B4210B9EC9001EA6BA /* InteropTestsCallOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InteropTestsCallOptions.m; sourceTree = ""; }; 5E7D71B6210B9EC9001EA6BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -254,6 +262,7 @@ 7A2E97E3F469CC2A758D77DE /* Pods-InteropTestsLocalSSL.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.release.xcconfig"; sourceTree = ""; }; 7BA53C6D224288D5870FE6F3 /* Pods-InteropTestsLocalCleartextCFStream.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.release.xcconfig"; sourceTree = ""; }; 8B498B05C6DA0818B2FA91D4 /* Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig"; sourceTree = ""; }; + 8C233E85C3EB45B3CAE52EDF /* Pods-APIv2Tests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APIv2Tests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests.cronet.xcconfig"; sourceTree = ""; }; 90E63AD3C4A1E3E6BC745096 /* Pods-ChannelTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChannelTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-ChannelTests/Pods-ChannelTests.cronet.xcconfig"; sourceTree = ""; }; 943138072A9605B5B8DC1FC0 /* Pods-InteropTestsLocalCleartextCFStream.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.debug.xcconfig"; sourceTree = ""; }; 94D7A5FAA13480E9A5166D7A /* Pods-UnitTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.test.xcconfig"; sourceTree = ""; }; @@ -266,6 +275,7 @@ AC414EF7A6BF76ED02B6E480 /* Pods-InteropTestsRemoteWithCronet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.release.xcconfig"; sourceTree = ""; }; AF3FC2CFFE7B0961823BC740 /* libPods-InteropTestsCallOptions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsCallOptions.a"; sourceTree = BUILT_PRODUCTS_DIR; }; B226619DC4E709E0FFFF94B8 /* Pods-CronetUnitTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CronetUnitTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-CronetUnitTests/Pods-CronetUnitTests.test.xcconfig"; sourceTree = ""; }; + B6AD69CACF67505B0F028E92 /* libPods-APIv2Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-APIv2Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; B94C27C06733CF98CE1B2757 /* Pods-AllTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.debug.xcconfig"; sourceTree = ""; }; BED74BC8ABF9917C66175879 /* Pods-ChannelTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChannelTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-ChannelTests/Pods-ChannelTests.test.xcconfig"; sourceTree = ""; }; C17F57E5BCB989AB1C2F1F25 /* Pods-InteropTestsRemoteCFStream.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteCFStream.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream.test.xcconfig"; sourceTree = ""; }; @@ -303,6 +313,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5E10F5A4218CB0D1008BAB68 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E7F4C80FC8FC667B7447BFE7 /* libPods-APIv2Tests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5E7D71AF210B9EC8001EA6BA /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -456,6 +474,7 @@ 355D0E30AD224763BC9519F4 /* libPods-InteropTestsMultipleChannels.a */, AF3FC2CFFE7B0961823BC740 /* libPods-InteropTestsCallOptions.a */, 22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */, + B6AD69CACF67505B0F028E92 /* libPods-APIv2Tests.a */, ); name = Frameworks; sourceTree = ""; @@ -525,6 +544,10 @@ 94D7A5FAA13480E9A5166D7A /* Pods-UnitTests.test.xcconfig */, E1E7660656D902104F728892 /* Pods-UnitTests.cronet.xcconfig */, EBFFEC04B514CB0D4922DC40 /* Pods-UnitTests.release.xcconfig */, + 1286B30AD74CB64CD91FB17D /* Pods-APIv2Tests.debug.xcconfig */, + 51F2A64B7AADBA1B225B132E /* Pods-APIv2Tests.test.xcconfig */, + 8C233E85C3EB45B3CAE52EDF /* Pods-APIv2Tests.cronet.xcconfig */, + 12B238CD1702393C2BA5DE80 /* Pods-APIv2Tests.release.xcconfig */, ); name = Pods; sourceTree = ""; @@ -538,6 +561,15 @@ path = UnitTests; sourceTree = ""; }; + 5E10F5A8218CB0D1008BAB68 /* APIv2Tests */ = { + isa = PBXGroup; + children = ( + 5E10F5A9218CB0D2008BAB68 /* APIv2Tests.m */, + 5E10F5AB218CB0D2008BAB68 /* Info.plist */, + ); + path = APIv2Tests; + sourceTree = ""; + }; 5E7D71B3210B9EC9001EA6BA /* InteropTestsCallOptions */ = { isa = PBXGroup; children = ( @@ -604,6 +636,7 @@ 5EB2A2F62109284500EB4B69 /* InteropTestsMultipleChannels */, 5E7D71B3210B9EC9001EA6BA /* InteropTestsCallOptions */, 5E0282E7215AA697007AC99D /* UnitTests */, + 5E10F5A8218CB0D1008BAB68 /* APIv2Tests */, 635697C81B14FC11007A7283 /* Products */, 51E4650F34F854F41FF053B3 /* Pods */, 136D535E19727099B941D7B1 /* Frameworks */, @@ -629,6 +662,7 @@ 5EB2A2F52109284500EB4B69 /* InteropTestsMultipleChannels.xctest */, 5E7D71B2210B9EC8001EA6BA /* InteropTestsCallOptions.xctest */, 5E0282E6215AA697007AC99D /* UnitTests.xctest */, + 5E10F5A7218CB0D1008BAB68 /* APIv2Tests.xctest */, ); name = Products; sourceTree = ""; @@ -681,6 +715,25 @@ productReference = 5E0282E6215AA697007AC99D /* UnitTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 5E10F5A6218CB0D1008BAB68 /* APIv2Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5E10F5B0218CB0D2008BAB68 /* Build configuration list for PBXNativeTarget "APIv2Tests" */; + buildPhases = ( + 031ADD72298D6C6979CB06DB /* [CP] Check Pods Manifest.lock */, + 5E10F5A3218CB0D1008BAB68 /* Sources */, + 5E10F5A4218CB0D1008BAB68 /* Frameworks */, + 5E10F5A5218CB0D1008BAB68 /* Resources */, + FBB92A8B11C52512E67791E8 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = APIv2Tests; + productName = APIv2Tests; + productReference = 5E10F5A7218CB0D1008BAB68 /* APIv2Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 5E7D71B1210B9EC8001EA6BA /* InteropTestsCallOptions */ = { isa = PBXNativeTarget; buildConfigurationList = 5E7D71BA210B9EC9001EA6BA /* Build configuration list for PBXNativeTarget "InteropTestsCallOptions" */; @@ -990,6 +1043,10 @@ CreatedOnToolsVersion = 9.2; ProvisioningStyle = Automatic; }; + 5E10F5A6218CB0D1008BAB68 = { + CreatedOnToolsVersion = 10.0; + ProvisioningStyle = Automatic; + }; 5E7D71B1210B9EC8001EA6BA = { CreatedOnToolsVersion = 9.3; ProvisioningStyle = Automatic; @@ -1071,6 +1128,7 @@ 5EB2A2F42109284500EB4B69 /* InteropTestsMultipleChannels */, 5E7D71B1210B9EC8001EA6BA /* InteropTestsCallOptions */, 5E0282E5215AA697007AC99D /* UnitTests */, + 5E10F5A6218CB0D1008BAB68 /* APIv2Tests */, ); }; /* End PBXProject section */ @@ -1083,6 +1141,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5E10F5A5218CB0D1008BAB68 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5E7D71B0210B9EC8001EA6BA /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1206,6 +1271,28 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 031ADD72298D6C6979CB06DB /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-APIv2Tests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 0617B5294978A95BEBBFF733 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1764,6 +1851,28 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + FBB92A8B11C52512E67791E8 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + ); + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -1775,6 +1884,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5E10F5A3218CB0D1008BAB68 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5E10F5AA218CB0D2008BAB68 /* APIv2Tests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5E7D71AE210B9EC8001EA6BA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -2098,6 +2215,141 @@ }; name = Release; }; + 5E10F5AC218CB0D2008BAB68 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1286B30AD74CB64CD91FB17D /* Pods-APIv2Tests.debug.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = APIv2Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 5E10F5AD218CB0D2008BAB68 /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 51F2A64B7AADBA1B225B132E /* Pods-APIv2Tests.test.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = APIv2Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Test; + }; + 5E10F5AE218CB0D2008BAB68 /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8C233E85C3EB45B3CAE52EDF /* Pods-APIv2Tests.cronet.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = APIv2Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Cronet; + }; + 5E10F5AF218CB0D2008BAB68 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 12B238CD1702393C2BA5DE80 /* Pods-APIv2Tests.release.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = APIv2Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; 5E1228981E4D400F00E8504F /* Test */ = { isa = XCBuildConfiguration; buildSettings = { @@ -3648,6 +3900,17 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 5E10F5B0218CB0D2008BAB68 /* Build configuration list for PBXNativeTarget "APIv2Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5E10F5AC218CB0D2008BAB68 /* Debug */, + 5E10F5AD218CB0D2008BAB68 /* Test */, + 5E10F5AE218CB0D2008BAB68 /* Cronet */, + 5E10F5AF218CB0D2008BAB68 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 5E7D71BA210B9EC9001EA6BA /* Build configuration list for PBXNativeTarget "InteropTestsCallOptions" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/APIv2Tests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/APIv2Tests.xcscheme new file mode 100644 index 00000000000..b444ddc2b67 --- /dev/null +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/APIv2Tests.xcscheme @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh index 118220ce4b1..e8c3e6ec2a4 100755 --- a/src/objective-c/tests/run_tests.sh +++ b/src/objective-c/tests/run_tests.sh @@ -183,4 +183,14 @@ xcodebuild \ | egrep -v '^$' \ | egrep -v "(GPBDictionary|GPBArray)" - +echo "TIME: $(date)" +xcodebuild \ + -workspace Tests.xcworkspace \ + -scheme APIv2Tests \ + -destination name="iPhone 8" \ + test \ + | egrep -v "$XCODEBUILD_FILTER" \ + | egrep -v '^$' \ + | egrep -v "(GPBDictionary|GPBArray)" - + exit 0 From 6b8f0ceae8f581cfd63b40c4e2ccab95783081ae Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 10:15:20 -0800 Subject: [PATCH 147/375] A few nits --- src/objective-c/GRPCClient/GRPCCall+OAuth2.h | 2 +- src/objective-c/GRPCClient/GRPCCall.h | 4 ++-- src/objective-c/GRPCClient/GRPCCall.m | 9 +++++++-- src/objective-c/ProtoRPC/ProtoRPC.h | 4 ++-- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall+OAuth2.h b/src/objective-c/GRPCClient/GRPCCall+OAuth2.h index 3054bfc5a7a..60cdc50bfda 100644 --- a/src/objective-c/GRPCClient/GRPCCall+OAuth2.h +++ b/src/objective-c/GRPCClient/GRPCCall+OAuth2.h @@ -24,7 +24,7 @@ @interface GRPCCall (OAuth2) @property(atomic, copy) NSString* oauth2AccessToken; -@property(atomic, readonly) NSString* oauth2ChallengeHeader; +@property(atomic, copy, readonly) NSString* oauth2ChallengeHeader; @property(atomic, strong) id tokenProvider; @end diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index a1f139fc186..4f0660d203e 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -196,7 +196,7 @@ extern NSString *const kGRPCTrailersKey; - (instancetype)init NS_UNAVAILABLE; -+ (instancetype) new NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; /** Initialize with all properties. */ - (instancetype)initWithHost:(NSString *)host @@ -224,7 +224,7 @@ extern NSString *const kGRPCTrailersKey; - (instancetype)init NS_UNAVAILABLE; -+ (instancetype) new NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; /** * Designated initializer for a call. diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 2abc0fe8f3b..2f727e62be1 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -67,6 +67,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; @implementation GRPCRequestOptions - (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety { + NSAssert(host.length != 0 && path.length != 0, @"Host and Path cannot be empty"); if ((self = [super init])) { _host = [host copy]; _path = [path copy]; @@ -90,7 +91,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; /** The handler of responses. */ id _handler; - // Thread safety of ivars below are protected by _dispatcheQueue. + // Thread safety of ivars below are protected by _dispatchQueue. /** * Make use of legacy GRPCCall to make calls. Nullified when call is finished. @@ -121,7 +122,11 @@ const char *kCFStreamVarName = "grpc_cfstream"; if ((self = [super init])) { _requestOptions = [requestOptions copy]; - _callOptions = [callOptions copy]; + if (callOptions == nil) { + _callOptions = [[GRPCCallOptions alloc] init]; + } else { + _callOptions = [callOptions copy]; + } _handler = responseHandler; _initialMetadataPublished = NO; _pipe = [GRXBufferedPipe pipe]; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index b0f4ced99e8..3d137a53ffc 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -66,7 +66,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init NS_UNAVAILABLE; -+ (instancetype) new NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; /** * Users should not use this initializer directly. Call objects will be created, initialized, and @@ -92,7 +92,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init NS_UNAVAILABLE; -+ (instancetype) new NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; /** * Users should not use this initializer directly. Call objects will be created, initialized, and From b496e3a2663824c22806b7ee7b1423c806ecc61a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 11:07:03 -0800 Subject: [PATCH 148/375] On finish, clean _handler and _call independently --- src/objective-c/GRPCClient/GRPCCall.m | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 2f727e62be1..af141935813 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -184,6 +184,11 @@ const char *kCFStreamVarName = "grpc_cfstream"; } completionHandler:^(NSError *errorOrNil) { dispatch_async(self->_dispatchQueue, ^{ + if (self->_call) { + [self->_pipe writesFinishedWithError:nil]; + self->_call = nil; + self->_pipe = nil; + } if (self->_handler) { if (!self->_initialMetadataPublished) { self->_initialMetadataPublished = YES; @@ -193,12 +198,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Clean up _handler so that no more responses are reported to the handler. self->_handler = nil; - - if (self->_call) { - [self->_pipe writesFinishedWithError:nil]; - self->_call = nil; - self->_pipe = nil; - } } }); }]; From 739760cdc8a6625fe93f4f0312d84305052b0d09 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 11:22:51 -0800 Subject: [PATCH 149/375] More comment --- src/objective-c/GRPCClient/GRPCCall.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index af141935813..9be0554ff98 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -185,6 +185,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; completionHandler:^(NSError *errorOrNil) { dispatch_async(self->_dispatchQueue, ^{ if (self->_call) { + // Clean up the request writers. This should have no effect to _call since its + // response writeable is already nullified. [self->_pipe writesFinishedWithError:nil]; self->_call = nil; self->_pipe = nil; From 24265b03ac5c6ace73916f3bc3a847abf1c64c33 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 11:31:48 -0800 Subject: [PATCH 150/375] Clarify cancel before call is started --- src/objective-c/GRPCClient/GRPCCall.h | 1 + src/objective-c/GRPCClient/GRPCCall.m | 1 + 2 files changed, 2 insertions(+) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 4f0660d203e..f713262b643 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -245,6 +245,7 @@ extern NSString *const kGRPCTrailersKey; /** * Starts the call. This function should only be called once; additional calls will be discarded. + * Invokes after calling cancel: are discarded. */ - (void)start; diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 9be0554ff98..5ce361300d6 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -209,6 +209,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)cancel { dispatch_async(_dispatchQueue, ^{ + self->_started = YES; if (self->_call) { [self->_call cancel]; self->_call = nil; From 9558618182aa817ad5aa9885f1fe12003ee1a93e Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 11:37:41 -0800 Subject: [PATCH 151/375] Check if call is cancelled --- src/objective-c/GRPCClient/GRPCCall.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 5ce361300d6..1338c1edd60 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -237,7 +237,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)writeData:(NSData *)data { dispatch_async(_dispatchQueue, ^{ - [self->_pipe writeValue:data]; + if (self->_call) { + [self->_pipe writeValue:data]; + } }); } From b3b98ba4a29f434541355e026765938998c22da4 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 12:09:46 -0800 Subject: [PATCH 152/375] test fix --- src/objective-c/tests/GRPCClientTests.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 727dc59ca11..834bf6d661a 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -585,12 +585,10 @@ static GRPCProtoMethod *kFullDuplexCallMethod; // values fail to be overridden by the channel args. - (void)testTimeoutBackoff1 { [self testTimeoutBackoffWithTimeout:0.7 Backoff:0.3]; - [self testTimeoutBackoffWithOptionsWithTimeout:0.7 Backoff:0.4]; } - (void)testTimeoutBackoff2 { [self testTimeoutBackoffWithTimeout:0.3 Backoff:0.7]; - [self testTimeoutBackoffWithOptionsWithTimeout:0.3 Backoff:0.8]; } - (void)testErrorDebugInformation { From 1be316e5641db3192a3f7b276e3926d8da17c62a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 14:12:14 -0800 Subject: [PATCH 153/375] Remove check in cancel --- src/objective-c/GRPCClient/GRPCCall.h | 5 ++-- src/objective-c/GRPCClient/GRPCCall.m | 42 +++++++++++++++------------ 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index f713262b643..260305a989c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -244,8 +244,7 @@ extern NSString *const kGRPCTrailersKey; responseHandler:(id)responseHandler; /** - * Starts the call. This function should only be called once; additional calls will be discarded. - * Invokes after calling cancel: are discarded. + * Starts the call. This function must only be called once for each instance. */ - (void)start; @@ -263,7 +262,7 @@ extern NSString *const kGRPCTrailersKey; /** * Finish the RPC request and half-close the call. The server may still send messages and/or - * trailers to the client. + * trailers to the client. The method must only be called once and after start is called. */ - (void)finish; diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 1338c1edd60..9f8339eb601 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -105,6 +105,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; dispatch_queue_t _dispatchQueue; /** Flags whether call has started. */ BOOL _started; + /** Flags whether call has been canceled. */ + BOOL _canceled; + /** Flags whether call has been finished. */ } - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions @@ -140,6 +143,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } dispatch_set_target_queue(responseHandler.dispatchQueue, _dispatchQueue); _started = NO; + _canceled = NO; } return self; @@ -153,9 +157,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)start { dispatch_async(_dispatchQueue, ^{ - if (self->_started) { - return; - } + NSAssert(!self->_started, @"Call already started."); + NSAssert(!self->_canceled, @"Call already canceled."); self->_started = YES; if (!self->_callOptions) { self->_callOptions = [[GRPCCallOptions alloc] init]; @@ -184,13 +187,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; } completionHandler:^(NSError *errorOrNil) { dispatch_async(self->_dispatchQueue, ^{ - if (self->_call) { - // Clean up the request writers. This should have no effect to _call since its - // response writeable is already nullified. - [self->_pipe writesFinishedWithError:nil]; - self->_call = nil; - self->_pipe = nil; - } if (self->_handler) { if (!self->_initialMetadataPublished) { self->_initialMetadataPublished = YES; @@ -201,6 +197,15 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Clean up _handler so that no more responses are reported to the handler. self->_handler = nil; } + // Clearing _call must happen *after* dispatching close in order to get trailing + // metadata from _call. + if (self->_call) { + // Clean up the request writers. This should have no effect to _call since its + // response writeable is already nullified. + [self->_pipe writesFinishedWithError:nil]; + self->_call = nil; + self->_pipe = nil; + } }); }]; [self->_call startWithWriteable:responseWriteable]; @@ -209,7 +214,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)cancel { dispatch_async(_dispatchQueue, ^{ - self->_started = YES; + NSAssert(!self->_canceled, @"Call already canceled."); if (self->_call) { [self->_call cancel]; self->_call = nil; @@ -237,6 +242,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)writeData:(NSData *)data { dispatch_async(_dispatchQueue, ^{ + NSAssert(!self->_canceled, @"Call arleady canceled."); + NSAssert(!self->_finished, @"Call is half-closed before sending data."); if (self->_call) { [self->_pipe writeValue:data]; } @@ -245,6 +252,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)finish { dispatch_async(_dispatchQueue, ^{ + NSAssert(self->started, @"Call not started."); + NSAssert(!self->_canceled, @"Call arleady canceled."); + NSAssert(!self->_finished, @"Call already half-closed."); if (self->_call) { [self->_pipe writesFinishedWithError:nil]; } @@ -265,9 +275,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)issueClosedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { - NSDictionary *trailers = _call.responseTrailers; if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - [_handler closedWithTrailingMetadata:trailers error:error]; + [_handler closedWithTrailingMetadata:_call.responseTrailers error:error]; } } @@ -464,11 +473,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)cancel { @synchronized(self) { - if (!self.isWaitingForToken) { - [self cancelCall]; - } else { - self.isWaitingForToken = NO; - } + [self cancelCall]; + self.isWaitingForToken = NO; } [self maybeFinishWithError:[NSError From 515941ae1899ca125e8da77c3031d3f0471488ff Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 16:04:56 -0800 Subject: [PATCH 154/375] copy _requestHeaders in GRPCCall --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 9f8339eb601..c10fe7c1346 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -578,7 +578,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; break; } - NSMutableDictionary *headers = _requestHeaders; + NSMutableDictionary *headers = [_requestHeaders copy]; NSString *fetchedOauth2AccessToken; @synchronized(self) { fetchedOauth2AccessToken = _fetchedOauth2AccessToken; From d635d9f9f98bc374c0b3502bbcc8f707c27d7038 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 16:43:58 -0800 Subject: [PATCH 155/375] fix some threading issues --- src/objective-c/GRPCClient/GRPCCall.m | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index c10fe7c1346..b3bddf08a05 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -468,7 +468,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)cancelCall { // Can be called from any thread, any number of times. - [_wrappedCall cancel]; + @synchronized (self) { + [_wrappedCall cancel]; + } } - (void)cancel { @@ -730,17 +732,21 @@ const char *kCFStreamVarName = "grpc_cfstream"; _responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable dispatchQueue:_responseQueue]; - _wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host path:_path callOptions:_callOptions]; - if (_wrappedCall == nil) { + GRPCWrappedCall *wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host path:_path callOptions:_callOptions]; + if (wrappedCall == nil) { [self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeUnavailable userInfo:@{ - NSLocalizedDescriptionKey : - @"Failed to create call or channel." - }]]; + NSLocalizedDescriptionKey : + @"Failed to create call or channel." + }]]; return; } + @synchronized (self) { + _wrappedCall = wrappedCall; + } + [self sendHeaders]; [self invokeCall]; From d40e828d53cdb983255e0406261fed71710ba361 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 17:08:26 -0800 Subject: [PATCH 156/375] NSInteger->NSUInteger --- src/objective-c/GRPCClient/GRPCCallOptions.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 77fde371bc0..bb8a1d251a9 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -34,7 +34,7 @@ typedef NS_ENUM(NSUInteger, GRPCCallSafety) { }; // Compression algorithm to be used by a gRPC call -typedef NS_ENUM(NSInteger, GRPCCompressionAlgorithm) { +typedef NS_ENUM(NSUInteger, GRPCCompressionAlgorithm) { GRPCCompressNone = 0, GRPCCompressDeflate, GRPCCompressGzip, @@ -45,7 +45,7 @@ typedef NS_ENUM(NSInteger, GRPCCompressionAlgorithm) { typedef GRPCCompressionAlgorithm GRPCCompressAlgorithm; /** The transport to be used by a gRPC call */ -typedef NS_ENUM(NSInteger, GRPCTransportType) { +typedef NS_ENUM(NSUInteger, GRPCTransportType) { GRPCTransportTypeDefault = 0, /** gRPC internal HTTP/2 stack with BoringSSL */ GRPCTransportTypeChttp2BoringSSL = 0, From ae623ea5b65ff6060d0b8a63fdf3f26560118720 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 17:32:22 -0800 Subject: [PATCH 157/375] Polish isEqual of options --- src/objective-c/GRPCClient/GRPCCallOptions.m | 43 +++++++++---------- .../GRPCClient/private/GRPCChannelPool.m | 2 +- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index c7096cf1cfb..beea9ce46ec 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -44,6 +44,17 @@ static const id kDefaultLogContext = nil; static NSString *const kDefaultChannelPoolDomain = nil; static const NSUInteger kDefaultChannelID = 0; +// Check if two objects are equal. Returns YES if both are nil; +BOOL areObjectsEqual(id obj1, id obj2) { + if (obj1 == obj2) { + return YES; + } + if (obj1 == nil || obj2 == nil) { + return NO; + } + return [obj1 isEqual:obj2]; +} + @implementation GRPCCallOptions { @protected NSString *_serverAuthority; @@ -232,9 +243,8 @@ static const NSUInteger kDefaultChannelID = 0; } - (BOOL)hasChannelOptionsEqualTo:(GRPCCallOptions *)callOptions { - if (!(callOptions.userAgentPrefix == _userAgentPrefix || - [callOptions.userAgentPrefix isEqualToString:_userAgentPrefix])) - return NO; + if (callOptions == nil) return NO; + if (!areObjectsEqual(callOptions.userAgentPrefix, _userAgentPrefix)) return NO; if (!(callOptions.responseSizeLimit == _responseSizeLimit)) return NO; if (!(callOptions.compressionAlgorithm == _compressionAlgorithm)) return NO; if (!(callOptions.retryEnabled == _retryEnabled)) return NO; @@ -243,27 +253,14 @@ static const NSUInteger kDefaultChannelID = 0; if (!(callOptions.connectMinTimeout == _connectMinTimeout)) return NO; if (!(callOptions.connectInitialBackoff == _connectInitialBackoff)) return NO; if (!(callOptions.connectMaxBackoff == _connectMaxBackoff)) return NO; - if (!(callOptions.additionalChannelArgs == _additionalChannelArgs || - [callOptions.additionalChannelArgs isEqualToDictionary:_additionalChannelArgs])) - return NO; - if (!(callOptions.PEMRootCertificates == _PEMRootCertificates || - [callOptions.PEMRootCertificates isEqualToString:_PEMRootCertificates])) - return NO; - if (!(callOptions.PEMPrivateKey == _PEMPrivateKey || - [callOptions.PEMPrivateKey isEqualToString:_PEMPrivateKey])) - return NO; - if (!(callOptions.PEMCertChain == _PEMCertChain || - [callOptions.PEMCertChain isEqualToString:_PEMCertChain])) - return NO; - if (!(callOptions.hostNameOverride == _hostNameOverride || - [callOptions.hostNameOverride isEqualToString:_hostNameOverride])) - return NO; + if (!areObjectsEqual(callOptions.additionalChannelArgs, _additionalChannelArgs)) return NO; + if (!areObjectsEqual(callOptions.PEMRootCertificates, _PEMRootCertificates)) return NO; + if (!areObjectsEqual(callOptions.PEMPrivateKey, _PEMPrivateKey)) return NO; + if (!areObjectsEqual(callOptions.PEMCertChain, _PEMCertChain)) return NO; + if (!areObjectsEqual(callOptions.hostNameOverride, _hostNameOverride)) return NO; if (!(callOptions.transportType == _transportType)) return NO; - if (!(callOptions.logContext == _logContext || [callOptions.logContext isEqual:_logContext])) - return NO; - if (!(callOptions.channelPoolDomain == _channelPoolDomain || - [callOptions.channelPoolDomain isEqualToString:_channelPoolDomain])) - return NO; + if (!areObjectsEqual(callOptions.logContext, _logContext)) return NO; + if (!areObjectsEqual(callOptions.channelPoolDomain, _channelPoolDomain)) return NO; if (!(callOptions.channelID == _channelID)) return NO; return YES; diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 56de8a0d6f5..627bbab3c01 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -151,7 +151,7 @@ extern const char *kCFStreamVarName; return NO; } GRPCChannelConfiguration *obj = (GRPCChannelConfiguration *)object; - if (!(obj.host == _host || [obj.host isEqualToString:_host])) return NO; + if (!(obj.host == _host || (_host != nil && [obj.host isEqualToString:_host]))) return NO; if (!(obj.callOptions == _callOptions || [obj.callOptions hasChannelOptionsEqualTo:_callOptions])) return NO; From bb5e55e86896ff353010db58bc6381436e11c4a5 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 17:37:47 -0800 Subject: [PATCH 158/375] remove extra copy --- src/objective-c/GRPCClient/GRPCCallOptions.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index beea9ce46ec..696e81703ff 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -360,7 +360,7 @@ BOOL areObjectsEqual(id obj1, id obj2) { connectMinTimeout:_connectMinTimeout connectInitialBackoff:_connectInitialBackoff connectMaxBackoff:_connectMaxBackoff - additionalChannelArgs:[_additionalChannelArgs copy] + additionalChannelArgs:_additionalChannelArgs PEMRootCertificates:_PEMRootCertificates PEMPrivateKey:_PEMPrivateKey PEMCertChain:_PEMCertChain From d8e7a6c6f1269eedec3f7b175ac85ed89e6e490e Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 17:38:21 -0800 Subject: [PATCH 159/375] hash: -> .hash --- src/objective-c/GRPCClient/GRPCCallOptions.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 696e81703ff..3e0dbbf7e42 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -283,7 +283,7 @@ BOOL areObjectsEqual(id obj1, id obj2) { result ^= _PEMCertChain.hash; result ^= _hostNameOverride.hash; result ^= _transportType; - result ^= [_logContext hash]; + result ^= _logContext.hash; result ^= _channelPoolDomain.hash; result ^= _channelID; From a0f5db15815d3ec5b2ad3b781cca5e2eb6468824 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 17:42:30 -0800 Subject: [PATCH 160/375] Rename GRPCCallOptions+internal->GRPCCallOptions+Internal --- gRPC.podspec | 2 +- .../{GRPCCallOptions+internal.h => GRPCCallOptions+Internal.h} | 0 templates/gRPC.podspec.template | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/objective-c/GRPCClient/internal/{GRPCCallOptions+internal.h => GRPCCallOptions+Internal.h} (100%) diff --git a/gRPC.podspec b/gRPC.podspec index 47a130d12d1..d8aa997e7cb 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -58,7 +58,7 @@ Pod::Spec.new do |s| ss.source_files = "#{src_dir}/*.{h,m}", "#{src_dir}/**/*.{h,m}" ss.exclude_files = "#{src_dir}/GRPCCall+GID.{h,m}" - ss.private_header_files = "#{src_dir}/private/*.h", "#{src_dir}/internal/GRPCCallOptions+Internal.h" + ss.private_header_files = "#{src_dir}/private/*.h", "#{src_dir}/internal/*.h" ss.dependency 'gRPC-Core', version end diff --git a/src/objective-c/GRPCClient/internal/GRPCCallOptions+internal.h b/src/objective-c/GRPCClient/internal/GRPCCallOptions+Internal.h similarity index 100% rename from src/objective-c/GRPCClient/internal/GRPCCallOptions+internal.h rename to src/objective-c/GRPCClient/internal/GRPCCallOptions+Internal.h diff --git a/templates/gRPC.podspec.template b/templates/gRPC.podspec.template index a3ed1d78584..593d277e5ba 100644 --- a/templates/gRPC.podspec.template +++ b/templates/gRPC.podspec.template @@ -60,7 +60,7 @@ ss.source_files = "#{src_dir}/*.{h,m}", "#{src_dir}/**/*.{h,m}" ss.exclude_files = "#{src_dir}/GRPCCall+GID.{h,m}" - ss.private_header_files = "#{src_dir}/private/*.h", "#{src_dir}/internal/GRPCCallOptions+Internal.h" + ss.private_header_files = "#{src_dir}/private/*.h", "#{src_dir}/internal/*.h" ss.dependency 'gRPC-Core', version end From ab9510560781dd2f27608e694518f67b7d425d9a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 6 Nov 2018 17:46:22 -0800 Subject: [PATCH 161/375] clang-format --- src/objective-c/GRPCClient/GRPCCall.h | 4 +-- src/objective-c/GRPCClient/GRPCCall.m | 13 +++---- src/objective-c/ProtoRPC/ProtoRPC.h | 4 +-- src/objective-c/tests/APIv2Tests/APIv2Tests.m | 35 ++++++++++--------- 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 260305a989c..bde69f01c52 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -196,7 +196,7 @@ extern NSString *const kGRPCTrailersKey; - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; ++ (instancetype) new NS_UNAVAILABLE; /** Initialize with all properties. */ - (instancetype)initWithHost:(NSString *)host @@ -224,7 +224,7 @@ extern NSString *const kGRPCTrailersKey; - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; ++ (instancetype) new NS_UNAVAILABLE; /** * Designated initializer for a call. diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index b3bddf08a05..321a0bd1bd7 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -468,7 +468,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)cancelCall { // Can be called from any thread, any number of times. - @synchronized (self) { + @synchronized(self) { [_wrappedCall cancel]; } } @@ -732,18 +732,19 @@ const char *kCFStreamVarName = "grpc_cfstream"; _responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable dispatchQueue:_responseQueue]; - GRPCWrappedCall *wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host path:_path callOptions:_callOptions]; + GRPCWrappedCall *wrappedCall = + [[GRPCWrappedCall alloc] initWithHost:_host path:_path callOptions:_callOptions]; if (wrappedCall == nil) { [self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeUnavailable userInfo:@{ - NSLocalizedDescriptionKey : - @"Failed to create call or channel." - }]]; + NSLocalizedDescriptionKey : + @"Failed to create call or channel." + }]]; return; } - @synchronized (self) { + @synchronized(self) { _wrappedCall = wrappedCall; } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 3d137a53ffc..b0f4ced99e8 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -66,7 +66,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; ++ (instancetype) new NS_UNAVAILABLE; /** * Users should not use this initializer directly. Call objects will be created, initialized, and @@ -92,7 +92,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; ++ (instancetype) new NS_UNAVAILABLE; /** * Users should not use this initializer directly. Call objects will be created, initialized, and diff --git a/src/objective-c/tests/APIv2Tests/APIv2Tests.m b/src/objective-c/tests/APIv2Tests/APIv2Tests.m index 7fc353391f3..d681163419d 100644 --- a/src/objective-c/tests/APIv2Tests/APIv2Tests.m +++ b/src/objective-c/tests/APIv2Tests/APIv2Tests.m @@ -449,28 +449,29 @@ static const NSTimeInterval kTestTimeout = 16; request.responseSize = kSimpleDataLength; request.payload.body = [NSMutableData dataWithLength:kSimpleDataLength]; GRPCRequestOptions *requestOptions = - [[GRPCRequestOptions alloc] initWithHost:kHostAddress - path:kUnaryCallMethod.HTTPPath - safety:GRPCCallSafetyDefault]; + [[GRPCRequestOptions alloc] initWithHost:kHostAddress + path:kUnaryCallMethod.HTTPPath + safety:GRPCCallSafetyDefault]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; options.transportType = GRPCTransportTypeInsecure; options.compressionAlgorithm = GRPCCompressGzip; GRPCCall2 *call = [[GRPCCall2 alloc] - initWithRequestOptions:requestOptions - responseHandler: [[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil - messageCallback:^(NSData *data) { - NSError *error; - RMTSimpleResponse *response = [RMTSimpleResponse parseFromData:data error:&error]; - XCTAssertNil(error, @"Error when parsing response: %@", error); - XCTAssertEqual(response.payload.body.length, kSimpleDataLength); - } - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - XCTAssertNil(error, @"Received failure: %@", error); - [completion fulfill]; - }] - - callOptions:options]; + initWithRequestOptions:requestOptions + responseHandler:[[ClientTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + messageCallback:^(NSData *data) { + NSError *error; + RMTSimpleResponse *response = + [RMTSimpleResponse parseFromData:data error:&error]; + XCTAssertNil(error, @"Error when parsing response: %@", error); + XCTAssertEqual(response.payload.body.length, kSimpleDataLength); + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + XCTAssertNil(error, @"Received failure: %@", error); + [completion fulfill]; + }] + + callOptions:options]; [call start]; [call writeData:[request data]]; From 9e5d7476ac48b82ee8ce7855c30d3aa5edab5280 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 7 Nov 2018 11:32:12 -0800 Subject: [PATCH 162/375] nit build fix --- src/objective-c/GRPCClient/GRPCCallOptions.m | 4 ++-- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 2 +- src/objective-c/GRPCClient/private/GRPCHost.m | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 3e0dbbf7e42..ecb517762b3 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -17,7 +17,7 @@ */ #import "GRPCCallOptions.h" -#import "internal/GRPCCallOptions+internal.h" +#import "internal/GRPCCallOptions+Internal.h" // The default values for the call options. static NSString *const kDefaultServerAuthority = nil; @@ -77,7 +77,7 @@ BOOL areObjectsEqual(id obj1, id obj2) { NSString *_PEMCertChain; GRPCTransportType _transportType; NSString *_hostNameOverride; - id _logContext; + id _logContext; NSString *_channelPoolDomain; NSUInteger _channelID; } diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 627bbab3c01..b4a589ae838 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -18,7 +18,7 @@ #import -#import "../internal/GRPCCallOptions+internal.h" +#import "../internal/GRPCCallOptions+Internal.h" #import "GRPCChannel.h" #import "GRPCChannelFactory.h" #import "GRPCChannelPool.h" diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 8a59bd43d74..a67162c1014 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -25,7 +25,7 @@ #include #include -#import "../internal/GRPCCallOptions+internal.h" +#import "../internal/GRPCCallOptions+Internal.h" #import "GRPCChannelFactory.h" #import "GRPCCompletionQueue.h" #import "GRPCConnectivityMonitor.h" From c9c060c52da12cc55bbd383b1544260ad665dbab Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 7 Nov 2018 11:32:30 -0800 Subject: [PATCH 163/375] nit fixes in ChannelArgsUtil --- src/objective-c/GRPCClient/private/ChannelArgsUtil.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m index b8342a79e79..d9e44b557d1 100644 --- a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m +++ b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m @@ -31,7 +31,7 @@ static void *copy_pointer_arg(void *p) { static void destroy_pointer_arg(void *p) { // Decrease ref count to the object when destroying - CFRelease((CFTreeRef)p); + CFRelease((CFTypeRef)p); } static int cmp_pointer_arg(void *p, void *q) { return p == q; } @@ -52,7 +52,7 @@ void GRPCFreeChannelArgs(grpc_channel_args *channel_args) { } grpc_channel_args *GRPCBuildChannelArgs(NSDictionary *dictionary) { - if (!dictionary) { + if (dictionary.count == 0) { return NULL; } From d72d5b2c8eaa8a434a7db4624fe6a45bc0d6bde4 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 8 Nov 2018 15:33:27 -0800 Subject: [PATCH 164/375] Some nit fixes --- src/objective-c/GRPCClient/GRPCCall.m | 4 +++- .../GRPCClient/private/GRPCChannel.m | 21 +++++++++++-------- .../GRPCClient/private/GRPCChannelPool.h | 2 -- .../GRPCClient/private/GRPCChannelPool.m | 1 + 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 321a0bd1bd7..9b9b4f95471 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -108,6 +108,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; /** Flags whether call has been canceled. */ BOOL _canceled; /** Flags whether call has been finished. */ + BOOL _finished; } - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions @@ -144,6 +145,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; dispatch_set_target_queue(responseHandler.dispatchQueue, _dispatchQueue); _started = NO; _canceled = NO; + _finished = YES; } return self; @@ -252,7 +254,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)finish { dispatch_async(_dispatchQueue, ^{ - NSAssert(self->started, @"Call not started."); + NSAssert(self->_started, @"Call not started."); NSAssert(!self->_canceled, @"Call arleady canceled."); NSAssert(!self->_finished, @"Call already half-closed."); if (self->_call) { diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 0ca2a359926..773f4261d75 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -53,7 +53,7 @@ static GRPCChannelPool *gChannelPool; /** Reduce call ref count to the channel and maybe set the timer. */ - (void)unrefChannel; -/** Disconnect the channel immediately. */ +/** Disconnect the channel. Any further ref/unref are discarded. */ - (void)disconnect; @end @@ -67,9 +67,8 @@ static GRPCChannelPool *gChannelPool; dispatch_queue_t _dispatchQueue; /** - * Date and time when last timer is scheduled. When a timer is fired, if - * _lastDispatch + _destroyDelay < now, it can be determined that another timer is scheduled after - * schedule of the current timer, hence the current one should be discarded. + * Date and time when last timer is scheduled. If a firing timer's scheduled date is different + * from this, it is discarded. */ NSDate *_lastDispatch; } @@ -113,7 +112,7 @@ static GRPCChannelPool *gChannelPool; dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)self->_destroyDelay * NSEC_PER_SEC); dispatch_after(delay, self->_dispatchQueue, ^{ - [self timerFireWithScheduleDate:now]; + [self timedDisconnectWithScheduleDate:now]; }); } } @@ -131,7 +130,7 @@ static GRPCChannelPool *gChannelPool; }); } -- (void)timerFireWithScheduleDate:(NSDate *)scheduleDate { +- (void)timedDisconnectWithScheduleDate:(NSDate *)scheduleDate { dispatch_async(_dispatchQueue, ^{ if (self->_disconnected || self->_lastDispatch != scheduleDate) { return; @@ -183,6 +182,8 @@ static GRPCChannelPool *gChannelPool; grpc_slice_unref(host_slice); } grpc_slice_unref(path_slice); + } else { + NSAssert(self->_unmanagedChannel != nil, @"Invalid channeg."); } }); return call; @@ -255,10 +256,9 @@ static GRPCChannelPool *gChannelPool; } + (nullable instancetype)createChannelWithConfiguration:(GRPCChannelConfiguration *)config { + NSAssert(config != nil, @"configuration cannot be empty"); NSString *host = config.host; - if (host.length == 0) { - return nil; - } + NSAssert(host.length != 0, @"host cannot be nil"); NSDictionary *channelArgs; if (config.callOptions.additionalChannelArgs.count != 0) { @@ -287,6 +287,9 @@ static GRPCChannelPool *gChannelPool; GRPCChannelConfiguration *channelConfig = [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; + if (channelConfig == nil) { + return nil; + } return [gChannelPool channelWithConfiguration:channelConfig]; } diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 2244361df2c..f99c0ba4dc2 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -57,8 +57,6 @@ NS_ASSUME_NONNULL_BEGIN */ @interface GRPCChannelPool : NSObject -- (instancetype)init; - /** * Return a channel with a particular configuration. If the channel does not exist, execute \a * createChannel then add it in the pool. If the channel exists, increase its reference count. diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index b4a589ae838..1bf2a5c5633 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -192,6 +192,7 @@ extern const char *kCFStreamVarName; } - (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration { + NSAssert(configuration != nil, @"Must has a configuration"); GRPCChannel *channel; @synchronized(self) { if ([_channelPool objectForKey:configuration]) { From 37dbad80d5254f9bf17076d12b22b7a081e6e9dc Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 8 Nov 2018 22:01:10 -0800 Subject: [PATCH 165/375] Refactor channel pool --- .../GRPCClient/GRPCCall+ChannelArg.m | 4 +- .../GRPCClient/private/GRPCChannel.h | 69 ++- .../GRPCClient/private/GRPCChannel.m | 397 ++++++++++-------- .../GRPCClient/private/GRPCChannelPool.h | 55 ++- .../GRPCClient/private/GRPCChannelPool.m | 215 ++-------- .../GRPCClient/private/GRPCWrappedCall.m | 24 +- .../tests/ChannelTests/ChannelPoolTest.m | 161 +++---- .../tests/ChannelTests/ChannelTests.m | 97 ++--- 8 files changed, 482 insertions(+), 540 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m index d01d0c0d4fd..971c2803e29 100644 --- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m +++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m @@ -18,7 +18,7 @@ #import "GRPCCall+ChannelArg.h" -#import "private/GRPCChannel.h" +#import "private/GRPCChannelPool.h" #import "private/GRPCHost.h" #import @@ -36,7 +36,7 @@ } + (void)closeOpenConnections { - [GRPCChannel closeOpenConnections]; + [GRPCChannelPool closeOpenConnections]; } + (void)setDefaultCompressMethod:(GRPCCompressAlgorithm)algorithm forhost:(nonnull NSString *)host { diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index e1bf8fb1af4..bbe0ba53904 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -20,11 +20,37 @@ #include +@protocol GRPCChannelFactory; + @class GRPCCompletionQueue; @class GRPCCallOptions; @class GRPCChannelConfiguration; struct grpc_channel_credentials; +NS_ASSUME_NONNULL_BEGIN + +/** Caching signature of a channel. */ +@interface GRPCChannelConfiguration : NSObject + +/** The host that this channel is connected to. */ +@property(copy, readonly) NSString *host; + +/** + * Options of the corresponding call. Note that only the channel-related options are of interest to + * this class. + */ +@property(strong, readonly) GRPCCallOptions *callOptions; + +/** Acquire the factory to generate a new channel with current configurations. */ +@property(readonly) id channelFactory; + +/** Acquire the dictionary of channel args with current configurations. */ +@property(copy, readonly) NSDictionary *channelArgs; + +- (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; + +@end + /** * Each separate instance of this class represents at least one TCP connection to the provided host. */ @@ -35,40 +61,45 @@ struct grpc_channel_credentials; + (nullable instancetype) new NS_UNAVAILABLE; /** - * Returns a channel connecting to \a host with options as \a callOptions. The channel may be new - * or a cached channel that is already connected. + * Create a channel with remote \a host and signature \a channelConfigurations. Destroy delay is + * defaulted to 30 seconds. */ -+ (nullable instancetype)channelWithHost:(nonnull NSString *)host - callOptions:(nullable GRPCCallOptions *)callOptions; +- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration; /** - * Create a channel object with the signature \a config. + * Create a channel with remote \a host, signature \a channelConfigurations, and destroy delay of + * \a destroyDelay. */ -+ (nullable instancetype)createChannelWithConfiguration:(nonnull GRPCChannelConfiguration *)config; +- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration + destroyDelay:(NSTimeInterval)destroyDelay NS_DESIGNATED_INITIALIZER; /** - * Get a grpc core call object from this channel. + * Create a grpc core call object from this channel. The channel's refcount is added by 1. If no + * call is created, NULL is returned, and if the reason is because the channel is already + * disconnected, \a disconnected is set to YES. When the returned call is unreffed, the caller is + * obligated to call \a unref method once. \a disconnected may be null. */ -- (nullable grpc_call *)unmanagedCallWithPath:(nonnull NSString *)path - completionQueue:(nonnull GRPCCompletionQueue *)queue - callOptions:(nonnull GRPCCallOptions *)callOptions; +- (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path + completionQueue:(GRPCCompletionQueue *)queue + callOptions:(GRPCCallOptions *)callOptions + disconnected:(BOOL * _Nullable)disconnected; /** - * Increase the refcount of the channel. If the channel was timed to be destroyed, cancel the timer. + * Unref the channel when a call is done. It also decreases the channel's refcount. If the refcount + * of the channel decreases to 0, the channel is destroyed after the destroy delay. */ -- (void)ref; +- (void)unref; /** - * Decrease the refcount of the channel. If the refcount of the channel decrease to 0, the channel - * is destroyed after 30 seconds. + * Force the channel to be disconnected and destroyed. */ -- (void)unref; +- (void)disconnect; /** - * Force the channel to be disconnected and destroyed immediately. + * Return whether the channel is already disconnected. */ -- (void)disconnect; +@property(readonly) BOOL disconnected; -// TODO (mxyan): deprecate with GRPCCall:closeOpenConnections -+ (void)closeOpenConnections; @end + +NS_ASSUME_NONNULL_END diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 773f4261d75..298b6605d1f 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -28,141 +28,222 @@ #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" #import "version.h" +#import "../internal/GRPCCallOptions+Internal.h" #import #import /** When all calls of a channel are destroyed, destroy the channel after this much seconds. */ -NSTimeInterval kChannelDestroyDelay = 30; +NSTimeInterval kDefaultChannelDestroyDelay = 30; -/** Global instance of channel pool. */ -static GRPCChannelPool *gChannelPool; +@implementation GRPCChannelConfiguration -/** - * Time the channel destroy when the channel's calls are unreffed. If there's new call, reset the - * timer. - */ -@interface GRPCChannelRef : NSObject +- (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { + NSAssert(host.length, @"Host must not be empty."); + NSAssert(callOptions, @"callOptions must not be empty."); + if ((self = [super init])) { + _host = [host copy]; + _callOptions = [callOptions copy]; + } + return self; +} -- (instancetype)initWithDestroyDelay:(NSTimeInterval)destroyDelay - destroyChannelCallback:(void (^)())destroyChannelCallback; +- (id)channelFactory { + NSError *error; + id factory; + GRPCTransportType type = _callOptions.transportType; + switch (type) { + case GRPCTransportTypeChttp2BoringSSL: + // TODO (mxyan): Remove when the API is deprecated +#ifdef GRPC_COMPILE_WITH_CRONET + if (![GRPCCall isUsingCronet]) { +#endif + factory = [GRPCSecureChannelFactory + factoryWithPEMRootCertificates:_callOptions.PEMRootCertificates + privateKey:_callOptions.PEMPrivateKey + certChain:_callOptions.PEMCertChain + error:&error]; + if (factory == nil) { + NSLog(@"Error creating secure channel factory: %@", error); + } + return factory; +#ifdef GRPC_COMPILE_WITH_CRONET + } +#endif + // fallthrough + case GRPCTransportTypeCronet: + return [GRPCCronetChannelFactory sharedInstance]; + case GRPCTransportTypeInsecure: + return [GRPCInsecureChannelFactory sharedInstance]; + } +} -/** Add call ref count to the channel and maybe reset the timer. */ -- (void)refChannel; +- (NSDictionary *)channelArgs { + NSMutableDictionary *args = [NSMutableDictionary new]; -/** Reduce call ref count to the channel and maybe set the timer. */ -- (void)unrefChannel; + NSString *userAgent = @"grpc-objc/" GRPC_OBJC_VERSION_STRING; + NSString *userAgentPrefix = _callOptions.userAgentPrefix; + if (userAgentPrefix) { + args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = + [_callOptions.userAgentPrefix stringByAppendingFormat:@" %@", userAgent]; + } else { + args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = userAgent; + } -/** Disconnect the channel. Any further ref/unref are discarded. */ -- (void)disconnect; + NSString *hostNameOverride = _callOptions.hostNameOverride; + if (hostNameOverride) { + args[@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG] = hostNameOverride; + } -@end + if (_callOptions.responseSizeLimit) { + args[@GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH] = + [NSNumber numberWithUnsignedInteger:_callOptions.responseSizeLimit]; + } -@implementation GRPCChannelRef { - NSTimeInterval _destroyDelay; - void (^_destroyChannelCallback)(); + if (_callOptions.compressionAlgorithm != GRPC_COMPRESS_NONE) { + args[@GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM] = + [NSNumber numberWithInt:_callOptions.compressionAlgorithm]; + } - NSUInteger _refCount; - BOOL _disconnected; - dispatch_queue_t _dispatchQueue; + if (_callOptions.keepaliveInterval != 0) { + args[@GRPC_ARG_KEEPALIVE_TIME_MS] = + [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.keepaliveInterval * 1000)]; + args[@GRPC_ARG_KEEPALIVE_TIMEOUT_MS] = + [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.keepaliveTimeout * 1000)]; + } - /** - * Date and time when last timer is scheduled. If a firing timer's scheduled date is different - * from this, it is discarded. - */ - NSDate *_lastDispatch; -} + if (_callOptions.retryEnabled == NO) { + args[@GRPC_ARG_ENABLE_RETRIES] = [NSNumber numberWithInt:_callOptions.retryEnabled]; + } -- (instancetype)initWithDestroyDelay:(NSTimeInterval)destroyDelay - destroyChannelCallback:(void (^)())destroyChannelCallback { - if ((self = [super init])) { - _destroyDelay = destroyDelay; - _destroyChannelCallback = destroyChannelCallback; + if (_callOptions.connectMinTimeout > 0) { + args[@GRPC_ARG_MIN_RECONNECT_BACKOFF_MS] = + [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectMinTimeout * 1000)]; + } + if (_callOptions.connectInitialBackoff > 0) { + args[@GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS] = [NSNumber + numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectInitialBackoff * 1000)]; + } + if (_callOptions.connectMaxBackoff > 0) { + args[@GRPC_ARG_MAX_RECONNECT_BACKOFF_MS] = + [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectMaxBackoff * 1000)]; + } - _refCount = 1; - _disconnected = NO; - if (@available(iOS 8.0, *)) { - _dispatchQueue = dispatch_queue_create( - NULL, - dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); - } else { - _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); - } - _lastDispatch = nil; + if (_callOptions.logContext != nil) { + args[@GRPC_ARG_MOBILE_LOG_CONTEXT] = _callOptions.logContext; } - return self; -} -- (void)refChannel { - dispatch_async(_dispatchQueue, ^{ - if (!self->_disconnected) { - self->_refCount++; - self->_lastDispatch = nil; - } - }); + if (_callOptions.channelPoolDomain.length != 0) { + args[@GRPC_ARG_CHANNEL_POOL_DOMAIN] = _callOptions.channelPoolDomain; + } + + [args addEntriesFromDictionary:_callOptions.additionalChannelArgs]; + + return args; } -- (void)unrefChannel { - dispatch_async(_dispatchQueue, ^{ - if (!self->_disconnected) { - self->_refCount--; - if (self->_refCount == 0) { - NSDate *now = [NSDate date]; - self->_lastDispatch = now; - dispatch_time_t delay = - dispatch_time(DISPATCH_TIME_NOW, (int64_t)self->_destroyDelay * NSEC_PER_SEC); - dispatch_after(delay, self->_dispatchQueue, ^{ - [self timedDisconnectWithScheduleDate:now]; - }); - } - } - }); +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + GRPCChannelConfiguration *newConfig = + [[GRPCChannelConfiguration alloc] initWithHost:_host callOptions:_callOptions]; + + return newConfig; } -- (void)disconnect { - dispatch_async(_dispatchQueue, ^{ - if (!self->_disconnected) { - self->_lastDispatch = nil; - self->_disconnected = YES; - // Break retain loop - self->_destroyChannelCallback = nil; - } - }); +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[GRPCChannelConfiguration class]]) { + return NO; + } + GRPCChannelConfiguration *obj = (GRPCChannelConfiguration *)object; + if (!(obj.host == _host || (_host != nil && [obj.host isEqualToString:_host]))) return NO; + if (!(obj.callOptions == _callOptions || [obj.callOptions hasChannelOptionsEqualTo:_callOptions])) + return NO; + + return YES; } -- (void)timedDisconnectWithScheduleDate:(NSDate *)scheduleDate { - dispatch_async(_dispatchQueue, ^{ - if (self->_disconnected || self->_lastDispatch != scheduleDate) { - return; - } - self->_lastDispatch = nil; - self->_disconnected = YES; - self->_destroyChannelCallback(); - // Break retain loop - self->_destroyChannelCallback = nil; - }); +- (NSUInteger)hash { + NSUInteger result = 0; + result ^= _host.hash; + result ^= _callOptions.channelOptionsHash; + + return result; } @end + + @implementation GRPCChannel { GRPCChannelConfiguration *_configuration; - grpc_channel *_unmanagedChannel; - GRPCChannelRef *_channelRef; + dispatch_queue_t _dispatchQueue; + grpc_channel *_unmanagedChannel; + NSTimeInterval _destroyDelay; + + NSUInteger _refcount; + NSDate *_lastDispatch; +} +@synthesize disconnected = _disconnected; + +- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration { + return [self initWithChannelConfiguration:channelConfiguration + destroyDelay:kDefaultChannelDestroyDelay]; +} + +- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration + destroyDelay:(NSTimeInterval)destroyDelay { + NSAssert(channelConfiguration, @"channelConfiguration must not be empty."); + NSAssert(destroyDelay > 0, @"destroyDelay must be greater than 0."); + if ((self = [super init])) { + _configuration = [channelConfiguration copy]; + if (@available(iOS 8.0, *)) { + _dispatchQueue = dispatch_queue_create( + NULL, + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + } else { + _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + } + + // Create gRPC core channel object. + NSString *host = channelConfiguration.host; + NSAssert(host.length != 0, @"host cannot be nil"); + NSDictionary *channelArgs; + if (channelConfiguration.callOptions.additionalChannelArgs.count != 0) { + NSMutableDictionary *args = [channelConfiguration.channelArgs mutableCopy]; + [args addEntriesFromDictionary:channelConfiguration.callOptions.additionalChannelArgs]; + channelArgs = args; + } else { + channelArgs = channelConfiguration.channelArgs; + } + id factory = channelConfiguration.channelFactory; + _unmanagedChannel = [factory createChannelWithHost:host channelArgs:channelArgs]; + if (_unmanagedChannel == NULL) { + NSLog(@"Unable to create channel."); + return nil; + } + _destroyDelay = destroyDelay; + _disconnected = NO; + } + return self; } - (grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue - callOptions:(GRPCCallOptions *)callOptions { + callOptions:(GRPCCallOptions *)callOptions + disconnected:(BOOL *)disconnected { NSAssert(path.length, @"path must not be empty."); NSAssert(queue, @"completionQueue must not be empty."); NSAssert(callOptions, @"callOptions must not be empty."); - __block grpc_call *call = nil; + __block BOOL isDisconnected = NO; + __block grpc_call *call = NULL; dispatch_sync(_dispatchQueue, ^{ - if (self->_unmanagedChannel) { + if (self->_disconnected) { + isDisconnected = YES; + } else { + NSAssert(self->_unmanagedChannel != NULL, @"Invalid channel."); + NSString *serverAuthority = - callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; + callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; NSTimeInterval timeout = callOptions.timeout; NSAssert(timeout >= 0, @"Invalid timeout"); grpc_slice host_slice = grpc_empty_slice(); @@ -171,10 +252,10 @@ static GRPCChannelPool *gChannelPool; } grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); gpr_timespec deadline_ms = - timeout == 0 - ? gpr_inf_future(GPR_CLOCK_REALTIME) - : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); + timeout == 0 + ? gpr_inf_future(GPR_CLOCK_REALTIME) + : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); call = grpc_channel_create_call(self->_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, queue.unmanagedQueue, path_slice, serverAuthority ? &host_slice : NULL, deadline_ms, NULL); @@ -182,71 +263,64 @@ static GRPCChannelPool *gChannelPool; grpc_slice_unref(host_slice); } grpc_slice_unref(path_slice); - } else { - NSAssert(self->_unmanagedChannel != nil, @"Invalid channeg."); + if (call == NULL) { + NSLog(@"Unable to create call."); + } else { + // Ref the channel; + [self ref]; + } } }); + if (disconnected != nil) { + *disconnected = isDisconnected; + } return call; } +// This function should be called on _dispatchQueue. - (void)ref { - dispatch_async(_dispatchQueue, ^{ - if (self->_unmanagedChannel) { - [self->_channelRef refChannel]; - } - }); + _refcount++; + if (_refcount == 1 && _lastDispatch != nil) { + _lastDispatch = nil; + } } - (void)unref { dispatch_async(_dispatchQueue, ^{ - if (self->_unmanagedChannel) { - [self->_channelRef unrefChannel]; + self->_refcount--; + if (self->_refcount == 0 && !self->_disconnected) { + // Start timer. + dispatch_time_t delay = + dispatch_time(DISPATCH_TIME_NOW, (int64_t)self->_destroyDelay * NSEC_PER_SEC); + NSDate *now = [NSDate date]; + self->_lastDispatch = now; + dispatch_after(delay, self->_dispatchQueue, ^{ + if (self->_lastDispatch == now) { + grpc_channel_destroy(self->_unmanagedChannel); + self->_unmanagedChannel = NULL; + self->_disconnected = YES; + } + }); } }); } - (void)disconnect { dispatch_async(_dispatchQueue, ^{ - if (self->_unmanagedChannel) { + if (!self->_disconnected) { grpc_channel_destroy(self->_unmanagedChannel); self->_unmanagedChannel = nil; - [self->_channelRef disconnect]; + self->_disconnected = YES; } }); } -- (void)destroyChannel { - dispatch_async(_dispatchQueue, ^{ - if (self->_unmanagedChannel) { - grpc_channel_destroy(self->_unmanagedChannel); - self->_unmanagedChannel = nil; - [gChannelPool removeChannel:self]; - } +- (BOOL)disconnected { + __block BOOL disconnected; + dispatch_sync(_dispatchQueue, ^{ + disconnected = self->_disconnected; }); -} - -- (nullable instancetype)initWithUnmanagedChannel:(grpc_channel *_Nullable)unmanagedChannel - configuration:(GRPCChannelConfiguration *)configuration { - NSAssert(configuration, @"Configuration must not be empty."); - if (!unmanagedChannel) { - return nil; - } - if ((self = [super init])) { - _unmanagedChannel = unmanagedChannel; - _configuration = [configuration copy]; - _channelRef = [[GRPCChannelRef alloc] initWithDestroyDelay:kChannelDestroyDelay - destroyChannelCallback:^{ - [self destroyChannel]; - }]; - if (@available(iOS 8.0, *)) { - _dispatchQueue = dispatch_queue_create( - NULL, - dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); - } else { - _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); - } - } - return self; + return disconnected; } - (void)dealloc { @@ -255,47 +329,4 @@ static GRPCChannelPool *gChannelPool; } } -+ (nullable instancetype)createChannelWithConfiguration:(GRPCChannelConfiguration *)config { - NSAssert(config != nil, @"configuration cannot be empty"); - NSString *host = config.host; - NSAssert(host.length != 0, @"host cannot be nil"); - - NSDictionary *channelArgs; - if (config.callOptions.additionalChannelArgs.count != 0) { - NSMutableDictionary *args = [config.channelArgs mutableCopy]; - [args addEntriesFromDictionary:config.callOptions.additionalChannelArgs]; - channelArgs = args; - } else { - channelArgs = config.channelArgs; - } - id factory = config.channelFactory; - grpc_channel *unmanaged_channel = [factory createChannelWithHost:host channelArgs:channelArgs]; - return [[GRPCChannel alloc] initWithUnmanagedChannel:unmanaged_channel configuration:config]; -} - -+ (nullable instancetype)channelWithHost:(NSString *)host - callOptions:(GRPCCallOptions *)callOptions { - static dispatch_once_t initChannelPool; - dispatch_once(&initChannelPool, ^{ - gChannelPool = [[GRPCChannelPool alloc] init]; - }); - - NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:host]]; - if (hostURL.host && !hostURL.port) { - host = [hostURL.host stringByAppendingString:@":443"]; - } - - GRPCChannelConfiguration *channelConfig = - [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; - if (channelConfig == nil) { - return nil; - } - - return [gChannelPool channelWithConfiguration:channelConfig]; -} - -+ (void)closeOpenConnections { - [gChannelPool removeAndCloseAllChannels]; -} - @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index f99c0ba4dc2..24c0a8df115 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -29,48 +29,45 @@ NS_ASSUME_NONNULL_BEGIN @class GRPCChannel; -/** Caching signature of a channel. */ -@interface GRPCChannelConfiguration : NSObject - -/** The host that this channel is connected to. */ -@property(copy, readonly) NSString *host; - -/** - * Options of the corresponding call. Note that only the channel-related options are of interest to - * this class. - */ -@property(strong, readonly) GRPCCallOptions *callOptions; - -/** Acquire the factory to generate a new channel with current configurations. */ -@property(readonly) id channelFactory; - -/** Acquire the dictionary of channel args with current configurations. */ -@property(copy, readonly) NSDictionary *channelArgs; - -- (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; - -@end - /** * Manage the pool of connected channels. When a channel is no longer referenced by any call, * destroy the channel after a certain period of time elapsed. */ @interface GRPCChannelPool : NSObject +/** + * Get the singleton instance + */ ++ (nullable instancetype)sharedInstance; + /** * Return a channel with a particular configuration. If the channel does not exist, execute \a * createChannel then add it in the pool. If the channel exists, increase its reference count. */ -- (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration; +- (GRPCChannel *)channelWithHost:(NSString *)host + callOptions:(GRPCCallOptions *)callOptions; + +/** + * This method is deprecated. + * + * Destroy all open channels and close their connections. + */ ++ (void)closeOpenConnections; -/** Remove a channel from the pool. */ -- (void)removeChannel:(GRPCChannel *)channel; +// Test-only methods below -/** Clear all channels in the pool. */ -- (void)removeAllChannels; +/** + * Return a channel with a special destroy delay. If \a destroyDelay is 0, use the default destroy + * delay. + */ +- (GRPCChannel *)channelWithHost:(NSString *)host + callOptions:(GRPCCallOptions *)callOptions + destroyDelay:(NSTimeInterval)destroyDelay; -/** Clear all channels in the pool and destroy the channels. */ -- (void)removeAndCloseAllChannels; +/** + * Simulate a network transition event and destroy all channels. + */ +- (void)destroyAllChannels; @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 1bf2a5c5633..98c1634bc8b 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -33,147 +33,23 @@ extern const char *kCFStreamVarName; -@implementation GRPCChannelConfiguration - -- (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { - NSAssert(host.length, @"Host must not be empty."); - NSAssert(callOptions, @"callOptions must not be empty."); - if ((self = [super init])) { - _host = [host copy]; - _callOptions = [callOptions copy]; - } - return self; -} - -- (id)channelFactory { - NSError *error; - id factory; - GRPCTransportType type = _callOptions.transportType; - switch (type) { - case GRPCTransportTypeChttp2BoringSSL: - // TODO (mxyan): Remove when the API is deprecated -#ifdef GRPC_COMPILE_WITH_CRONET - if (![GRPCCall isUsingCronet]) { -#endif - factory = [GRPCSecureChannelFactory - factoryWithPEMRootCertificates:_callOptions.PEMRootCertificates - privateKey:_callOptions.PEMPrivateKey - certChain:_callOptions.PEMCertChain - error:&error]; - if (factory == nil) { - NSLog(@"Error creating secure channel factory: %@", error); - } - return factory; -#ifdef GRPC_COMPILE_WITH_CRONET - } -#endif - // fallthrough - case GRPCTransportTypeCronet: - return [GRPCCronetChannelFactory sharedInstance]; - case GRPCTransportTypeInsecure: - return [GRPCInsecureChannelFactory sharedInstance]; - } -} - -- (NSDictionary *)channelArgs { - NSMutableDictionary *args = [NSMutableDictionary new]; - - NSString *userAgent = @"grpc-objc/" GRPC_OBJC_VERSION_STRING; - NSString *userAgentPrefix = _callOptions.userAgentPrefix; - if (userAgentPrefix) { - args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = - [_callOptions.userAgentPrefix stringByAppendingFormat:@" %@", userAgent]; - } else { - args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = userAgent; - } - - NSString *hostNameOverride = _callOptions.hostNameOverride; - if (hostNameOverride) { - args[@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG] = hostNameOverride; - } - - if (_callOptions.responseSizeLimit) { - args[@GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH] = - [NSNumber numberWithUnsignedInteger:_callOptions.responseSizeLimit]; - } - - if (_callOptions.compressionAlgorithm != GRPC_COMPRESS_NONE) { - args[@GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM] = - [NSNumber numberWithInt:_callOptions.compressionAlgorithm]; - } - - if (_callOptions.keepaliveInterval != 0) { - args[@GRPC_ARG_KEEPALIVE_TIME_MS] = - [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.keepaliveInterval * 1000)]; - args[@GRPC_ARG_KEEPALIVE_TIMEOUT_MS] = - [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.keepaliveTimeout * 1000)]; - } - - if (_callOptions.retryEnabled == NO) { - args[@GRPC_ARG_ENABLE_RETRIES] = [NSNumber numberWithInt:_callOptions.retryEnabled]; - } - - if (_callOptions.connectMinTimeout > 0) { - args[@GRPC_ARG_MIN_RECONNECT_BACKOFF_MS] = - [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectMinTimeout * 1000)]; - } - if (_callOptions.connectInitialBackoff > 0) { - args[@GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS] = [NSNumber - numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectInitialBackoff * 1000)]; - } - if (_callOptions.connectMaxBackoff > 0) { - args[@GRPC_ARG_MAX_RECONNECT_BACKOFF_MS] = - [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectMaxBackoff * 1000)]; - } - - if (_callOptions.logContext != nil) { - args[@GRPC_ARG_MOBILE_LOG_CONTEXT] = _callOptions.logContext; - } - - if (_callOptions.channelPoolDomain.length != 0) { - args[@GRPC_ARG_CHANNEL_POOL_DOMAIN] = _callOptions.channelPoolDomain; - } - - [args addEntriesFromDictionary:_callOptions.additionalChannelArgs]; - - return args; -} - -- (nonnull id)copyWithZone:(nullable NSZone *)zone { - GRPCChannelConfiguration *newConfig = - [[GRPCChannelConfiguration alloc] initWithHost:_host callOptions:_callOptions]; - - return newConfig; -} - -- (BOOL)isEqual:(id)object { - if (![object isKindOfClass:[GRPCChannelConfiguration class]]) { - return NO; - } - GRPCChannelConfiguration *obj = (GRPCChannelConfiguration *)object; - if (!(obj.host == _host || (_host != nil && [obj.host isEqualToString:_host]))) return NO; - if (!(obj.callOptions == _callOptions || [obj.callOptions hasChannelOptionsEqualTo:_callOptions])) - return NO; - - return YES; -} - -- (NSUInteger)hash { - NSUInteger result = 0; - result ^= _host.hash; - result ^= _callOptions.channelOptionsHash; - - return result; -} - -@end - -#pragma mark GRPCChannelPool +static GRPCChannelPool *gChannelPool; +static dispatch_once_t gInitChannelPool; @implementation GRPCChannelPool { NSMutableDictionary *_channelPool; } ++ (nullable instancetype)sharedInstance { + dispatch_once(&gInitChannelPool, ^{ + gChannelPool = [[GRPCChannelPool alloc] init]; + if (gChannelPool == nil) { + [NSException raise:NSMallocException format:@"Cannot initialize global channel pool."]; + } + }); + return gChannelPool; +} + - (instancetype)init { if ((self = [super init])) { _channelPool = [NSMutableDictionary dictionary]; @@ -187,61 +63,56 @@ extern const char *kCFStreamVarName; return self; } -- (void)dealloc { - [GRPCConnectivityMonitor unregisterObserver:self]; +- (GRPCChannel *)channelWithHost:(NSString *)host + callOptions:(GRPCCallOptions *)callOptions { + return [self channelWithHost:host + callOptions:callOptions + destroyDelay:0]; } -- (GRPCChannel *)channelWithConfiguration:(GRPCChannelConfiguration *)configuration { - NSAssert(configuration != nil, @"Must has a configuration"); +- (GRPCChannel *)channelWithHost:(NSString *)host + callOptions:(GRPCCallOptions *)callOptions + destroyDelay:(NSTimeInterval)destroyDelay { + NSAssert(host.length > 0, @"Host must not be empty."); + NSAssert(callOptions != nil, @"callOptions must not be empty."); GRPCChannel *channel; + GRPCChannelConfiguration *configuration = + [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; @synchronized(self) { - if ([_channelPool objectForKey:configuration]) { - channel = _channelPool[configuration]; - [channel ref]; - } else { - channel = [GRPCChannel createChannelWithConfiguration:configuration]; - if (channel != nil) { - _channelPool[configuration] = channel; + channel = _channelPool[configuration]; + if (channel == nil || channel.disconnected) { + if (destroyDelay == 0) { + channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration]; + } else { + channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration destroyDelay:destroyDelay]; } + _channelPool[configuration] = channel; } } return channel; } -- (void)removeChannel:(GRPCChannel *)channel { - @synchronized(self) { - __block GRPCChannelConfiguration *keyToDelete = nil; - [_channelPool - enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration *_Nonnull key, - GRPCChannel *_Nonnull obj, BOOL *_Nonnull stop) { - if (obj == channel) { - keyToDelete = key; - *stop = YES; - } - }]; - [self->_channelPool removeObjectForKey:keyToDelete]; - } -} -- (void)removeAllChannels { - @synchronized(self) { - _channelPool = [NSMutableDictionary dictionary]; - } + ++ (void)closeOpenConnections { + [[GRPCChannelPool sharedInstance] destroyAllChannels]; } -- (void)removeAndCloseAllChannels { +- (void)destroyAllChannels { @synchronized(self) { - [_channelPool - enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration *_Nonnull key, - GRPCChannel *_Nonnull obj, BOOL *_Nonnull stop) { - [obj disconnect]; - }]; + for (id key in _channelPool) { + [_channelPool[key] disconnect]; + } _channelPool = [NSMutableDictionary dictionary]; } } - (void)connectivityChange:(NSNotification *)note { - [self removeAndCloseAllChannels]; + [self destroyAllChannels]; +} + +- (void)dealloc { + [GRPCConnectivityMonitor unregisterObserver:self]; } @end diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 577002e7a85..2358c7bb0a8 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -24,6 +24,7 @@ #include #import "GRPCChannel.h" +#import "GRPCChannelPool.h" #import "GRPCCompletionQueue.h" #import "GRPCHost.h" #import "NSData+GRPC.h" @@ -256,13 +257,21 @@ // consuming too many threads and having contention of multiple calls in a single completion // queue. Currently we use a singleton queue. _queue = [GRPCCompletionQueue completionQueue]; - _channel = [GRPCChannel channelWithHost:host callOptions:callOptions]; - if (_channel == nil) { - NSLog(@"Failed to get a channel for the host."); - return nil; - } - _call = [_channel unmanagedCallWithPath:path completionQueue:_queue callOptions:callOptions]; - if (_call == NULL) { + BOOL disconnected; + do { + _channel = [[GRPCChannelPool sharedInstance] channelWithHost:host callOptions:callOptions]; + if (_channel == nil) { + NSLog(@"Failed to get a channel for the host."); + return nil; + } + _call = [_channel unmanagedCallWithPath:path + completionQueue:_queue + callOptions:callOptions + disconnected:&disconnected]; + // Try create another channel if the current channel is disconnected (due to idleness or + // connectivity monitor disconnection). + } while (_call == NULL && disconnected); + if (_call == nil) { NSLog(@"Failed to create a call."); return nil; } @@ -317,6 +326,7 @@ - (void)dealloc { if (_call) { grpc_call_unref(_call); + [_channel unref]; } [_channel unref]; _channel = nil; diff --git a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m index 5c3f0edba0b..d684db545e9 100644 --- a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m +++ b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m @@ -20,6 +20,7 @@ #import "../../GRPCClient/private/GRPCChannel.h" #import "../../GRPCClient/private/GRPCChannelPool.h" +#import "../../GRPCClient/private/GRPCCompletionQueue.h" #define TEST_TIMEOUT 32 @@ -35,92 +36,104 @@ NSString *kDummyHost = @"dummy.host"; grpc_init(); } -- (void)testCreateChannel { +- (void)testChannelPooling { NSString *kDummyHost = @"dummy.host"; + NSString *kDummyHost2 = @"dummy.host2"; + GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; - options1.transportType = GRPCTransportTypeInsecure; GRPCCallOptions *options2 = [options1 copy]; - GRPCChannelConfiguration *config1 = - [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; - GRPCChannelConfiguration *config2 = - [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options2]; - GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; - - GRPCChannel *channel1 = [pool channelWithConfiguration:config1]; - GRPCChannel *channel2 = [pool channelWithConfiguration:config2]; + GRPCMutableCallOptions *options3 = [options2 mutableCopy]; + options3.transportType = GRPCTransportTypeInsecure; + + GRPCChannelPool *pool = [GRPCChannelPool sharedInstance]; + + GRPCChannel *channel1 = [pool channelWithHost:kDummyHost + callOptions:options1]; + GRPCChannel *channel2 = [pool channelWithHost:kDummyHost + callOptions:options2]; + GRPCChannel *channel3 = [pool channelWithHost:kDummyHost2 + callOptions:options1]; + GRPCChannel *channel4 = [pool channelWithHost:kDummyHost + callOptions:options3]; XCTAssertEqual(channel1, channel2); + XCTAssertNotEqual(channel1, channel3); + XCTAssertNotEqual(channel1, channel4); + XCTAssertNotEqual(channel3, channel4); } -- (void)testChannelRemove { - GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; - options1.transportType = GRPCTransportTypeInsecure; - GRPCChannelConfiguration *config1 = - [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; - GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; - GRPCChannel *channel1 = [pool channelWithConfiguration:config1]; - [pool removeChannel:channel1]; - GRPCChannel *channel2 = [pool channelWithConfiguration:config1]; - XCTAssertNotEqual(channel1, channel2); -} - -extern NSTimeInterval kChannelDestroyDelay; +- (void)testDestroyAllChannels { + NSString *kDummyHost = @"dummy.host"; -- (void)testChannelTimeoutCancel { - NSTimeInterval kOriginalInterval = kChannelDestroyDelay; - kChannelDestroyDelay = 3.0; - GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; - options1.transportType = GRPCTransportTypeInsecure; - GRPCChannelConfiguration *config1 = - [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; - GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; - GRPCChannel *channel1 = [pool channelWithConfiguration:config1]; - [channel1 unref]; - sleep(1); - GRPCChannel *channel2 = [pool channelWithConfiguration:config1]; - XCTAssertEqual(channel1, channel2); - sleep((int)kChannelDestroyDelay + 2); - GRPCChannel *channel3 = [pool channelWithConfiguration:config1]; - XCTAssertEqual(channel1, channel3); - kChannelDestroyDelay = kOriginalInterval; + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + GRPCChannelPool *pool = [GRPCChannelPool sharedInstance]; + GRPCChannel *channel = [pool channelWithHost:kDummyHost + callOptions:options]; + grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" + completionQueue:[GRPCCompletionQueue completionQueue] + callOptions:options + disconnected:nil]; + [pool destroyAllChannels]; + XCTAssertTrue(channel.disconnected); + GRPCChannel *channel2 = [pool channelWithHost:kDummyHost + callOptions:options]; + XCTAssertNotEqual(channel, channel2); + grpc_call_unref(call); } -- (void)testChannelDisconnect { +- (void)testGetChannelBeforeChannelTimedDisconnection { NSString *kDummyHost = @"dummy.host"; - GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; - options1.transportType = GRPCTransportTypeInsecure; - GRPCCallOptions *options2 = [options1 copy]; - GRPCChannelConfiguration *config1 = - [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; - GRPCChannelConfiguration *config2 = - [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options2]; - GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; - - GRPCChannel *channel1 = [pool channelWithConfiguration:config1]; - [pool removeAndCloseAllChannels]; - GRPCChannel *channel2 = [pool channelWithConfiguration:config2]; - XCTAssertNotEqual(channel1, channel2); + const NSTimeInterval kDestroyDelay = 1; + + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + GRPCChannelPool *pool = [GRPCChannelPool sharedInstance]; + GRPCChannel *channel = [pool channelWithHost:kDummyHost + callOptions:options + destroyDelay:kDestroyDelay]; + grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" + completionQueue:[GRPCCompletionQueue completionQueue] + callOptions:options + disconnected:nil]; + grpc_call_unref(call); + [channel unref]; + + // Test that we can still get the channel at this time + GRPCChannel *channel2 = [pool channelWithHost:kDummyHost + callOptions:options + destroyDelay:kDestroyDelay]; + XCTAssertEqual(channel, channel2); + call = [channel2 unmanagedCallWithPath:@"dummy.path" + completionQueue:[GRPCCompletionQueue completionQueue] + callOptions:options + disconnected:nil]; + + // Test that after the destroy delay, the channel is still alive + sleep(kDestroyDelay + 1); + XCTAssertFalse(channel.disconnected); } -- (void)testClearChannels { - GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; - options1.transportType = GRPCTransportTypeInsecure; - GRPCMutableCallOptions *options2 = [[GRPCMutableCallOptions alloc] init]; - options2.transportType = GRPCTransportTypeChttp2BoringSSL; - GRPCChannelConfiguration *config1 = - [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options1]; - GRPCChannelConfiguration *config2 = - [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options2]; - GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; - - GRPCChannel *channel1 = [pool channelWithConfiguration:config1]; - GRPCChannel *channel2 = [pool channelWithConfiguration:config2]; - XCTAssertNotEqual(channel1, channel2); - - [pool removeAndCloseAllChannels]; - GRPCChannel *channel3 = [pool channelWithConfiguration:config1]; - GRPCChannel *channel4 = [pool channelWithConfiguration:config2]; - XCTAssertNotEqual(channel1, channel3); - XCTAssertNotEqual(channel2, channel4); +- (void)testGetChannelAfterChannelTimedDisconnection { + NSString *kDummyHost = @"dummy.host"; + const NSTimeInterval kDestroyDelay = 1; + + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + GRPCChannelPool *pool = [GRPCChannelPool sharedInstance]; + GRPCChannel *channel = [pool channelWithHost:kDummyHost + callOptions:options + destroyDelay:kDestroyDelay]; + grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" + completionQueue:[GRPCCompletionQueue completionQueue] + callOptions:options + disconnected:nil]; + grpc_call_unref(call); + [channel unref]; + + sleep(kDestroyDelay + 1); + + // Test that we get new channel to the same host and with the same callOptions + GRPCChannel *channel2 = [pool channelWithHost:kDummyHost + callOptions:options + destroyDelay:kDestroyDelay]; + XCTAssertNotEqual(channel, channel2); } @end diff --git a/src/objective-c/tests/ChannelTests/ChannelTests.m b/src/objective-c/tests/ChannelTests/ChannelTests.m index 64c3356b13f..27e76d41799 100644 --- a/src/objective-c/tests/ChannelTests/ChannelTests.m +++ b/src/objective-c/tests/ChannelTests/ChannelTests.m @@ -20,6 +20,7 @@ #import "../../GRPCClient/GRPCCallOptions.h" #import "../../GRPCClient/private/GRPCChannel.h" +#import "../../GRPCClient/private/GRPCCompletionQueue.h" @interface ChannelTests : XCTestCase @@ -31,63 +32,51 @@ grpc_init(); } -- (void)testSameConfiguration { - NSString *host = @"grpc-test.sandbox.googleapis.com"; - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.userAgentPrefix = @"TestUAPrefix"; - NSMutableDictionary *args = [NSMutableDictionary new]; - args[@"abc"] = @"xyz"; - options.additionalChannelArgs = [args copy]; - GRPCChannel *channel1 = [GRPCChannel channelWithHost:host callOptions:options]; - GRPCChannel *channel2 = [GRPCChannel channelWithHost:host callOptions:options]; - XCTAssertEqual(channel1, channel2); - GRPCMutableCallOptions *options2 = [options mutableCopy]; - options2.additionalChannelArgs = [args copy]; - GRPCChannel *channel3 = [GRPCChannel channelWithHost:host callOptions:options2]; - XCTAssertEqual(channel1, channel3); -} +- (void)testTimedDisconnection { + NSString * const kHost = @"grpc-test.sandbox.googleapis.com"; + const NSTimeInterval kDestroyDelay = 1; + GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; + GRPCChannelConfiguration *configuration = [[GRPCChannelConfiguration alloc] initWithHost:kHost callOptions:options]; + GRPCChannel *channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration + destroyDelay:kDestroyDelay]; + BOOL disconnected; + grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" + completionQueue:[GRPCCompletionQueue completionQueue] + callOptions:options + disconnected:&disconnected]; + XCTAssertFalse(disconnected); + grpc_call_unref(call); + [channel unref]; + XCTAssertFalse(channel.disconnected, @"Channel is pre-maturely disconnected."); + sleep(kDestroyDelay + 1); + XCTAssertTrue(channel.disconnected, @"Channel is not disconnected after delay."); -- (void)testDifferentHost { - NSString *host1 = @"grpc-test.sandbox.googleapis.com"; - NSString *host2 = @"grpc-test2.sandbox.googleapis.com"; - NSString *host3 = @"http://grpc-test.sandbox.googleapis.com"; - NSString *host4 = @"dns://grpc-test.sandbox.googleapis.com"; - NSString *host5 = @"grpc-test.sandbox.googleapis.com:80"; - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - options.userAgentPrefix = @"TestUAPrefix"; - NSMutableDictionary *args = [NSMutableDictionary new]; - args[@"abc"] = @"xyz"; - options.additionalChannelArgs = [args copy]; - GRPCChannel *channel1 = [GRPCChannel channelWithHost:host1 callOptions:options]; - GRPCChannel *channel2 = [GRPCChannel channelWithHost:host2 callOptions:options]; - GRPCChannel *channel3 = [GRPCChannel channelWithHost:host3 callOptions:options]; - GRPCChannel *channel4 = [GRPCChannel channelWithHost:host4 callOptions:options]; - GRPCChannel *channel5 = [GRPCChannel channelWithHost:host5 callOptions:options]; - XCTAssertNotEqual(channel1, channel2); - XCTAssertNotEqual(channel1, channel3); - XCTAssertNotEqual(channel1, channel4); - XCTAssertNotEqual(channel1, channel5); + // Check another call creation returns null and indicates disconnected. + call = [channel unmanagedCallWithPath:@"dummy.path" + completionQueue:[GRPCCompletionQueue completionQueue] + callOptions:options + disconnected:&disconnected]; + XCTAssert(call == NULL); + XCTAssertTrue(disconnected); } -- (void)testDifferentChannelParameters { - NSString *host = @"grpc-test.sandbox.googleapis.com"; - GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; - options1.transportType = GRPCTransportTypeChttp2BoringSSL; - NSMutableDictionary *args = [NSMutableDictionary new]; - args[@"abc"] = @"xyz"; - options1.additionalChannelArgs = [args copy]; - GRPCMutableCallOptions *options2 = [[GRPCMutableCallOptions alloc] init]; - options2.transportType = GRPCTransportTypeInsecure; - options2.additionalChannelArgs = [args copy]; - GRPCMutableCallOptions *options3 = [[GRPCMutableCallOptions alloc] init]; - options3.transportType = GRPCTransportTypeChttp2BoringSSL; - args[@"def"] = @"uvw"; - options3.additionalChannelArgs = [args copy]; - GRPCChannel *channel1 = [GRPCChannel channelWithHost:host callOptions:options1]; - GRPCChannel *channel2 = [GRPCChannel channelWithHost:host callOptions:options2]; - GRPCChannel *channel3 = [GRPCChannel channelWithHost:host callOptions:options3]; - XCTAssertNotEqual(channel1, channel2); - XCTAssertNotEqual(channel1, channel3); +- (void)testForceDisconnection { + NSString * const kHost = @"grpc-test.sandbox.googleapis.com"; + const NSTimeInterval kDestroyDelay = 1; + GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; + GRPCChannelConfiguration *configuration = [[GRPCChannelConfiguration alloc] initWithHost:kHost callOptions:options]; + GRPCChannel *channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration + destroyDelay:kDestroyDelay]; + grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" + completionQueue:[GRPCCompletionQueue completionQueue] + callOptions:options + disconnected:nil]; + grpc_call_unref(call); + [channel disconnect]; + XCTAssertTrue(channel.disconnected, @"Channel is not disconnected."); + + // Test calling another unref here will not crash + [channel unref]; } @end From 861e7ce452866311ee2746d7b7a9fd1d11b84087 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 9 Nov 2018 07:51:38 -0800 Subject: [PATCH 166/375] nit fixes --- src/objective-c/GRPCClient/private/GRPCChannel.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 298b6605d1f..4f26b349b49 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -34,7 +34,7 @@ #import /** When all calls of a channel are destroyed, destroy the channel after this much seconds. */ -NSTimeInterval kDefaultChannelDestroyDelay = 30; +static const NSTimeInterval kDefaultChannelDestroyDelay = 30; @implementation GRPCChannelConfiguration @@ -295,6 +295,7 @@ NSTimeInterval kDefaultChannelDestroyDelay = 30; NSDate *now = [NSDate date]; self->_lastDispatch = now; dispatch_after(delay, self->_dispatchQueue, ^{ + // Timed disconnection. if (self->_lastDispatch == now) { grpc_channel_destroy(self->_unmanagedChannel); self->_unmanagedChannel = NULL; From 33022c9172bd3cf52c9aa3416ce9c69d9f3c6494 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 9 Nov 2018 10:23:05 -0800 Subject: [PATCH 167/375] Introduce GRPCAssert --- src/objective-c/GRPCClient/GRPCCall.m | 47 +++++++------------ .../GRPCClient/private/GRPCChannel.m | 21 +++++---- .../GRPCClient/private/GRPCChannelPool.m | 9 ++-- src/objective-c/GRPCClient/private/GRPCHost.m | 3 +- .../private/GRPCSecureChannelFactory.m | 4 +- .../GRPCClient/private/utilities.h | 35 ++++++++++++++ 6 files changed, 72 insertions(+), 47 deletions(-) create mode 100644 src/objective-c/GRPCClient/private/utilities.h diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 9b9b4f95471..3d06aa929bb 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -35,6 +35,7 @@ #import "private/NSData+GRPC.h" #import "private/NSDictionary+GRPC.h" #import "private/NSError+GRPC.h" +#import "private/utilities.h" // At most 6 ops can be in an op batch for a client: SEND_INITIAL_METADATA, // SEND_MESSAGE, SEND_CLOSE_FROM_CLIENT, RECV_INITIAL_METADATA, RECV_MESSAGE, @@ -67,7 +68,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; @implementation GRPCRequestOptions - (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety { - NSAssert(host.length != 0 && path.length != 0, @"Host and Path cannot be empty"); + GRPCAssert(host.length != 0 && path.length != 0, NSInvalidArgumentException, @"Host and Path cannot be empty"); if ((self = [super init])) { _host = [host copy]; _path = [path copy]; @@ -114,15 +115,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)responseHandler callOptions:(GRPCCallOptions *_Nullable)callOptions { - if (requestOptions.host.length == 0 || requestOptions.path.length == 0) { - [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; - } - if (requestOptions.safety > GRPCCallSafetyCacheableRequest) { - [NSException raise:NSInvalidArgumentException format:@"Invalid call safety value."]; - } - if (responseHandler == nil) { - [NSException raise:NSInvalidArgumentException format:@"Response handler required."]; - } + GRPCAssert(requestOptions.host.length != 0 && requestOptions.path.length != 0, NSInvalidArgumentException, @"Neither host nor path can be nil."); + GRPCAssert(requestOptions.safety <= GRPCCallSafetyCacheableRequest, NSInvalidArgumentException, @"Invalid call safety value."); + GRPCAssert(responseHandler != nil, NSInvalidArgumentException, @"Response handler required."); if ((self = [super init])) { _requestOptions = [requestOptions copy]; @@ -159,8 +154,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)start { dispatch_async(_dispatchQueue, ^{ - NSAssert(!self->_started, @"Call already started."); - NSAssert(!self->_canceled, @"Call already canceled."); + GRPCAssert(!self->_started, NSInternalInconsistencyException, @"Call already started."); + GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call already canceled."); self->_started = YES; if (!self->_callOptions) { self->_callOptions = [[GRPCCallOptions alloc] init]; @@ -216,7 +211,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)cancel { dispatch_async(_dispatchQueue, ^{ - NSAssert(!self->_canceled, @"Call already canceled."); + GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call already canceled."); if (self->_call) { [self->_call cancel]; self->_call = nil; @@ -244,8 +239,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)writeData:(NSData *)data { dispatch_async(_dispatchQueue, ^{ - NSAssert(!self->_canceled, @"Call arleady canceled."); - NSAssert(!self->_finished, @"Call is half-closed before sending data."); + GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call arleady canceled."); + GRPCAssert(!self->_finished, NSInternalInconsistencyException, @"Call is half-closed before sending data."); if (self->_call) { [self->_pipe writeValue:data]; } @@ -254,9 +249,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)finish { dispatch_async(_dispatchQueue, ^{ - NSAssert(self->_started, @"Call not started."); - NSAssert(!self->_canceled, @"Call arleady canceled."); - NSAssert(!self->_finished, @"Call already half-closed."); + GRPCAssert(self->_started, NSInternalInconsistencyException, @"Call not started."); + GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call arleady canceled."); + GRPCAssert(!self->_finished, NSInternalInconsistencyException, @"Call already half-closed."); if (self->_call) { [self->_pipe writesFinishedWithError:nil]; } @@ -404,16 +399,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; requestsWriter:(GRXWriter *)requestWriter callOptions:(GRPCCallOptions *)callOptions { // Purposely using pointer rather than length ([host length] == 0) for backwards compatibility. - if (!host || !path) { - [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; - } - if (safety > GRPCCallSafetyCacheableRequest) { - [NSException raise:NSInvalidArgumentException format:@"Invalid call safety value."]; - } - if (requestWriter.state != GRXWriterStateNotStarted) { - [NSException raise:NSInvalidArgumentException - format:@"The requests writer can't be already started."]; - } + GRPCAssert(host && path, NSInvalidArgumentException, @"Neither host nor path can be nil."); + GRPCAssert(safety <= GRPCCallSafetyCacheableRequest, NSInvalidArgumentException, @"Invalid call safety value."); + GRPCAssert(requestWriter.state == GRXWriterStateNotStarted, NSInvalidArgumentException, @"The requests writer can't be already started."); if ((self = [super init])) { _host = [host copy]; _path = [path copy]; @@ -798,8 +786,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; _callOptions = callOptions; } - NSAssert(_callOptions.authTokenProvider == nil || _callOptions.oauth2AccessToken == nil, - @"authTokenProvider and oauth2AccessToken cannot be set at the same time"); + GRPCAssert(_callOptions.authTokenProvider == nil || _callOptions.oauth2AccessToken == nil, NSInvalidArgumentException, @"authTokenProvider and oauth2AccessToken cannot be set at the same time"); if (_callOptions.authTokenProvider != nil) { @synchronized(self) { self.isWaitingForToken = YES; diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 4f26b349b49..7d0baa91ee6 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -28,6 +28,7 @@ #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" #import "version.h" +#import "utilities.h" #import "../internal/GRPCCallOptions+Internal.h" #import @@ -39,8 +40,8 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; @implementation GRPCChannelConfiguration - (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { - NSAssert(host.length, @"Host must not be empty."); - NSAssert(callOptions, @"callOptions must not be empty."); + GRPCAssert(host.length, NSInvalidArgumentException, @"Host must not be empty."); + GRPCAssert(callOptions != nil, NSInvalidArgumentException, @"callOptions must not be empty."); if ((self = [super init])) { _host = [host copy]; _callOptions = [callOptions copy]; @@ -192,8 +193,8 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; - (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration destroyDelay:(NSTimeInterval)destroyDelay { - NSAssert(channelConfiguration, @"channelConfiguration must not be empty."); - NSAssert(destroyDelay > 0, @"destroyDelay must be greater than 0."); + GRPCAssert(channelConfiguration != nil, NSInvalidArgumentException, @"channelConfiguration must not be empty."); + GRPCAssert(destroyDelay > 0, NSInvalidArgumentException, @"destroyDelay must be greater than 0."); if ((self = [super init])) { _configuration = [channelConfiguration copy]; if (@available(iOS 8.0, *)) { @@ -206,7 +207,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; // Create gRPC core channel object. NSString *host = channelConfiguration.host; - NSAssert(host.length != 0, @"host cannot be nil"); + GRPCAssert(host.length != 0, NSInvalidArgumentException, @"host cannot be nil"); NSDictionary *channelArgs; if (channelConfiguration.callOptions.additionalChannelArgs.count != 0) { NSMutableDictionary *args = [channelConfiguration.channelArgs mutableCopy]; @@ -231,21 +232,21 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; completionQueue:(GRPCCompletionQueue *)queue callOptions:(GRPCCallOptions *)callOptions disconnected:(BOOL *)disconnected { - NSAssert(path.length, @"path must not be empty."); - NSAssert(queue, @"completionQueue must not be empty."); - NSAssert(callOptions, @"callOptions must not be empty."); + GRPCAssert(path.length, NSInvalidArgumentException, @"path must not be empty."); + GRPCAssert(queue, NSInvalidArgumentException, @"completionQueue must not be empty."); + GRPCAssert(callOptions, NSInvalidArgumentException, @"callOptions must not be empty."); __block BOOL isDisconnected = NO; __block grpc_call *call = NULL; dispatch_sync(_dispatchQueue, ^{ if (self->_disconnected) { isDisconnected = YES; } else { - NSAssert(self->_unmanagedChannel != NULL, @"Invalid channel."); + GRPCAssert(self->_unmanagedChannel != NULL, NSInvalidArgumentException, @"Invalid channel."); NSString *serverAuthority = callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; NSTimeInterval timeout = callOptions.timeout; - NSAssert(timeout >= 0, @"Invalid timeout"); + GRPCAssert(timeout >= 0, NSInvalidArgumentException, @"Invalid timeout"); grpc_slice host_slice = grpc_empty_slice(); if (serverAuthority) { host_slice = grpc_slice_from_copied_string(serverAuthority.UTF8String); diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 98c1634bc8b..8a3b5edfa12 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -27,6 +27,7 @@ #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" #import "version.h" +#import "utilities.h" #import #include @@ -43,9 +44,7 @@ static dispatch_once_t gInitChannelPool; + (nullable instancetype)sharedInstance { dispatch_once(&gInitChannelPool, ^{ gChannelPool = [[GRPCChannelPool alloc] init]; - if (gChannelPool == nil) { - [NSException raise:NSMallocException format:@"Cannot initialize global channel pool."]; - } + GRPCAssert(gChannelPool != nil, NSMallocException, @"Cannot initialize global channel pool."); }); return gChannelPool; } @@ -73,8 +72,8 @@ static dispatch_once_t gInitChannelPool; - (GRPCChannel *)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions destroyDelay:(NSTimeInterval)destroyDelay { - NSAssert(host.length > 0, @"Host must not be empty."); - NSAssert(callOptions != nil, @"callOptions must not be empty."); + GRPCAssert(host.length > 0, NSInvalidArgumentException, @"Host must not be empty."); + GRPCAssert(callOptions != nil, NSInvalidArgumentException, @"callOptions must not be empty."); GRPCChannel *channel; GRPCChannelConfiguration *configuration = [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index a67162c1014..14d07e949b7 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -33,6 +33,7 @@ #import "GRPCSecureChannelFactory.h" #import "NSDictionary+GRPC.h" #import "version.h" +#import "utilities.h" NS_ASSUME_NONNULL_BEGIN @@ -121,7 +122,7 @@ static NSMutableDictionary *gHostCache; if (_transportType == GRPCTransportTypeInsecure) { options.transportType = GRPCTransportTypeInsecure; } else { - NSAssert(_transportType == GRPCTransportTypeDefault, @"Invalid transport type"); + GRPCAssert(_transportType == GRPCTransportTypeDefault, NSInvalidArgumentException, @"Invalid transport type"); options.transportType = GRPCTransportTypeCronet; } } else diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 1f6458c5247..3079394ed8a 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -22,6 +22,7 @@ #import "ChannelArgsUtil.h" #import "GRPCChannel.h" +#import "utilities.h" NS_ASSUME_NONNULL_BEGIN @@ -82,8 +83,9 @@ NS_ASSUME_NONNULL_BEGIN if (errorPtr) { *errorPtr = defaultRootsError; } - NSAssert( + GRPCAssertWithArgument( defaultRootsASCII, + NSObjectNotAvailableException, @"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 " diff --git a/src/objective-c/GRPCClient/private/utilities.h b/src/objective-c/GRPCClient/private/utilities.h new file mode 100644 index 00000000000..c664e8bf9df --- /dev/null +++ b/src/objective-c/GRPCClient/private/utilities.h @@ -0,0 +1,35 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import + +/** Raise exception when condition not met. Disregard NS_BLOCK_ASSERTIONS. */ +#define GRPCAssert(condition, errorType, errorString) \ +do { \ +if (!(condition)) { \ +[NSException raise:(errorType) format:(errorString)]; \ +} \ +} while (0) + +/** The same as GRPCAssert but allows arguments to be put in the raised string. */ +#define GRPCAssertWithArgument(condition, errorType, errorFormat, ...) \ + do { \ + if (!(condition)) { \ + [NSException raise:(errorType) format:(errorFormat), __VA_ARGS__]; \ + } \ + } while (0) From 2895ee9b6a63c19ebbd6c188ab475f0a6e7f0ba5 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 9 Nov 2018 11:06:46 -0800 Subject: [PATCH 168/375] clang-format --- src/objective-c/GRPCClient/GRPCCall.m | 22 +++++--- .../GRPCClient/private/GRPCChannel.h | 11 ++-- .../GRPCClient/private/GRPCChannel.m | 55 ++++++++++--------- .../GRPCClient/private/GRPCChannelPool.h | 3 +- .../GRPCClient/private/GRPCChannelPool.m | 16 ++---- src/objective-c/GRPCClient/private/GRPCHost.m | 5 +- .../private/GRPCSecureChannelFactory.m | 3 +- .../GRPCClient/private/utilities.h | 27 ++++----- 8 files changed, 75 insertions(+), 67 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 3d06aa929bb..5e3491dafaa 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -68,7 +68,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; @implementation GRPCRequestOptions - (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety { - GRPCAssert(host.length != 0 && path.length != 0, NSInvalidArgumentException, @"Host and Path cannot be empty"); + GRPCAssert(host.length != 0 && path.length != 0, NSInvalidArgumentException, + @"Host and Path cannot be empty"); if ((self = [super init])) { _host = [host copy]; _path = [path copy]; @@ -115,8 +116,10 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)responseHandler callOptions:(GRPCCallOptions *_Nullable)callOptions { - GRPCAssert(requestOptions.host.length != 0 && requestOptions.path.length != 0, NSInvalidArgumentException, @"Neither host nor path can be nil."); - GRPCAssert(requestOptions.safety <= GRPCCallSafetyCacheableRequest, NSInvalidArgumentException, @"Invalid call safety value."); + GRPCAssert(requestOptions.host.length != 0 && requestOptions.path.length != 0, + NSInvalidArgumentException, @"Neither host nor path can be nil."); + GRPCAssert(requestOptions.safety <= GRPCCallSafetyCacheableRequest, NSInvalidArgumentException, + @"Invalid call safety value."); GRPCAssert(responseHandler != nil, NSInvalidArgumentException, @"Response handler required."); if ((self = [super init])) { @@ -240,7 +243,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)writeData:(NSData *)data { dispatch_async(_dispatchQueue, ^{ GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call arleady canceled."); - GRPCAssert(!self->_finished, NSInternalInconsistencyException, @"Call is half-closed before sending data."); + GRPCAssert(!self->_finished, NSInternalInconsistencyException, + @"Call is half-closed before sending data."); if (self->_call) { [self->_pipe writeValue:data]; } @@ -400,8 +404,10 @@ const char *kCFStreamVarName = "grpc_cfstream"; callOptions:(GRPCCallOptions *)callOptions { // Purposely using pointer rather than length ([host length] == 0) for backwards compatibility. GRPCAssert(host && path, NSInvalidArgumentException, @"Neither host nor path can be nil."); - GRPCAssert(safety <= GRPCCallSafetyCacheableRequest, NSInvalidArgumentException, @"Invalid call safety value."); - GRPCAssert(requestWriter.state == GRXWriterStateNotStarted, NSInvalidArgumentException, @"The requests writer can't be already started."); + GRPCAssert(safety <= GRPCCallSafetyCacheableRequest, NSInvalidArgumentException, + @"Invalid call safety value."); + GRPCAssert(requestWriter.state == GRXWriterStateNotStarted, NSInvalidArgumentException, + @"The requests writer can't be already started."); if ((self = [super init])) { _host = [host copy]; _path = [path copy]; @@ -786,7 +792,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; _callOptions = callOptions; } - GRPCAssert(_callOptions.authTokenProvider == nil || _callOptions.oauth2AccessToken == nil, NSInvalidArgumentException, @"authTokenProvider and oauth2AccessToken cannot be set at the same time"); + GRPCAssert(_callOptions.authTokenProvider == nil || _callOptions.oauth2AccessToken == nil, + NSInvalidArgumentException, + @"authTokenProvider and oauth2AccessToken cannot be set at the same time"); if (_callOptions.authTokenProvider != nil) { @synchronized(self) { self.isWaitingForToken = YES; diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index bbe0ba53904..6c58f4f387f 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -64,14 +64,17 @@ NS_ASSUME_NONNULL_BEGIN * Create a channel with remote \a host and signature \a channelConfigurations. Destroy delay is * defaulted to 30 seconds. */ -- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration; +- (nullable instancetype)initWithChannelConfiguration: + (GRPCChannelConfiguration *)channelConfiguration; /** * Create a channel with remote \a host, signature \a channelConfigurations, and destroy delay of * \a destroyDelay. */ -- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration - destroyDelay:(NSTimeInterval)destroyDelay NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithChannelConfiguration: + (GRPCChannelConfiguration *)channelConfiguration + destroyDelay:(NSTimeInterval)destroyDelay + NS_DESIGNATED_INITIALIZER; /** * Create a grpc core call object from this channel. The channel's refcount is added by 1. If no @@ -82,7 +85,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue callOptions:(GRPCCallOptions *)callOptions - disconnected:(BOOL * _Nullable)disconnected; + disconnected:(BOOL *_Nullable)disconnected; /** * Unref the channel when a call is done. It also decreases the channel's refcount. If the refcount diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 7d0baa91ee6..fc0448bb962 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -20,6 +20,7 @@ #include +#import "../internal/GRPCCallOptions+Internal.h" #import "ChannelArgsUtil.h" #import "GRPCChannelFactory.h" #import "GRPCChannelPool.h" @@ -27,9 +28,8 @@ #import "GRPCCronetChannelFactory.h" #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" -#import "version.h" #import "utilities.h" -#import "../internal/GRPCCallOptions+Internal.h" +#import "version.h" #import #import @@ -60,10 +60,10 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; if (![GRPCCall isUsingCronet]) { #endif factory = [GRPCSecureChannelFactory - factoryWithPEMRootCertificates:_callOptions.PEMRootCertificates - privateKey:_callOptions.PEMPrivateKey - certChain:_callOptions.PEMCertChain - error:&error]; + factoryWithPEMRootCertificates:_callOptions.PEMRootCertificates + privateKey:_callOptions.PEMPrivateKey + certChain:_callOptions.PEMCertChain + error:&error]; if (factory == nil) { NSLog(@"Error creating secure channel factory: %@", error); } @@ -86,7 +86,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; NSString *userAgentPrefix = _callOptions.userAgentPrefix; if (userAgentPrefix) { args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = - [_callOptions.userAgentPrefix stringByAppendingFormat:@" %@", userAgent]; + [_callOptions.userAgentPrefix stringByAppendingFormat:@" %@", userAgent]; } else { args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = userAgent; } @@ -98,19 +98,19 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; if (_callOptions.responseSizeLimit) { args[@GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH] = - [NSNumber numberWithUnsignedInteger:_callOptions.responseSizeLimit]; + [NSNumber numberWithUnsignedInteger:_callOptions.responseSizeLimit]; } if (_callOptions.compressionAlgorithm != GRPC_COMPRESS_NONE) { args[@GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM] = - [NSNumber numberWithInt:_callOptions.compressionAlgorithm]; + [NSNumber numberWithInt:_callOptions.compressionAlgorithm]; } if (_callOptions.keepaliveInterval != 0) { args[@GRPC_ARG_KEEPALIVE_TIME_MS] = - [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.keepaliveInterval * 1000)]; + [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.keepaliveInterval * 1000)]; args[@GRPC_ARG_KEEPALIVE_TIMEOUT_MS] = - [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.keepaliveTimeout * 1000)]; + [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.keepaliveTimeout * 1000)]; } if (_callOptions.retryEnabled == NO) { @@ -119,15 +119,15 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; if (_callOptions.connectMinTimeout > 0) { args[@GRPC_ARG_MIN_RECONNECT_BACKOFF_MS] = - [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectMinTimeout * 1000)]; + [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectMinTimeout * 1000)]; } if (_callOptions.connectInitialBackoff > 0) { args[@GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS] = [NSNumber - numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectInitialBackoff * 1000)]; + numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectInitialBackoff * 1000)]; } if (_callOptions.connectMaxBackoff > 0) { args[@GRPC_ARG_MAX_RECONNECT_BACKOFF_MS] = - [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectMaxBackoff * 1000)]; + [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.connectMaxBackoff * 1000)]; } if (_callOptions.logContext != nil) { @@ -145,7 +145,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; - (nonnull id)copyWithZone:(nullable NSZone *)zone { GRPCChannelConfiguration *newConfig = - [[GRPCChannelConfiguration alloc] initWithHost:_host callOptions:_callOptions]; + [[GRPCChannelConfiguration alloc] initWithHost:_host callOptions:_callOptions]; return newConfig; } @@ -172,8 +172,6 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; @end - - @implementation GRPCChannel { GRPCChannelConfiguration *_configuration; @@ -186,21 +184,24 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } @synthesize disconnected = _disconnected; -- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration { +- (nullable instancetype)initWithChannelConfiguration: + (GRPCChannelConfiguration *)channelConfiguration { return [self initWithChannelConfiguration:channelConfiguration destroyDelay:kDefaultChannelDestroyDelay]; } -- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration +- (nullable instancetype)initWithChannelConfiguration: + (GRPCChannelConfiguration *)channelConfiguration destroyDelay:(NSTimeInterval)destroyDelay { - GRPCAssert(channelConfiguration != nil, NSInvalidArgumentException, @"channelConfiguration must not be empty."); + GRPCAssert(channelConfiguration != nil, NSInvalidArgumentException, + @"channelConfiguration must not be empty."); GRPCAssert(destroyDelay > 0, NSInvalidArgumentException, @"destroyDelay must be greater than 0."); if ((self = [super init])) { _configuration = [channelConfiguration copy]; if (@available(iOS 8.0, *)) { _dispatchQueue = dispatch_queue_create( - NULL, - dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + NULL, + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); } else { _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); } @@ -244,7 +245,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; GRPCAssert(self->_unmanagedChannel != NULL, NSInvalidArgumentException, @"Invalid channel."); NSString *serverAuthority = - callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; + callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; NSTimeInterval timeout = callOptions.timeout; GRPCAssert(timeout >= 0, NSInvalidArgumentException, @"Invalid timeout"); grpc_slice host_slice = grpc_empty_slice(); @@ -253,10 +254,10 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); gpr_timespec deadline_ms = - timeout == 0 - ? gpr_inf_future(GPR_CLOCK_REALTIME) - : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); + timeout == 0 + ? gpr_inf_future(GPR_CLOCK_REALTIME) + : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); call = grpc_channel_create_call(self->_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, queue.unmanagedQueue, path_slice, serverAuthority ? &host_slice : NULL, deadline_ms, NULL); diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 24c0a8df115..48779c44497 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -44,8 +44,7 @@ NS_ASSUME_NONNULL_BEGIN * Return a channel with a particular configuration. If the channel does not exist, execute \a * createChannel then add it in the pool. If the channel exists, increase its reference count. */ -- (GRPCChannel *)channelWithHost:(NSString *)host - callOptions:(GRPCCallOptions *)callOptions; +- (GRPCChannel *)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; /** * This method is deprecated. diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 8a3b5edfa12..85ca527277c 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -26,8 +26,8 @@ #import "GRPCCronetChannelFactory.h" #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" -#import "version.h" #import "utilities.h" +#import "version.h" #import #include @@ -62,11 +62,8 @@ static dispatch_once_t gInitChannelPool; return self; } -- (GRPCChannel *)channelWithHost:(NSString *)host - callOptions:(GRPCCallOptions *)callOptions { - return [self channelWithHost:host - callOptions:callOptions - destroyDelay:0]; +- (GRPCChannel *)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { + return [self channelWithHost:host callOptions:callOptions destroyDelay:0]; } - (GRPCChannel *)channelWithHost:(NSString *)host @@ -76,14 +73,15 @@ static dispatch_once_t gInitChannelPool; GRPCAssert(callOptions != nil, NSInvalidArgumentException, @"callOptions must not be empty."); GRPCChannel *channel; GRPCChannelConfiguration *configuration = - [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; + [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; @synchronized(self) { channel = _channelPool[configuration]; if (channel == nil || channel.disconnected) { if (destroyDelay == 0) { channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration]; } else { - channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration destroyDelay:destroyDelay]; + channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration + destroyDelay:destroyDelay]; } _channelPool[configuration] = channel; } @@ -91,8 +89,6 @@ static dispatch_once_t gInitChannelPool; return channel; } - - + (void)closeOpenConnections { [[GRPCChannelPool sharedInstance] destroyAllChannels]; } diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 14d07e949b7..5fc7427b689 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -32,8 +32,8 @@ #import "GRPCCronetChannelFactory.h" #import "GRPCSecureChannelFactory.h" #import "NSDictionary+GRPC.h" -#import "version.h" #import "utilities.h" +#import "version.h" NS_ASSUME_NONNULL_BEGIN @@ -122,7 +122,8 @@ static NSMutableDictionary *gHostCache; if (_transportType == GRPCTransportTypeInsecure) { options.transportType = GRPCTransportTypeInsecure; } else { - GRPCAssert(_transportType == GRPCTransportTypeDefault, NSInvalidArgumentException, @"Invalid transport type"); + GRPCAssert(_transportType == GRPCTransportTypeDefault, NSInvalidArgumentException, + @"Invalid transport type"); options.transportType = GRPCTransportTypeCronet; } } else diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 3079394ed8a..57bd40d6787 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -84,8 +84,7 @@ NS_ASSUME_NONNULL_BEGIN *errorPtr = defaultRootsError; } GRPCAssertWithArgument( - defaultRootsASCII, - NSObjectNotAvailableException, + defaultRootsASCII, NSObjectNotAvailableException, @"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 " diff --git a/src/objective-c/GRPCClient/private/utilities.h b/src/objective-c/GRPCClient/private/utilities.h index c664e8bf9df..3e51730d637 100644 --- a/src/objective-c/GRPCClient/private/utilities.h +++ b/src/objective-c/GRPCClient/private/utilities.h @@ -19,17 +19,18 @@ #import /** Raise exception when condition not met. Disregard NS_BLOCK_ASSERTIONS. */ -#define GRPCAssert(condition, errorType, errorString) \ -do { \ -if (!(condition)) { \ -[NSException raise:(errorType) format:(errorString)]; \ -} \ -} while (0) +#define GRPCAssert(condition, errorType, errorString) \ + do { \ + if (!(condition)) { \ + [NSException raise:(errorType)format:(errorString)]; \ + } \ + } while (0) -/** The same as GRPCAssert but allows arguments to be put in the raised string. */ -#define GRPCAssertWithArgument(condition, errorType, errorFormat, ...) \ - do { \ - if (!(condition)) { \ - [NSException raise:(errorType) format:(errorFormat), __VA_ARGS__]; \ - } \ - } while (0) +/** The same as GRPCAssert but allows arguments to be put in the raised string. + */ +#define GRPCAssertWithArgument(condition, errorType, errorFormat, ...) \ + do { \ + if (!(condition)) { \ + [NSException raise:(errorType)format:(errorFormat), __VA_ARGS__]; \ + } \ + } while (0) From 699c10386d6f0cbed7364e5a94144f0794f469d5 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 9 Nov 2018 19:43:00 -0800 Subject: [PATCH 169/375] Add method to fail recv msg for hijacked rpcs --- include/grpcpp/impl/codegen/call_op_set.h | 4 +- include/grpcpp/impl/codegen/interceptor.h | 3 + .../grpcpp/impl/codegen/interceptor_common.h | 14 ++- .../grpcpp/impl/codegen/server_interface.h | 2 +- src/cpp/server/server_cc.cc | 4 +- .../client_interceptors_end2end_test.cc | 101 ++++++++++++++++++ 6 files changed, 122 insertions(+), 6 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index b4c34a01c9a..aae8b9d3e37 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -406,7 +406,7 @@ class CallOpRecvMessage { void SetInterceptionHookPoint( InterceptorBatchMethodsImpl* interceptor_methods) { - interceptor_methods->SetRecvMessage(message_); + interceptor_methods->SetRecvMessage(message_, &got_message); } void SetFinishInterceptionHookPoint( @@ -501,7 +501,7 @@ class CallOpGenericRecvMessage { void SetInterceptionHookPoint( InterceptorBatchMethodsImpl* interceptor_methods) { - interceptor_methods->SetRecvMessage(message_); + interceptor_methods->SetRecvMessage(message_, &got_message); } void SetFinishInterceptionHookPoint( diff --git a/include/grpcpp/impl/codegen/interceptor.h b/include/grpcpp/impl/codegen/interceptor.h index e449e44a23b..943376a5451 100644 --- a/include/grpcpp/impl/codegen/interceptor.h +++ b/include/grpcpp/impl/codegen/interceptor.h @@ -118,6 +118,9 @@ class InterceptorBatchMethods { // only interceptors after the current interceptor are created from the // factory objects registered with the channel. virtual std::unique_ptr GetInterceptedChannel() = 0; + + // On a hijacked RPC, an interceptor can decide to fail a RECV MESSAGE op. + virtual void FailHijackedRecvMessage() = 0; }; class Interceptor { diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index d0aa23cb0a0..4c881c783d3 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -134,7 +134,10 @@ class InterceptorBatchMethodsImpl send_trailing_metadata_ = metadata; } - void SetRecvMessage(void* message) { recv_message_ = message; } + void SetRecvMessage(void* message, bool* got_message) { + recv_message_ = message; + got_message_ = got_message; + } void SetRecvInitialMetadata(MetadataMap* map) { recv_initial_metadata_ = map; @@ -157,6 +160,8 @@ class InterceptorBatchMethodsImpl info->channel(), current_interceptor_index_ + 1)); } + void FailHijackedRecvMessage() override { *got_message_ = false; } + // Clears all state void ClearState() { reverse_ = false; @@ -345,6 +350,7 @@ class InterceptorBatchMethodsImpl std::multimap* send_trailing_metadata_ = nullptr; void* recv_message_ = nullptr; + bool* got_message_ = nullptr; MetadataMap* recv_initial_metadata_ = nullptr; @@ -451,6 +457,12 @@ class CancelInterceptorBatchMethods "method which has a Cancel notification"); return std::unique_ptr(nullptr); } + + void FailHijackedRecvMessage() override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call FailHijackedRecvMessage on a " + "method which has a Cancel notification"); + } }; } // namespace internal } // namespace grpc diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h index 55c94f4d2fa..23d1f445b16 100644 --- a/include/grpcpp/impl/codegen/server_interface.h +++ b/include/grpcpp/impl/codegen/server_interface.h @@ -270,7 +270,7 @@ class ServerInterface : public internal::CallHook { /* Set interception point for recv message */ interceptor_methods_.AddInterceptionHookPoint( experimental::InterceptionHookPoints::POST_RECV_MESSAGE); - interceptor_methods_.SetRecvMessage(request_); + interceptor_methods_.SetRecvMessage(request_, nullptr); return RegisteredAsyncRequest::FinalizeResult(tag, status); } diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 7a98bce507a..8b1658dd278 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -280,7 +280,7 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { request_payload_ = nullptr; interceptor_methods_.AddInterceptionHookPoint( experimental::InterceptionHookPoints::POST_RECV_MESSAGE); - interceptor_methods_.SetRecvMessage(request_); + interceptor_methods_.SetRecvMessage(request_, nullptr); } if (interceptor_methods_.RunInterceptors( @@ -447,7 +447,7 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { req_->request_payload_ = nullptr; req_->interceptor_methods_.AddInterceptionHookPoint( experimental::InterceptionHookPoints::POST_RECV_MESSAGE); - req_->interceptor_methods_.SetRecvMessage(req_->request_); + req_->interceptor_methods_.SetRecvMessage(req_->request_, nullptr); } if (req_->interceptor_methods_.RunInterceptors( diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 0b34ec93ae7..b94a3d752e8 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -269,6 +269,92 @@ class HijackingInterceptorMakesAnotherCallFactory } }; +class ServerStreamingRpcHijackingInterceptor + : public experimental::Interceptor { + public: + ServerStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) { + info_ = info; + } + + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + bool hijack = false; + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + auto* map = methods->GetSendInitialMetadata(); + // Check that we can see the test metadata + ASSERT_EQ(map->size(), static_cast(1)); + auto iterator = map->begin(); + EXPECT_EQ("testkey", iterator->first); + EXPECT_EQ("testvalue", iterator->second); + hijack = true; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + EchoRequest req; + auto* buffer = methods->GetSendMessage(); + auto copied_buffer = *buffer; + EXPECT_TRUE( + SerializationTraits::Deserialize(&copied_buffer, &req) + .ok()); + EXPECT_EQ(req.message(), "Hello"); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { + // Got nothing to do here for now + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + bool found = false; + // Check that we received the metadata as an echo + for (const auto& pair : *map) { + found = pair.first.starts_with("testkey") && + pair.second.starts_with("testvalue"); + if (found) break; + } + EXPECT_EQ(found, true); + auto* status = methods->GetRecvStatus(); + EXPECT_EQ(status->ok(), true); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { + if (++count > 10) { + methods->FailHijackedRecvMessage(); + } + EchoResponse* resp = + static_cast(methods->GetRecvMessage()); + resp->set_message("Hello"); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + // insert the metadata that we want + EXPECT_EQ(map->size(), static_cast(0)); + map->insert(std::make_pair("testkey", "testvalue")); + auto* status = methods->GetRecvStatus(); + *status = Status(StatusCode::OK, ""); + } + if (hijack) { + methods->Hijack(); + } else { + methods->Proceed(); + } + } + + private: + experimental::ClientRpcInfo* info_; + int count = 0; +}; + +class ServerStreamingRpcHijackingInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new ServerStreamingRpcHijackingInterceptor(info); + } +}; + class LoggingInterceptor : public experimental::Interceptor { public: LoggingInterceptor(experimental::ClientRpcInfo* info) { info_ = info; } @@ -535,6 +621,21 @@ TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingTest) { EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); } +TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingHijackingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + auto creators = std::unique_ptr>>( + new std::vector< + std::unique_ptr>()); + creators->push_back( + std::unique_ptr( + new ServerStreamingRpcHijackingInterceptorFactory())); + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeServerStreamingCall(channel); +} + TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingTest) { ChannelArguments args; DummyInterceptor::Reset(); From 565edf529766e66b4394f59ff33a89211c92206a Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 9 Nov 2018 19:51:11 -0800 Subject: [PATCH 170/375] Add safety checks --- include/grpcpp/impl/codegen/interceptor_common.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index 4c881c783d3..d23b71f8a77 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -160,7 +160,11 @@ class InterceptorBatchMethodsImpl info->channel(), current_interceptor_index_ + 1)); } - void FailHijackedRecvMessage() override { *got_message_ = false; } + void FailHijackedRecvMessage() override { + GPR_CODEGEN_ASSERT(hooks_[static_cast( + experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)]); + *got_message_ = false; + } // Clears all state void ClearState() { From 94d220d32c0db708a3afa36a17aae25d93c2636b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 14 Nov 2018 14:03:27 -0800 Subject: [PATCH 171/375] Rename variable --- .../cronet/client/secure/cronet_channel_create.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc index dffb61b082d..1cb38f25b6d 100644 --- a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc +++ b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc @@ -47,11 +47,11 @@ GRPCAPI grpc_channel* grpc_cronet_secure_channel_create( target); // Disable client authority filter when using Cronet - grpc_arg arg; - arg.key = const_cast(GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER); - arg.type = GRPC_ARG_INTEGER; - arg.value.integer = 1; - grpc_channel_args* new_args = grpc_channel_args_copy_and_add(args, &arg, 1); + grpc_arg disable_client_authority_filter_arg; + disable_client_authority_filter_arg.key = const_cast(GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER); + disable_client_authority_filter_arg.type = GRPC_ARG_INTEGER; + disable_client_authority_filter_arg.value.integer = 1; + grpc_channel_args* new_args = grpc_channel_args_copy_and_add(args, &disable_client_authority_filter_arg, 1); grpc_transport* ct = grpc_create_cronet_transport(engine, target, new_args, reserved); From 8d0cf9ec0aaa9e9efd23254d189d78fbaead2702 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 14 Nov 2018 14:03:50 -0800 Subject: [PATCH 172/375] clang-format --- .../tests/ChannelTests/ChannelPoolTest.m | 38 +++++++------------ .../tests/ChannelTests/ChannelTests.m | 18 +++++---- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m index d684db545e9..b85e62feb5f 100644 --- a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m +++ b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m @@ -47,14 +47,10 @@ NSString *kDummyHost = @"dummy.host"; GRPCChannelPool *pool = [GRPCChannelPool sharedInstance]; - GRPCChannel *channel1 = [pool channelWithHost:kDummyHost - callOptions:options1]; - GRPCChannel *channel2 = [pool channelWithHost:kDummyHost - callOptions:options2]; - GRPCChannel *channel3 = [pool channelWithHost:kDummyHost2 - callOptions:options1]; - GRPCChannel *channel4 = [pool channelWithHost:kDummyHost - callOptions:options3]; + GRPCChannel *channel1 = [pool channelWithHost:kDummyHost callOptions:options1]; + GRPCChannel *channel2 = [pool channelWithHost:kDummyHost callOptions:options2]; + GRPCChannel *channel3 = [pool channelWithHost:kDummyHost2 callOptions:options1]; + GRPCChannel *channel4 = [pool channelWithHost:kDummyHost callOptions:options3]; XCTAssertEqual(channel1, channel2); XCTAssertNotEqual(channel1, channel3); XCTAssertNotEqual(channel1, channel4); @@ -66,16 +62,14 @@ NSString *kDummyHost = @"dummy.host"; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; GRPCChannelPool *pool = [GRPCChannelPool sharedInstance]; - GRPCChannel *channel = [pool channelWithHost:kDummyHost - callOptions:options]; + GRPCChannel *channel = [pool channelWithHost:kDummyHost callOptions:options]; grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" completionQueue:[GRPCCompletionQueue completionQueue] callOptions:options disconnected:nil]; [pool destroyAllChannels]; XCTAssertTrue(channel.disconnected); - GRPCChannel *channel2 = [pool channelWithHost:kDummyHost - callOptions:options]; + GRPCChannel *channel2 = [pool channelWithHost:kDummyHost callOptions:options]; XCTAssertNotEqual(channel, channel2); grpc_call_unref(call); } @@ -86,9 +80,8 @@ NSString *kDummyHost = @"dummy.host"; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; GRPCChannelPool *pool = [GRPCChannelPool sharedInstance]; - GRPCChannel *channel = [pool channelWithHost:kDummyHost - callOptions:options - destroyDelay:kDestroyDelay]; + GRPCChannel *channel = + [pool channelWithHost:kDummyHost callOptions:options destroyDelay:kDestroyDelay]; grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" completionQueue:[GRPCCompletionQueue completionQueue] callOptions:options @@ -97,9 +90,8 @@ NSString *kDummyHost = @"dummy.host"; [channel unref]; // Test that we can still get the channel at this time - GRPCChannel *channel2 = [pool channelWithHost:kDummyHost - callOptions:options - destroyDelay:kDestroyDelay]; + GRPCChannel *channel2 = + [pool channelWithHost:kDummyHost callOptions:options destroyDelay:kDestroyDelay]; XCTAssertEqual(channel, channel2); call = [channel2 unmanagedCallWithPath:@"dummy.path" completionQueue:[GRPCCompletionQueue completionQueue] @@ -117,9 +109,8 @@ NSString *kDummyHost = @"dummy.host"; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; GRPCChannelPool *pool = [GRPCChannelPool sharedInstance]; - GRPCChannel *channel = [pool channelWithHost:kDummyHost - callOptions:options - destroyDelay:kDestroyDelay]; + GRPCChannel *channel = + [pool channelWithHost:kDummyHost callOptions:options destroyDelay:kDestroyDelay]; grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" completionQueue:[GRPCCompletionQueue completionQueue] callOptions:options @@ -130,9 +121,8 @@ NSString *kDummyHost = @"dummy.host"; sleep(kDestroyDelay + 1); // Test that we get new channel to the same host and with the same callOptions - GRPCChannel *channel2 = [pool channelWithHost:kDummyHost - callOptions:options - destroyDelay:kDestroyDelay]; + GRPCChannel *channel2 = + [pool channelWithHost:kDummyHost callOptions:options destroyDelay:kDestroyDelay]; XCTAssertNotEqual(channel, channel2); } diff --git a/src/objective-c/tests/ChannelTests/ChannelTests.m b/src/objective-c/tests/ChannelTests/ChannelTests.m index 27e76d41799..5daafcdf3f3 100644 --- a/src/objective-c/tests/ChannelTests/ChannelTests.m +++ b/src/objective-c/tests/ChannelTests/ChannelTests.m @@ -33,12 +33,13 @@ } - (void)testTimedDisconnection { - NSString * const kHost = @"grpc-test.sandbox.googleapis.com"; + NSString *const kHost = @"grpc-test.sandbox.googleapis.com"; const NSTimeInterval kDestroyDelay = 1; GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCChannelConfiguration *configuration = [[GRPCChannelConfiguration alloc] initWithHost:kHost callOptions:options]; - GRPCChannel *channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration - destroyDelay:kDestroyDelay]; + GRPCChannelConfiguration *configuration = + [[GRPCChannelConfiguration alloc] initWithHost:kHost callOptions:options]; + GRPCChannel *channel = + [[GRPCChannel alloc] initWithChannelConfiguration:configuration destroyDelay:kDestroyDelay]; BOOL disconnected; grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" completionQueue:[GRPCCompletionQueue completionQueue] @@ -61,12 +62,13 @@ } - (void)testForceDisconnection { - NSString * const kHost = @"grpc-test.sandbox.googleapis.com"; + NSString *const kHost = @"grpc-test.sandbox.googleapis.com"; const NSTimeInterval kDestroyDelay = 1; GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCChannelConfiguration *configuration = [[GRPCChannelConfiguration alloc] initWithHost:kHost callOptions:options]; - GRPCChannel *channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration - destroyDelay:kDestroyDelay]; + GRPCChannelConfiguration *configuration = + [[GRPCChannelConfiguration alloc] initWithHost:kHost callOptions:options]; + GRPCChannel *channel = + [[GRPCChannel alloc] initWithChannelConfiguration:configuration destroyDelay:kDestroyDelay]; grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" completionQueue:[GRPCCompletionQueue completionQueue] callOptions:options From b77203fdf59faa38e7be01f8796d3bc3e67db602 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 14 Nov 2018 14:09:41 -0800 Subject: [PATCH 173/375] Move blocks into varibles for readability --- src/objective-c/GRPCClient/GRPCCall.m | 53 ++++++++++++++------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 5e3491dafaa..39681d2adfb 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -172,7 +172,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; if (self->_callOptions.initialMetadata) { [self->_call.requestHeaders addEntriesFromDictionary:self->_callOptions.initialMetadata]; } - id responseWriteable = [[GRXWriteable alloc] initWithValueHandler:^(id value) { + + void (^valueHandler)(id value) = ^(id value) { dispatch_async(self->_dispatchQueue, ^{ if (self->_handler) { if (!self->_initialMetadataPublished) { @@ -184,30 +185,32 @@ const char *kCFStreamVarName = "grpc_cfstream"; } } }); - } - completionHandler:^(NSError *errorOrNil) { - dispatch_async(self->_dispatchQueue, ^{ - if (self->_handler) { - if (!self->_initialMetadataPublished) { - self->_initialMetadataPublished = YES; - [self issueInitialMetadata:self->_call.responseHeaders]; - } - [self issueClosedWithTrailingMetadata:self->_call.responseTrailers error:errorOrNil]; - - // Clean up _handler so that no more responses are reported to the handler. - self->_handler = nil; - } - // Clearing _call must happen *after* dispatching close in order to get trailing - // metadata from _call. - if (self->_call) { - // Clean up the request writers. This should have no effect to _call since its - // response writeable is already nullified. - [self->_pipe writesFinishedWithError:nil]; - self->_call = nil; - self->_pipe = nil; - } - }); - }]; + }; + void (^completionHandler)(NSError *errorOrNil) = ^(NSError *errorOrNil) { + dispatch_async(self->_dispatchQueue, ^{ + if (self->_handler) { + if (!self->_initialMetadataPublished) { + self->_initialMetadataPublished = YES; + [self issueInitialMetadata:self->_call.responseHeaders]; + } + [self issueClosedWithTrailingMetadata:self->_call.responseTrailers error:errorOrNil]; + + // Clean up _handler so that no more responses are reported to the handler. + self->_handler = nil; + } + // Clearing _call must happen *after* dispatching close in order to get trailing + // metadata from _call. + if (self->_call) { + // Clean up the request writers. This should have no effect to _call since its + // response writeable is already nullified. + [self->_pipe writesFinishedWithError:nil]; + self->_call = nil; + self->_pipe = nil; + } + }); + }; + id responseWriteable = [[GRXWriteable alloc] initWithValueHandler:valueHandler + completionHandler:completionHandler]; [self->_call startWithWriteable:responseWriteable]; }); } From 78c2176afcdf2267467c68f6f070fc6543673bd7 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 14 Nov 2018 14:40:44 -0800 Subject: [PATCH 174/375] Assign finished and canceled --- src/objective-c/GRPCClient/GRPCCall.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 39681d2adfb..9d81dcf6e6e 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -143,7 +143,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; dispatch_set_target_queue(responseHandler.dispatchQueue, _dispatchQueue); _started = NO; _canceled = NO; - _finished = YES; + _finished = NO; } return self; @@ -218,6 +218,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)cancel { dispatch_async(_dispatchQueue, ^{ GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call already canceled."); + self->_canceled = YES; if (self->_call) { [self->_call cancel]; self->_call = nil; @@ -263,6 +264,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; [self->_pipe writesFinishedWithError:nil]; } self->_pipe = nil; + self->_finished = YES; }); } From f4a77ce4926064e193787521081e835bd94f1e7d Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 14 Nov 2018 14:51:07 -0800 Subject: [PATCH 175/375] _call->_pipe --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 9d81dcf6e6e..46cd5a4f227 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -260,7 +260,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; GRPCAssert(self->_started, NSInternalInconsistencyException, @"Call not started."); GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call arleady canceled."); GRPCAssert(!self->_finished, NSInternalInconsistencyException, @"Call already half-closed."); - if (self->_call) { + if (self->_pipe) { [self->_pipe writesFinishedWithError:nil]; } self->_pipe = nil; From c83ab56fe1d4bc6e5c3cebbc4943505eaf6ea74a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 14 Nov 2018 14:51:25 -0800 Subject: [PATCH 176/375] copy->mutableCopy --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 46cd5a4f227..6de7bd8967b 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -581,7 +581,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; break; } - NSMutableDictionary *headers = [_requestHeaders copy]; + NSMutableDictionary *headers = [_requestHeaders mutableCopy]; NSString *fetchedOauth2AccessToken; @synchronized(self) { fetchedOauth2AccessToken = _fetchedOauth2AccessToken; From b22120f69601450d4cbdc6957f661ba7ec29ca3a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 14 Nov 2018 16:10:10 -0800 Subject: [PATCH 177/375] Test fix --- src/objective-c/tests/APIv2Tests/APIv2Tests.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/objective-c/tests/APIv2Tests/APIv2Tests.m b/src/objective-c/tests/APIv2Tests/APIv2Tests.m index d681163419d..28f94cd8c77 100644 --- a/src/objective-c/tests/APIv2Tests/APIv2Tests.m +++ b/src/objective-c/tests/APIv2Tests/APIv2Tests.m @@ -277,6 +277,7 @@ static const NSTimeInterval kTestTimeout = 16; callOptions:options]; [call writeData:[NSData data]]; [call start]; + [call finish]; [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; } @@ -312,6 +313,7 @@ static const NSTimeInterval kTestTimeout = 16; callOptions:options]; [call writeData:[request data]]; [call start]; + [call finish]; [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; } From e023468e9a82a4338e30e57ab822c86406480b94 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 14 Nov 2018 16:34:58 -0800 Subject: [PATCH 178/375] some nit fixes --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- src/objective-c/GRPCClient/GRPCCallOptions.m | 2 +- src/objective-c/GRPCClient/private/GRPCChannel.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 6de7bd8967b..2a56514bdc9 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -282,7 +282,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)issueClosedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - [_handler closedWithTrailingMetadata:_call.responseTrailers error:error]; + [_handler closedWithTrailingMetadata:trailingMetadata error:error]; } } diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index ecb517762b3..9a36ee547cd 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -45,7 +45,7 @@ static NSString *const kDefaultChannelPoolDomain = nil; static const NSUInteger kDefaultChannelID = 0; // Check if two objects are equal. Returns YES if both are nil; -BOOL areObjectsEqual(id obj1, id obj2) { +static BOOL areObjectsEqual(id obj1, id obj2) { if (obj1 == obj2) { return YES; } diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index 6c58f4f387f..32e68bb2625 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -39,7 +39,7 @@ NS_ASSUME_NONNULL_BEGIN * Options of the corresponding call. Note that only the channel-related options are of interest to * this class. */ -@property(strong, readonly) GRPCCallOptions *callOptions; +@property(readonly) GRPCCallOptions *callOptions; /** Acquire the factory to generate a new channel with current configurations. */ @property(readonly) id channelFactory; From 5d7d6c0fbdcac75ea482e1fde3e128cd0c1646c1 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 14 Nov 2018 17:35:26 -0800 Subject: [PATCH 179/375] Add method to fail hijacked send messages --- include/grpcpp/impl/codegen/call_op_set.h | 10 ++- include/grpcpp/impl/codegen/interceptor.h | 4 + .../grpcpp/impl/codegen/interceptor_common.h | 18 ++++- .../client_interceptors_end2end_test.cc | 73 +++++++++++++++++++ 4 files changed, 102 insertions(+), 3 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index b4c34a01c9a..1f2b88e9e14 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -314,14 +314,19 @@ class CallOpSendMessage { // Flags are per-message: clear them after use. write_options_.Clear(); } - void FinishOp(bool* status) { send_buf_.Clear(); } + void FinishOp(bool* status) { + send_buf_.Clear(); + if (hijacked_ && failed_send_) { + *status = false; + } + } void SetInterceptionHookPoint( InterceptorBatchMethodsImpl* interceptor_methods) { if (!send_buf_.Valid()) return; interceptor_methods->AddInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_MESSAGE); - interceptor_methods->SetSendMessage(&send_buf_); + interceptor_methods->SetSendMessage(&send_buf_, &failed_send_); } void SetFinishInterceptionHookPoint( @@ -333,6 +338,7 @@ class CallOpSendMessage { private: bool hijacked_ = false; + bool failed_send_ = false; ByteBuffer send_buf_; WriteOptions write_options_; }; diff --git a/include/grpcpp/impl/codegen/interceptor.h b/include/grpcpp/impl/codegen/interceptor.h index e449e44a23b..47239332c86 100644 --- a/include/grpcpp/impl/codegen/interceptor.h +++ b/include/grpcpp/impl/codegen/interceptor.h @@ -118,6 +118,10 @@ class InterceptorBatchMethods { // only interceptors after the current interceptor are created from the // factory objects registered with the channel. virtual std::unique_ptr GetInterceptedChannel() = 0; + + // On a hijacked RPC/ to-be hijacked RPC, this can be called to fail a SEND + // MESSAGE op + virtual void FailHijackedSendMessage() = 0; }; class Interceptor { diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index d0aa23cb0a0..601a929afe6 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -110,12 +110,21 @@ class InterceptorBatchMethodsImpl Status* GetRecvStatus() override { return recv_status_; } + void FailHijackedSendMessage() override { + GPR_CODEGEN_ASSERT(hooks_[static_cast( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)]); + *fail_send_message_ = true; + } + std::multimap* GetRecvTrailingMetadata() override { return recv_trailing_metadata_->map(); } - void SetSendMessage(ByteBuffer* buf) { send_message_ = buf; } + void SetSendMessage(ByteBuffer* buf, bool* fail_send_message) { + send_message_ = buf; + fail_send_message_ = fail_send_message; + } void SetSendInitialMetadata( std::multimap* metadata) { @@ -334,6 +343,7 @@ class InterceptorBatchMethodsImpl std::function callback_; ByteBuffer* send_message_ = nullptr; + bool* fail_send_message_ = nullptr; std::multimap* send_initial_metadata_; @@ -451,6 +461,12 @@ class CancelInterceptorBatchMethods "method which has a Cancel notification"); return std::unique_ptr(nullptr); } + + void FailHijackedSendMessage() override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call FailHijackedSendMessage on a " + "method which has a Cancel notification"); + } }; } // namespace internal } // namespace grpc diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 0b34ec93ae7..81efd154525 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -269,6 +269,49 @@ class HijackingInterceptorMakesAnotherCallFactory } }; +class ClientStreamingRpcHijackingInterceptor + : public experimental::Interceptor { + public: + ClientStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) { + info_ = info; + } + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + bool hijack = false; + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + hijack = true; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + if (++count_ > 10) { + methods->FailHijackedSendMessage(); + } + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { + auto* status = methods->GetRecvStatus(); + *status = Status(StatusCode::UNAVAILABLE, "Done sending 10 messages"); + } + if (hijack) { + methods->Hijack(); + } else { + methods->Proceed(); + } + } + + private: + experimental::ClientRpcInfo* info_; + int count_ = 0; +}; +class ClientStreamingRpcHijackingInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new ClientStreamingRpcHijackingInterceptor(info); + } +}; + class LoggingInterceptor : public experimental::Interceptor { public: LoggingInterceptor(experimental::ClientRpcInfo* info) { info_ = info; } @@ -535,6 +578,36 @@ TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingTest) { EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); } +TEST_F(ClientInterceptorsStreamingEnd2endTest, ClientStreamingHijackingTest) { + ChannelArguments args; + auto creators = std::unique_ptr>>( + new std::vector< + std::unique_ptr>()); + creators->push_back( + std::unique_ptr( + new ClientStreamingRpcHijackingInterceptorFactory())); + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + + auto stub = grpc::testing::EchoTestService::NewStub(channel); + ClientContext ctx; + EchoRequest req; + EchoResponse resp; + req.mutable_param()->set_echo_metadata(true); + req.set_message("Hello"); + string expected_resp = ""; + auto writer = stub->RequestStream(&ctx, &resp); + for (int i = 0; i < 10; i++) { + EXPECT_TRUE(writer->Write(req)); + expected_resp += "Hello"; + } + // Expect that the interceptor will reject the 11th message + EXPECT_FALSE(writer->Write(req)); + Status s = writer->Finish(); + EXPECT_EQ(s.ok(), false); +} + TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingTest) { ChannelArguments args; DummyInterceptor::Reset(); From 2bd38f29df16b874bea254e001e3c40d6945c28c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 14 Nov 2018 17:59:30 -0800 Subject: [PATCH 180/375] Batch fixes --- .../GRPCClient/private/GRPCChannel.m | 17 ++++++++++------- .../GRPCClient/private/GRPCWrappedCall.m | 7 +++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index fc0448bb962..52dacad9f50 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -84,7 +84,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; NSString *userAgent = @"grpc-objc/" GRPC_OBJC_VERSION_STRING; NSString *userAgentPrefix = _callOptions.userAgentPrefix; - if (userAgentPrefix) { + if (userAgentPrefix.length != 0) { args[@GRPC_ARG_PRIMARY_USER_AGENT_STRING] = [_callOptions.userAgentPrefix stringByAppendingFormat:@" %@", userAgent]; } else { @@ -242,7 +242,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; if (self->_disconnected) { isDisconnected = YES; } else { - GRPCAssert(self->_unmanagedChannel != NULL, NSInvalidArgumentException, @"Invalid channel."); + GRPCAssert(self->_unmanagedChannel != NULL, NSInternalInconsistencyException, @"Channel should have valid unmanaged channel."); NSString *serverAuthority = callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; @@ -281,14 +281,17 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; // This function should be called on _dispatchQueue. - (void)ref { - _refcount++; - if (_refcount == 1 && _lastDispatch != nil) { - _lastDispatch = nil; - } + dispatch_sync(_dispatchQueue, ^{ + self->_refcount++; + if (self->_refcount == 1 && self->_lastDispatch != nil) { + self->_lastDispatch = nil; + } + }); } - (void)unref { dispatch_async(_dispatchQueue, ^{ + GRPCAssert(self->_refcount > 0, NSInternalInconsistencyException, @"Illegal reference count."); self->_refcount--; if (self->_refcount == 0 && !self->_disconnected) { // Start timer. @@ -298,7 +301,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; self->_lastDispatch = now; dispatch_after(delay, self->_dispatchQueue, ^{ // Timed disconnection. - if (self->_lastDispatch == now) { + if (!self->_disconnected && self->_lastDispatch == now) { grpc_channel_destroy(self->_unmanagedChannel); self->_unmanagedChannel = NULL; self->_disconnected = YES; diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 2358c7bb0a8..f3fe8bac455 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -30,6 +30,7 @@ #import "NSData+GRPC.h" #import "NSDictionary+GRPC.h" #import "NSError+GRPC.h" +#import "utilities.h" #import "GRPCOpBatchLog.h" @@ -248,16 +249,14 @@ - (instancetype)initWithHost:(NSString *)host path:(NSString *)path callOptions:(GRPCCallOptions *)callOptions { - if (host.length == 0 || path.length == 0) { - [NSException raise:NSInvalidArgumentException format:@"path and host cannot be nil."]; - } + GRPCAssert(host.length != 0 && path.length != 0, NSInvalidArgumentException, @"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. _queue = [GRPCCompletionQueue completionQueue]; - BOOL disconnected; + BOOL disconnected = NO; do { _channel = [[GRPCChannelPool sharedInstance] channelWithHost:host callOptions:callOptions]; if (_channel == nil) { From ceeb28a360d48389edb8c1c91a1efac46e24a9b7 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 14 Nov 2018 18:02:54 -0800 Subject: [PATCH 181/375] s/count/count_/ --- test/cpp/end2end/client_interceptors_end2end_test.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index b94a3d752e8..459788ba519 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -318,7 +318,7 @@ class ServerStreamingRpcHijackingInterceptor } if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { - if (++count > 10) { + if (++count_ > 10) { methods->FailHijackedRecvMessage(); } EchoResponse* resp = @@ -343,7 +343,7 @@ class ServerStreamingRpcHijackingInterceptor private: experimental::ClientRpcInfo* info_; - int count = 0; + int count_ = 0; }; class ServerStreamingRpcHijackingInterceptorFactory From b5434c05aaaacfba9d6ef6882b6c1f3285a304e2 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 14 Nov 2018 18:48:09 -0800 Subject: [PATCH 182/375] Make tests pass --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- src/objective-c/GRPCClient/private/GRPCChannel.m | 11 +++++------ src/objective-c/GRPCClient/private/GRPCWrappedCall.m | 1 - 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 2a56514bdc9..1ba55a7744d 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -249,7 +249,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call arleady canceled."); GRPCAssert(!self->_finished, NSInternalInconsistencyException, @"Call is half-closed before sending data."); - if (self->_call) { + if (self->_pipe) { [self->_pipe writeValue:data]; } }); diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 52dacad9f50..f63157c9743 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -281,15 +281,14 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; // This function should be called on _dispatchQueue. - (void)ref { - dispatch_sync(_dispatchQueue, ^{ - self->_refcount++; - if (self->_refcount == 1 && self->_lastDispatch != nil) { - self->_lastDispatch = nil; - } - }); + _refcount++; + if (_refcount == 1 && _lastDispatch != nil) { + _lastDispatch = nil; + } } - (void)unref { + NSLog(@"unref"); dispatch_async(_dispatchQueue, ^{ GRPCAssert(self->_refcount > 0, NSInternalInconsistencyException, @"Illegal reference count."); self->_refcount--; diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index f3fe8bac455..905719f4642 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -325,7 +325,6 @@ - (void)dealloc { if (_call) { grpc_call_unref(_call); - [_channel unref]; } [_channel unref]; _channel = nil; From e14ec44b0ac1512bc3def0f2094be883d1b53c5f Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 14 Nov 2018 18:52:35 -0800 Subject: [PATCH 183/375] clang-format --- src/objective-c/GRPCClient/GRPCCall.m | 5 +++-- src/objective-c/GRPCClient/private/GRPCChannel.m | 3 ++- src/objective-c/GRPCClient/private/GRPCWrappedCall.m | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 1ba55a7744d..4068c3b4608 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -209,8 +209,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; } }); }; - id responseWriteable = [[GRXWriteable alloc] initWithValueHandler:valueHandler - completionHandler:completionHandler]; + id responseWriteable = + [[GRXWriteable alloc] initWithValueHandler:valueHandler + completionHandler:completionHandler]; [self->_call startWithWriteable:responseWriteable]; }); } diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index f63157c9743..2933ca7044a 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -242,7 +242,8 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; if (self->_disconnected) { isDisconnected = YES; } else { - GRPCAssert(self->_unmanagedChannel != NULL, NSInternalInconsistencyException, @"Channel should have valid unmanaged channel."); + GRPCAssert(self->_unmanagedChannel != NULL, NSInternalInconsistencyException, + @"Channel should have valid unmanaged channel."); NSString *serverAuthority = callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 905719f4642..aa7d60786ea 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -249,7 +249,8 @@ - (instancetype)initWithHost:(NSString *)host path:(NSString *)path callOptions:(GRPCCallOptions *)callOptions { - GRPCAssert(host.length != 0 && path.length != 0, NSInvalidArgumentException, @"path and host cannot be nil."); + GRPCAssert(host.length != 0 && path.length != 0, NSInvalidArgumentException, + @"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 From 7500528b15b3a47343a6483c1b71857cbe00244a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 15 Nov 2018 09:45:12 -0800 Subject: [PATCH 184/375] clang-format --- .../transport/cronet/client/secure/cronet_channel_create.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc index 1cb38f25b6d..6e08d27b21d 100644 --- a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc +++ b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc @@ -48,10 +48,12 @@ GRPCAPI grpc_channel* grpc_cronet_secure_channel_create( // Disable client authority filter when using Cronet grpc_arg disable_client_authority_filter_arg; - disable_client_authority_filter_arg.key = const_cast(GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER); + disable_client_authority_filter_arg.key = + const_cast(GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER); disable_client_authority_filter_arg.type = GRPC_ARG_INTEGER; disable_client_authority_filter_arg.value.integer = 1; - grpc_channel_args* new_args = grpc_channel_args_copy_and_add(args, &disable_client_authority_filter_arg, 1); + grpc_channel_args* new_args = grpc_channel_args_copy_and_add( + args, &disable_client_authority_filter_arg, 1); grpc_transport* ct = grpc_create_cronet_transport(engine, target, new_args, reserved); From 6b6ab2bdc9d03ffe85398451342a140320aac1dd Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 15 Nov 2018 12:22:38 -0800 Subject: [PATCH 185/375] Back to NSAssert --- src/objective-c/GRPCClient/GRPCCall.m | 37 +++++++++---------- .../GRPCClient/private/GRPCChannel.m | 22 +++++------ .../GRPCClient/private/GRPCChannelPool.m | 6 +-- src/objective-c/GRPCClient/private/GRPCHost.m | 2 +- .../private/GRPCSecureChannelFactory.m | 2 +- .../GRPCClient/private/GRPCWrappedCall.m | 4 +- .../GRPCClient/private/utilities.h | 19 ++-------- 7 files changed, 39 insertions(+), 53 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 4068c3b4608..788afeb6c3c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -68,8 +68,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; @implementation GRPCRequestOptions - (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety { - GRPCAssert(host.length != 0 && path.length != 0, NSInvalidArgumentException, - @"Host and Path cannot be empty"); + NSAssert(host.length != 0 && path.length != 0, @"Host and Path cannot be empty"); if ((self = [super init])) { _host = [host copy]; _path = [path copy]; @@ -116,11 +115,11 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)responseHandler callOptions:(GRPCCallOptions *_Nullable)callOptions { - GRPCAssert(requestOptions.host.length != 0 && requestOptions.path.length != 0, - NSInvalidArgumentException, @"Neither host nor path can be nil."); - GRPCAssert(requestOptions.safety <= GRPCCallSafetyCacheableRequest, NSInvalidArgumentException, + NSAssert(requestOptions.host.length != 0 && requestOptions.path.length != 0, + @"Neither host nor path can be nil."); + NSAssert(requestOptions.safety <= GRPCCallSafetyCacheableRequest, @"Invalid call safety value."); - GRPCAssert(responseHandler != nil, NSInvalidArgumentException, @"Response handler required."); + NSAssert(responseHandler != nil, @"Response handler required."); if ((self = [super init])) { _requestOptions = [requestOptions copy]; @@ -157,8 +156,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)start { dispatch_async(_dispatchQueue, ^{ - GRPCAssert(!self->_started, NSInternalInconsistencyException, @"Call already started."); - GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call already canceled."); + NSAssert(!self->_started, @"Call already started."); + NSAssert(!self->_canceled, @"Call already canceled."); self->_started = YES; if (!self->_callOptions) { self->_callOptions = [[GRPCCallOptions alloc] init]; @@ -218,7 +217,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)cancel { dispatch_async(_dispatchQueue, ^{ - GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call already canceled."); + NSAssert(!self->_canceled, @"Call already canceled."); self->_canceled = YES; if (self->_call) { [self->_call cancel]; @@ -247,9 +246,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)writeData:(NSData *)data { dispatch_async(_dispatchQueue, ^{ - GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call arleady canceled."); - GRPCAssert(!self->_finished, NSInternalInconsistencyException, - @"Call is half-closed before sending data."); + NSAssert(!self->_canceled, @"Call arleady canceled."); + NSAssert(!self->_finished, @"Call is half-closed before sending data."); if (self->_pipe) { [self->_pipe writeValue:data]; } @@ -258,9 +256,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)finish { dispatch_async(_dispatchQueue, ^{ - GRPCAssert(self->_started, NSInternalInconsistencyException, @"Call not started."); - GRPCAssert(!self->_canceled, NSInternalInconsistencyException, @"Call arleady canceled."); - GRPCAssert(!self->_finished, NSInternalInconsistencyException, @"Call already half-closed."); + NSAssert(self->_started, @"Call not started."); + NSAssert(!self->_canceled, @"Call arleady canceled."); + NSAssert(!self->_finished, @"Call already half-closed."); if (self->_pipe) { [self->_pipe writesFinishedWithError:nil]; } @@ -409,10 +407,10 @@ const char *kCFStreamVarName = "grpc_cfstream"; requestsWriter:(GRXWriter *)requestWriter callOptions:(GRPCCallOptions *)callOptions { // Purposely using pointer rather than length ([host length] == 0) for backwards compatibility. - GRPCAssert(host && path, NSInvalidArgumentException, @"Neither host nor path can be nil."); - GRPCAssert(safety <= GRPCCallSafetyCacheableRequest, NSInvalidArgumentException, + NSAssert(host && path, @"Neither host nor path can be nil."); + NSAssert(safety <= GRPCCallSafetyCacheableRequest, @"Invalid call safety value."); - GRPCAssert(requestWriter.state == GRXWriterStateNotStarted, NSInvalidArgumentException, + NSAssert(requestWriter.state == GRXWriterStateNotStarted, @"The requests writer can't be already started."); if ((self = [super init])) { _host = [host copy]; @@ -798,8 +796,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; _callOptions = callOptions; } - GRPCAssert(_callOptions.authTokenProvider == nil || _callOptions.oauth2AccessToken == nil, - NSInvalidArgumentException, + NSAssert(_callOptions.authTokenProvider == nil || _callOptions.oauth2AccessToken == nil, @"authTokenProvider and oauth2AccessToken cannot be set at the same time"); if (_callOptions.authTokenProvider != nil) { @synchronized(self) { diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 2933ca7044a..ab084fba480 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -40,8 +40,8 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; @implementation GRPCChannelConfiguration - (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { - GRPCAssert(host.length, NSInvalidArgumentException, @"Host must not be empty."); - GRPCAssert(callOptions != nil, NSInvalidArgumentException, @"callOptions must not be empty."); + NSAssert(host.length, @"Host must not be empty."); + NSAssert(callOptions != nil, @"callOptions must not be empty."); if ((self = [super init])) { _host = [host copy]; _callOptions = [callOptions copy]; @@ -193,9 +193,9 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; - (nullable instancetype)initWithChannelConfiguration: (GRPCChannelConfiguration *)channelConfiguration destroyDelay:(NSTimeInterval)destroyDelay { - GRPCAssert(channelConfiguration != nil, NSInvalidArgumentException, + NSAssert(channelConfiguration != nil, @"channelConfiguration must not be empty."); - GRPCAssert(destroyDelay > 0, NSInvalidArgumentException, @"destroyDelay must be greater than 0."); + NSAssert(destroyDelay > 0, @"destroyDelay must be greater than 0."); if ((self = [super init])) { _configuration = [channelConfiguration copy]; if (@available(iOS 8.0, *)) { @@ -208,7 +208,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; // Create gRPC core channel object. NSString *host = channelConfiguration.host; - GRPCAssert(host.length != 0, NSInvalidArgumentException, @"host cannot be nil"); + NSAssert(host.length != 0, @"host cannot be nil"); NSDictionary *channelArgs; if (channelConfiguration.callOptions.additionalChannelArgs.count != 0) { NSMutableDictionary *args = [channelConfiguration.channelArgs mutableCopy]; @@ -233,22 +233,22 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; completionQueue:(GRPCCompletionQueue *)queue callOptions:(GRPCCallOptions *)callOptions disconnected:(BOOL *)disconnected { - GRPCAssert(path.length, NSInvalidArgumentException, @"path must not be empty."); - GRPCAssert(queue, NSInvalidArgumentException, @"completionQueue must not be empty."); - GRPCAssert(callOptions, NSInvalidArgumentException, @"callOptions must not be empty."); + NSAssert(path.length, @"path must not be empty."); + NSAssert(queue, @"completionQueue must not be empty."); + NSAssert(callOptions, @"callOptions must not be empty."); __block BOOL isDisconnected = NO; __block grpc_call *call = NULL; dispatch_sync(_dispatchQueue, ^{ if (self->_disconnected) { isDisconnected = YES; } else { - GRPCAssert(self->_unmanagedChannel != NULL, NSInternalInconsistencyException, + NSAssert(self->_unmanagedChannel != NULL, @"Channel should have valid unmanaged channel."); NSString *serverAuthority = callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; NSTimeInterval timeout = callOptions.timeout; - GRPCAssert(timeout >= 0, NSInvalidArgumentException, @"Invalid timeout"); + NSAssert(timeout >= 0, @"Invalid timeout"); grpc_slice host_slice = grpc_empty_slice(); if (serverAuthority) { host_slice = grpc_slice_from_copied_string(serverAuthority.UTF8String); @@ -291,7 +291,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; - (void)unref { NSLog(@"unref"); dispatch_async(_dispatchQueue, ^{ - GRPCAssert(self->_refcount > 0, NSInternalInconsistencyException, @"Illegal reference count."); + NSAssert(self->_refcount > 0, @"Illegal reference count."); self->_refcount--; if (self->_refcount == 0 && !self->_disconnected) { // Start timer. diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 85ca527277c..6745010bd49 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -44,7 +44,7 @@ static dispatch_once_t gInitChannelPool; + (nullable instancetype)sharedInstance { dispatch_once(&gInitChannelPool, ^{ gChannelPool = [[GRPCChannelPool alloc] init]; - GRPCAssert(gChannelPool != nil, NSMallocException, @"Cannot initialize global channel pool."); + NSAssert(gChannelPool != nil, @"Cannot initialize global channel pool."); }); return gChannelPool; } @@ -69,8 +69,8 @@ static dispatch_once_t gInitChannelPool; - (GRPCChannel *)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions destroyDelay:(NSTimeInterval)destroyDelay { - GRPCAssert(host.length > 0, NSInvalidArgumentException, @"Host must not be empty."); - GRPCAssert(callOptions != nil, NSInvalidArgumentException, @"callOptions must not be empty."); + NSAssert(host.length > 0, @"Host must not be empty."); + NSAssert(callOptions != nil, @"callOptions must not be empty."); GRPCChannel *channel; GRPCChannelConfiguration *configuration = [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 5fc7427b689..b693b926bad 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -122,7 +122,7 @@ static NSMutableDictionary *gHostCache; if (_transportType == GRPCTransportTypeInsecure) { options.transportType = GRPCTransportTypeInsecure; } else { - GRPCAssert(_transportType == GRPCTransportTypeDefault, NSInvalidArgumentException, + NSAssert(_transportType == GRPCTransportTypeDefault, @"Invalid transport type"); options.transportType = GRPCTransportTypeCronet; } diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 57bd40d6787..f5e7a2b9e20 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -83,7 +83,7 @@ NS_ASSUME_NONNULL_BEGIN if (errorPtr) { *errorPtr = defaultRootsError; } - GRPCAssertWithArgument( + NSAssert( defaultRootsASCII, NSObjectNotAvailableException, @"Could not read gRPCCertificates.bundle/roots.pem. This file, " "with the root certificates, is needed to establish secure (TLS) connections. " diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index aa7d60786ea..ae7f07f1192 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -249,7 +249,7 @@ - (instancetype)initWithHost:(NSString *)host path:(NSString *)path callOptions:(GRPCCallOptions *)callOptions { - GRPCAssert(host.length != 0 && path.length != 0, NSInvalidArgumentException, + NSAssert(host.length != 0 && path.length != 0, @"path and host cannot be nil."); if ((self = [super init])) { @@ -261,6 +261,7 @@ do { _channel = [[GRPCChannelPool sharedInstance] channelWithHost:host callOptions:callOptions]; if (_channel == nil) { + NSAssert(_channel != nil, @"Failed to get a channel for the host."); NSLog(@"Failed to get a channel for the host."); return nil; } @@ -272,6 +273,7 @@ // connectivity monitor disconnection). } while (_call == NULL && disconnected); if (_call == nil) { + NSAssert(_channel != nil, @"Failed to get a channel for the host."); NSLog(@"Failed to create a call."); return nil; } diff --git a/src/objective-c/GRPCClient/private/utilities.h b/src/objective-c/GRPCClient/private/utilities.h index 3e51730d637..8f6baadcf7b 100644 --- a/src/objective-c/GRPCClient/private/utilities.h +++ b/src/objective-c/GRPCClient/private/utilities.h @@ -18,19 +18,6 @@ #import -/** Raise exception when condition not met. Disregard NS_BLOCK_ASSERTIONS. */ -#define GRPCAssert(condition, errorType, errorString) \ - do { \ - if (!(condition)) { \ - [NSException raise:(errorType)format:(errorString)]; \ - } \ - } while (0) - -/** The same as GRPCAssert but allows arguments to be put in the raised string. - */ -#define GRPCAssertWithArgument(condition, errorType, errorFormat, ...) \ - do { \ - if (!(condition)) { \ - [NSException raise:(errorType)format:(errorFormat), __VA_ARGS__]; \ - } \ - } while (0) +/** Raise exception when condition not met. */ +#define GRPCAssert(condition, errorString) \ + NSAssert(condition, errorString) From 8a762d447813db1b1c3fe52b24e638581235460e Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 15 Nov 2018 12:56:08 -0800 Subject: [PATCH 186/375] Polish nullability + something else --- src/objective-c/GRPCClient/GRPCCall.h | 28 +++++------ src/objective-c/GRPCClient/GRPCCall.m | 4 +- src/objective-c/GRPCClient/GRPCCallOptions.h | 46 +++++++++---------- .../GRPCClient/private/GRPCChannel.h | 2 +- .../GRPCClient/private/GRPCChannel.m | 10 ++-- .../GRPCClient/private/GRPCChannelFactory.h | 4 +- .../GRPCClient/private/GRPCChannelPool.m | 2 +- .../private/GRPCConnectivityMonitor.m | 4 +- .../private/GRPCCronetChannelFactory.m | 22 +++------ .../private/GRPCInsecureChannelFactory.m | 10 ++-- .../private/GRPCSecureChannelFactory.m | 22 ++++----- src/objective-c/ProtoRPC/ProtoRPC.h | 12 ++--- src/objective-c/ProtoRPC/ProtoRPC.m | 14 +++--- src/objective-c/tests/InteropTests.m | 8 ++-- 14 files changed, 86 insertions(+), 102 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index bde69f01c52..fcda4dc8acd 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -159,14 +159,14 @@ extern NSString *const kGRPCTrailersKey; * Issued when initial metadata is received from the server. The task must be scheduled onto the * dispatch queue in property \a dispatchQueue. */ -- (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata; +- (void)receivedInitialMetadata:(nullable NSDictionary *)initialMetadata; /** * Issued when a message is received from the server. The message is the raw data received from the * server, with decompression and without proto deserialization. The task must be scheduled onto the * dispatch queue in property \a dispatchQueue. */ -- (void)receivedRawMessage:(NSData *_Nullable)message; +- (void)receivedRawMessage:(nullable NSData *)message; /** * Issued when a call finished. If the call finished successfully, \a error is nil and \a @@ -175,8 +175,8 @@ extern NSString *const kGRPCTrailersKey; * error descriptions. The task must be scheduled onto the dispatch queue in property * \a dispatchQueue. */ -- (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata - error:(NSError *_Nullable)error; +- (void)closedWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata + error:(nullable NSError *)error; @required @@ -234,7 +234,7 @@ extern NSString *const kGRPCTrailersKey; */ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)responseHandler - callOptions:(GRPCCallOptions *_Nullable)callOptions + callOptions:(nullable GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; /** * Convenience initializer for a call that uses default call options (see GRPCCallOptions.m for @@ -342,9 +342,9 @@ NS_ASSUME_NONNULL_END * 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 _Null_unspecified)initWithHost:(NSString *_Null_unspecified)host - path:(NSString *_Null_unspecified)path - requestsWriter:(GRXWriter *_Null_unspecified)requestWriter; +- (null_unspecified instancetype)initWithHost:(null_unspecified NSString *)host + path:(null_unspecified NSString *)path + requestsWriter:(null_unspecified GRXWriter *)requestWriter; /** * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and @@ -356,11 +356,11 @@ NS_ASSUME_NONNULL_END * The following methods are deprecated. */ + (void)setCallSafety:(GRPCCallSafety)callSafety - host:(NSString *_Null_unspecified)host - path:(NSString *_Null_unspecified)path; + host:(null_unspecified NSString *)host + path:(null_unspecified NSString *)path; @property(null_unspecified, atomic, copy, readwrite) NSString *serverName; @property NSTimeInterval timeout; -- (void)setResponseDispatchQueue:(dispatch_queue_t _Null_unspecified)queue; +- (void)setResponseDispatchQueue:(null_unspecified dispatch_queue_t)queue; @end @@ -371,11 +371,11 @@ DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.") @protocol GRPCRequestHeaders @property(nonatomic, readonly) NSUInteger count; -- (id _Null_unspecified)objectForKeyedSubscript:(id _Null_unspecified)key; -- (void)setObject:(id _Null_unspecified)obj forKeyedSubscript:(id _Null_unspecified)key; +- (null_unspecified id)objectForKeyedSubscript:(null_unspecified id)key; +- (void)setObject:(null_unspecified id)obj forKeyedSubscript:(null_unspecified id)key; - (void)removeAllObjects; -- (void)removeObjectForKey:(id _Null_unspecified)key; +- (void)removeObjectForKey:(null_unspecified id)key; @end #pragma clang diagnostic push diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 788afeb6c3c..68b51d8c846 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -114,7 +114,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)responseHandler - callOptions:(GRPCCallOptions *_Nullable)callOptions { + callOptions:(GRPCCallOptions *)callOptions { NSAssert(requestOptions.host.length != 0 && requestOptions.path.length != 0, @"Neither host nor path can be nil."); NSAssert(requestOptions.safety <= GRPCCallSafetyCacheableRequest, @@ -134,7 +134,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; if (@available(iOS 8.0, *)) { _dispatchQueue = dispatch_queue_create( NULL, - dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); } else { // Fallback on earlier versions _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index bb8a1d251a9..61d85642863 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -78,7 +78,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * :authority header field of the call and performs an extra check that server's certificate * matches the :authority header. */ -@property(copy, readonly) NSString *serverAuthority; +@property(copy, readonly, nullable) NSString *serverAuthority; /** * The timeout for the RPC call in seconds. If set to 0, the call will not timeout. If set to @@ -94,18 +94,18 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * request's "authorization" header field. This parameter should not be used simultaneously with * \a authTokenProvider. */ -@property(copy, readonly) NSString *oauth2AccessToken; +@property(copy, readonly, nullable) NSString *oauth2AccessToken; /** * The interface to get the OAuth2 access token string. gRPC will attempt to acquire token when * initiating the call. This parameter should not be used simultaneously with \a oauth2AccessToken. */ -@property(readonly) id authTokenProvider; +@property(readonly, nullable) id authTokenProvider; /** * Initial metadata key-value pairs that should be included in the request. */ -@property(copy, readonly) NSDictionary *initialMetadata; +@property(copy, readonly, nullable) NSDictionary *initialMetadata; // Channel parameters; take into account of channel signature. @@ -113,7 +113,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * Custom string that is prefixed to a request's user-agent header field before gRPC's internal * user-agent string. */ -@property(copy, readonly) NSString *userAgentPrefix; +@property(copy, readonly, nullable) NSString *userAgentPrefix; /** * The size limit for the response received from server. If it is exceeded, an error with status @@ -152,7 +152,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * Specify channel args to be used for this call. For a list of channel args available, see * grpc/grpc_types.h */ -@property(copy, readonly) NSDictionary *additionalChannelArgs; +@property(copy, readonly, nullable) NSDictionary *additionalChannelArgs; // Parameters for SSL authentication. @@ -160,17 +160,17 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * PEM format root certifications that is trusted. If set to nil, gRPC uses a list of default * root certificates. */ -@property(copy, readonly) NSString *PEMRootCertificates; +@property(copy, readonly, nullable) NSString *PEMRootCertificates; /** * PEM format private key for client authentication, if required by the server. */ -@property(copy, readonly) NSString *PEMPrivateKey; +@property(copy, readonly, nullable) NSString *PEMPrivateKey; /** * PEM format certificate chain for client authentication, if required by the server. */ -@property(copy, readonly) NSString *PEMCertChain; +@property(copy, readonly, nullable) NSString *PEMCertChain; /** * Select the transport type to be used for this call. @@ -180,13 +180,13 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { /** * Override the hostname during the TLS hostname validation process. */ -@property(copy, readonly) NSString *hostNameOverride; +@property(copy, readonly, nullable) NSString *hostNameOverride; /** * A string that specify the domain where channel is being cached. Channels with different domains * will not get cached to the same connection. */ -@property(copy, readonly) NSString *channelPoolDomain; +@property(copy, readonly, nullable) NSString *channelPoolDomain; /** * Channel id allows control of channel caching within a channelPoolDomain. A call with a unique @@ -199,7 +199,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { /** * Return if the channel options are equal to another object. */ -- (BOOL)hasChannelOptionsEqualTo:(GRPCCallOptions *)callOptions; +- (BOOL)hasChannelOptionsEqualTo:(nonnull GRPCCallOptions *)callOptions; /** * Hash for channel options. @@ -219,7 +219,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * :authority header field of the call and performs an extra check that server's certificate * matches the :authority header. */ -@property(copy, readwrite) NSString *serverAuthority; +@property(copy, readwrite, nullable) NSString *serverAuthority; /** * The timeout for the RPC call in seconds. If set to 0, the call will not timeout. If set to @@ -236,18 +236,18 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * request's "authorization" header field. This parameter should not be used simultaneously with * \a authTokenProvider. */ -@property(copy, readwrite) NSString *oauth2AccessToken; +@property(copy, readwrite, nullable) NSString *oauth2AccessToken; /** * The interface to get the OAuth2 access token string. gRPC will attempt to acquire token when * initiating the call. This parameter should not be used simultaneously with \a oauth2AccessToken. */ -@property(readwrite) id authTokenProvider; +@property(readwrite, nullable) id authTokenProvider; /** * Initial metadata key-value pairs that should be included in the request. */ -@property(copy, readwrite) NSDictionary *initialMetadata; +@property(copy, readwrite, nullable) NSDictionary *initialMetadata; // Channel parameters; take into account of channel signature. @@ -255,7 +255,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * Custom string that is prefixed to a request's user-agent header field before gRPC's internal * user-agent string. */ -@property(copy, readwrite) NSString *userAgentPrefix; +@property(copy, readwrite, nullable) NSString *userAgentPrefix; /** * The size limit for the response received from server. If it is exceeded, an error with status @@ -296,7 +296,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * Specify channel args to be used for this call. For a list of channel args available, see * grpc/grpc_types.h */ -@property(copy, readwrite) NSDictionary *additionalChannelArgs; +@property(copy, readwrite, nullable) NSDictionary *additionalChannelArgs; // Parameters for SSL authentication. @@ -304,17 +304,17 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * PEM format root certifications that is trusted. If set to nil, gRPC uses a list of default * root certificates. */ -@property(copy, readwrite) NSString *PEMRootCertificates; +@property(copy, readwrite, nullable) NSString *PEMRootCertificates; /** * PEM format private key for client authentication, if required by the server. */ -@property(copy, readwrite) NSString *PEMPrivateKey; +@property(copy, readwrite, nullable) NSString *PEMPrivateKey; /** * PEM format certificate chain for client authentication, if required by the server. */ -@property(copy, readwrite) NSString *PEMCertChain; +@property(copy, readwrite, nullable) NSString *PEMCertChain; /** * Select the transport type to be used for this call. @@ -324,7 +324,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { /** * Override the hostname during the TLS hostname validation process. */ -@property(copy, readwrite) NSString *hostNameOverride; +@property(copy, readwrite, nullable) NSString *hostNameOverride; /** * A string that specify the domain where channel is being cached. Channels with different domains @@ -332,7 +332,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * domain 'io.grpc.example' so that its calls do not reuse the channel created by other modules in * the same process. */ -@property(copy, readwrite) NSString *channelPoolDomain; +@property(copy, readwrite, nullable) NSString *channelPoolDomain; /** * Channel id allows a call to force creating a new channel (connection) rather than using a cached diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index 32e68bb2625..4dbe0c276ce 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -85,7 +85,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue callOptions:(GRPCCallOptions *)callOptions - disconnected:(BOOL *_Nullable)disconnected; + disconnected:(nullable BOOL *)disconnected; /** * Unref the channel when a call is done. It also decreases the channel's refcount. If the refcount diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index ab084fba480..de3302598ef 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -39,7 +39,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; @implementation GRPCChannelConfiguration -- (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { +- (instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { NSAssert(host.length, @"Host must not be empty."); NSAssert(callOptions != nil, @"callOptions must not be empty."); if ((self = [super init])) { @@ -143,7 +143,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; return args; } -- (nonnull id)copyWithZone:(nullable NSZone *)zone { +- (id)copyWithZone:(NSZone *)zone { GRPCChannelConfiguration *newConfig = [[GRPCChannelConfiguration alloc] initWithHost:_host callOptions:_callOptions]; @@ -184,13 +184,13 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } @synthesize disconnected = _disconnected; -- (nullable instancetype)initWithChannelConfiguration: +- (instancetype)initWithChannelConfiguration: (GRPCChannelConfiguration *)channelConfiguration { return [self initWithChannelConfiguration:channelConfiguration destroyDelay:kDefaultChannelDestroyDelay]; } -- (nullable instancetype)initWithChannelConfiguration: +- (instancetype)initWithChannelConfiguration: (GRPCChannelConfiguration *)channelConfiguration destroyDelay:(NSTimeInterval)destroyDelay { NSAssert(channelConfiguration != nil, @@ -201,7 +201,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; if (@available(iOS 8.0, *)) { _dispatchQueue = dispatch_queue_create( NULL, - dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); } else { _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); } diff --git a/src/objective-c/GRPCClient/private/GRPCChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h index 3a3500fc95e..a934e966e9d 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelFactory.h @@ -26,8 +26,8 @@ NS_ASSUME_NONNULL_BEGIN @protocol GRPCChannelFactory /** Create a channel with specific channel args to a specific host. */ -- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *_Nullable)args; +- (nullable grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(nullable NSDictionary *)args; @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 6745010bd49..72554ca6dc8 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -41,7 +41,7 @@ static dispatch_once_t gInitChannelPool; NSMutableDictionary *_channelPool; } -+ (nullable instancetype)sharedInstance { ++ (instancetype)sharedInstance { dispatch_once(&gInitChannelPool, ^{ gChannelPool = [[GRPCChannelPool alloc] init]; NSAssert(gChannelPool != nil, @"Cannot initialize global channel pool."); diff --git a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m index a36788b35aa..bb8618ff335 100644 --- a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m +++ b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m @@ -76,14 +76,14 @@ static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReach } } -+ (void)registerObserver:(_Nonnull id)observer selector:(SEL)selector { ++ (void)registerObserver:(id)observer selector:(SEL)selector { [[NSNotificationCenter defaultCenter] addObserver:observer selector:selector name:kGRPCConnectivityNotification object:nil]; } -+ (void)unregisterObserver:(_Nonnull id)observer { ++ (void)unregisterObserver:(id)observer { [[NSNotificationCenter defaultCenter] removeObserver:observer]; } diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m index 781881d211b..74ea9723b3d 100644 --- a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m @@ -26,13 +26,11 @@ #import #include -NS_ASSUME_NONNULL_BEGIN - @implementation GRPCCronetChannelFactory { stream_engine *_cronetEngine; } -+ (instancetype _Nullable)sharedInstance { ++ (instancetype)sharedInstance { static GRPCCronetChannelFactory *instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -41,7 +39,7 @@ NS_ASSUME_NONNULL_BEGIN return instance; } -- (instancetype _Nullable)initWithEngine:(stream_engine *)engine { +- (instancetype)initWithEngine:(stream_engine *)engine { if (!engine) { [NSException raise:NSInvalidArgumentException format:@"Cronet engine is NULL. Set it first."]; return nil; @@ -52,8 +50,8 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *_Nullable)args { +- (grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary *)args { grpc_channel_args *channelArgs = GRPCBuildChannelArgs(args); grpc_channel *unmanagedChannel = grpc_cronet_secure_channel_create(_cronetEngine, host.UTF8String, channelArgs, NULL); @@ -63,22 +61,18 @@ NS_ASSUME_NONNULL_BEGIN @end -NS_ASSUME_NONNULL_END - #else -NS_ASSUME_NONNULL_BEGIN - @implementation GRPCCronetChannelFactory -+ (instancetype _Nullable)sharedInstance { ++ (instancetype)sharedInstance { [NSException raise:NSInvalidArgumentException format:@"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."]; return nil; } -- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *_Nullable)args { +- (grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary *)args { [NSException raise:NSInvalidArgumentException format:@"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."]; return NULL; @@ -86,6 +80,4 @@ NS_ASSUME_NONNULL_BEGIN @end -NS_ASSUME_NONNULL_END - #endif diff --git a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m index 99698877124..3e9ebe7ae02 100644 --- a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m @@ -21,11 +21,9 @@ #import "ChannelArgsUtil.h" #import "GRPCChannel.h" -NS_ASSUME_NONNULL_BEGIN - @implementation GRPCInsecureChannelFactory -+ (instancetype _Nullable)sharedInstance { ++ (instancetype)sharedInstance { static GRPCInsecureChannelFactory *instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -34,8 +32,8 @@ NS_ASSUME_NONNULL_BEGIN return instance; } -- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *_Nullable)args { +- (grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary *)args { grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs([args copy]); grpc_channel *unmanagedChannel = grpc_insecure_channel_create(host.UTF8String, coreChannelArgs, NULL); @@ -44,5 +42,3 @@ NS_ASSUME_NONNULL_BEGIN } @end - -NS_ASSUME_NONNULL_END diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index f5e7a2b9e20..2e7f1a0dbe2 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -24,15 +24,13 @@ #import "GRPCChannel.h" #import "utilities.h" -NS_ASSUME_NONNULL_BEGIN - @implementation GRPCSecureChannelFactory { grpc_channel_credentials *_channelCreds; } -+ (instancetype _Nullable)factoryWithPEMRootCertificates:(NSString *_Nullable)rootCerts - privateKey:(NSString *_Nullable)privateKey - certChain:(NSString *_Nullable)certChain ++ (instancetype)factoryWithPEMRootCertificates:(NSString *)rootCerts + privateKey:(NSString *)privateKey + certChain:(NSString *)certChain error:(NSError **)errorPtr { return [[self alloc] initWithPEMRootCerts:rootCerts privateKey:privateKey @@ -40,7 +38,7 @@ NS_ASSUME_NONNULL_BEGIN error:errorPtr]; } -- (NSData *_Nullable)nullTerminatedDataWithString:(NSString *_Nullable)string { +- (NSData *)nullTerminatedDataWithString:(NSString *)string { // dataUsingEncoding: does not return a null-terminated string. NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; if (data == nil) { @@ -51,9 +49,9 @@ NS_ASSUME_NONNULL_BEGIN return nullTerminated; } -- (instancetype _Nullable)initWithPEMRootCerts:(NSString *_Nullable)rootCerts - privateKey:(NSString *_Nullable)privateKey - certChain:(NSString *_Nullable)certChain +- (instancetype)initWithPEMRootCerts:(NSString *)rootCerts + privateKey:(NSString *)privateKey + certChain:(NSString *)certChain error:(NSError **)errorPtr { static NSData *defaultRootsASCII; static NSError *defaultRootsError; @@ -117,8 +115,8 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *_Nullable)args { +- (grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(NSDictionary *)args { grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs([args copy]); grpc_channel *unmanagedChannel = grpc_secure_channel_create(_channelCreds, host.UTF8String, coreChannelArgs, NULL); @@ -133,5 +131,3 @@ NS_ASSUME_NONNULL_BEGIN } @end - -NS_ASSUME_NONNULL_END diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index b0f4ced99e8..dc776368a8f 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -33,13 +33,13 @@ NS_ASSUME_NONNULL_BEGIN /** * Issued when initial metadata is received from the server. The task must be scheduled onto the * dispatch queue in property \a dispatchQueue. */ -- (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata; +- (void)receivedInitialMetadata:(nullable NSDictionary *)initialMetadata; /** * Issued when a message is received from the server. The message is the deserialized proto object. * The task must be scheduled onto the dispatch queue in property \a dispatchQueue. */ -- (void)receivedProtoMessage:(GPBMessage *_Nullable)message; +- (void)receivedProtoMessage:(nullable GPBMessage *)message; /** * Issued when a call finished. If the call finished successfully, \a error is nil and \a @@ -48,8 +48,8 @@ NS_ASSUME_NONNULL_BEGIN * error descriptions. The task must be scheduled onto the dispatch queue in property * \a dispatchQueue. */ -- (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata - error:(NSError *_Nullable)error; +- (void)closedWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata + error:(nullable NSError *)error; @required @@ -75,7 +75,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions message:(GPBMessage *)message responseHandler:(id)handler - callOptions:(GRPCCallOptions *_Nullable)callOptions + callOptions:(nullable GRPCCallOptions *)callOptions responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; /** @@ -100,7 +100,7 @@ NS_ASSUME_NONNULL_BEGIN */ - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)handler - callOptions:(GRPCCallOptions *_Nullable)callOptions + callOptions:(nullable GRPCCallOptions *)callOptions responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; /** diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 34891e8953b..f99da45fef9 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -52,7 +52,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions message:(GPBMessage *)message responseHandler:(id)handler - callOptions:(GRPCCallOptions *_Nullable)callOptions + callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass { if ((self = [super init])) { _call = [[GRPCStreamingProtoCall alloc] initWithRequestOptions:requestOptions @@ -88,7 +88,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions responseHandler:(id)handler - callOptions:(GRPCCallOptions *_Nullable)callOptions + callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass { if (requestOptions.host.length == 0 || requestOptions.path.length == 0) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; @@ -108,7 +108,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing if (@available(iOS 8.0, *)) { _dispatchQueue = dispatch_queue_create( NULL, - dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, -1)); + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); } else { _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); } @@ -171,7 +171,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing }); } -- (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { +- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { dispatch_async(_dispatchQueue, ^{ if (initialMetadata != nil && [self->_handler respondsToSelector:@selector(initialMetadata:)]) { [self->_handler receivedInitialMetadata:initialMetadata]; @@ -179,7 +179,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing }); } -- (void)receivedRawMessage:(NSData *_Nullable)message { +- (void)receivedRawMessage:(NSData *)message { dispatch_async(_dispatchQueue, ^{ if (self->_handler && message != nil) { NSError *error = nil; @@ -202,8 +202,8 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing }); } -- (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata - error:(NSError *_Nullable)error { +- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata + error:(NSError *)error { dispatch_async(_dispatchQueue, ^{ if ([self->_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { [self->_handler closedWithTrailingMetadata:trailingMetadata error:error]; diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index c42718f15ee..dcc8f1b589a 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -102,7 +102,7 @@ BOOL isRemoteInteropTest(NSString *host) { return self; } -- (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { +- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { dispatch_async(_dispatchQueue, ^{ if (_initialMetadataCallback) { _initialMetadataCallback(initialMetadata); @@ -110,7 +110,7 @@ BOOL isRemoteInteropTest(NSString *host) { }); } -- (void)receivedProtoMessage:(GPBMessage *_Nullable)message { +- (void)receivedProtoMessage:(GPBMessage *)message { dispatch_async(_dispatchQueue, ^{ if (_messageCallback) { _messageCallback(message); @@ -118,8 +118,8 @@ BOOL isRemoteInteropTest(NSString *host) { }); } -- (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata - error:(NSError *_Nullable)error { +- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata + error:(NSError *)error { dispatch_async(_dispatchQueue, ^{ if (_closeCallback) { _closeCallback(trailingMetadata, error); From 0911e489e3fe22e2ca5d7c927dac83358f2f05b7 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 15 Nov 2018 13:55:56 -0800 Subject: [PATCH 187/375] Add a method to check whether the message was received successfully --- include/grpcpp/impl/codegen/call_op_set.h | 6 ++++-- include/grpcpp/impl/codegen/interceptor.h | 3 +++ include/grpcpp/impl/codegen/interceptor_common.h | 10 ++++++++++ test/cpp/end2end/client_interceptors_end2end_test.cc | 12 ++++++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index aae8b9d3e37..3699ec94f2f 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -406,12 +406,13 @@ class CallOpRecvMessage { void SetInterceptionHookPoint( InterceptorBatchMethodsImpl* interceptor_methods) { + if (message_ == nullptr) return; interceptor_methods->SetRecvMessage(message_, &got_message); } void SetFinishInterceptionHookPoint( InterceptorBatchMethodsImpl* interceptor_methods) { - if (!got_message) return; + if (message_ == nullptr) return; interceptor_methods->AddInterceptionHookPoint( experimental::InterceptionHookPoints::POST_RECV_MESSAGE); } @@ -501,12 +502,13 @@ class CallOpGenericRecvMessage { void SetInterceptionHookPoint( InterceptorBatchMethodsImpl* interceptor_methods) { + if (!deserialize_) return; interceptor_methods->SetRecvMessage(message_, &got_message); } void SetFinishInterceptionHookPoint( InterceptorBatchMethodsImpl* interceptor_methods) { - if (!got_message) return; + if (!deserialize_) return; interceptor_methods->AddInterceptionHookPoint( experimental::InterceptionHookPoints::POST_RECV_MESSAGE); } diff --git a/include/grpcpp/impl/codegen/interceptor.h b/include/grpcpp/impl/codegen/interceptor.h index 943376a5451..b977c350166 100644 --- a/include/grpcpp/impl/codegen/interceptor.h +++ b/include/grpcpp/impl/codegen/interceptor.h @@ -103,6 +103,9 @@ class InterceptorBatchMethods { // is already deserialized virtual void* GetRecvMessage() = 0; + // Checks whether the RECV MESSAGE op completed successfully + virtual bool GetRecvMessageStatus() = 0; + // Returns a modifiable multimap of the received initial metadata virtual std::multimap* GetRecvInitialMetadata() = 0; diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index d23b71f8a77..b2e92dd6f3d 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -103,6 +103,8 @@ class InterceptorBatchMethodsImpl void* GetRecvMessage() override { return recv_message_; } + bool GetRecvMessageStatus() override { return *got_message_; } + std::multimap* GetRecvInitialMetadata() override { return recv_initial_metadata_->map(); @@ -432,6 +434,14 @@ class CancelInterceptorBatchMethods return nullptr; } + bool GetRecvMessageStatus() override { + GPR_CODEGEN_ASSERT( + false && + "It is illegal to call GetRecvMessageStatus on a method which " + "has a Cancel notification"); + return false; + } + std::multimap* GetRecvInitialMetadata() override { GPR_CODEGEN_ASSERT(false && diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 459788ba519..4d4760a6524 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -325,6 +325,12 @@ class ServerStreamingRpcHijackingInterceptor static_cast(methods->GetRecvMessage()); resp->set_message("Hello"); } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { + // Only the last message will be a failure + EXPECT_FALSE(got_failed_message_); + got_failed_message_ = !methods->GetRecvMessageStatus(); + } if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { auto* map = methods->GetRecvTrailingMetadata(); @@ -341,11 +347,16 @@ class ServerStreamingRpcHijackingInterceptor } } + static bool GotFailedMessage() { return got_failed_message_; } + private: experimental::ClientRpcInfo* info_; + static bool got_failed_message_; int count_ = 0; }; +bool ServerStreamingRpcHijackingInterceptor::got_failed_message_ = false; + class ServerStreamingRpcHijackingInterceptorFactory : public experimental::ClientInterceptorFactoryInterface { public: @@ -634,6 +645,7 @@ TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingHijackingTest) { auto channel = experimental::CreateCustomChannelWithInterceptors( server_address_, InsecureChannelCredentials(), args, std::move(creators)); MakeServerStreamingCall(channel); + EXPECT_TRUE(ServerStreamingRpcHijackingInterceptor::GotFailedMessage()); } TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingTest) { From 57464321214a5ce34e5de1868ce4eb3624ebdebb Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 15 Nov 2018 14:00:51 -0800 Subject: [PATCH 188/375] Fix handler release - Part 1 --- src/objective-c/GRPCClient/GRPCCall.h | 9 +++---- src/objective-c/ProtoRPC/ProtoRPC.h | 7 ++---- src/objective-c/tests/APIv2Tests/APIv2Tests.m | 24 +++++++------------ src/objective-c/tests/InteropTests.m | 24 +++++++------------ 4 files changed, 23 insertions(+), 41 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index fcda4dc8acd..7f80c17f1f3 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -156,15 +156,13 @@ extern NSString *const kGRPCTrailersKey; @optional /** - * Issued when initial metadata is received from the server. The task must be scheduled onto the - * dispatch queue in property \a dispatchQueue. + * Issued when initial metadata is received from the server. */ - (void)receivedInitialMetadata:(nullable NSDictionary *)initialMetadata; /** * Issued when a message is received from the server. The message is the raw data received from the - * server, with decompression and without proto deserialization. The task must be scheduled onto the - * dispatch queue in property \a dispatchQueue. + * server, with decompression and without proto deserialization. */ - (void)receivedRawMessage:(nullable NSData *)message; @@ -172,8 +170,7 @@ extern NSString *const kGRPCTrailersKey; * Issued when a call finished. If the call finished successfully, \a error is nil and \a * trainingMetadata consists any trailing metadata received from the server. Otherwise, \a error * is non-nil and contains the corresponding error information, including gRPC error codes and - * error descriptions. The task must be scheduled onto the dispatch queue in property - * \a dispatchQueue. + * error descriptions. */ - (void)closedWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata error:(nullable NSError *)error; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index dc776368a8f..569aaa79e4d 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -31,13 +31,11 @@ NS_ASSUME_NONNULL_BEGIN @optional /** - * Issued when initial metadata is received from the server. The task must be scheduled onto the - * dispatch queue in property \a dispatchQueue. */ + * Issued when initial metadata is received from the server. - (void)receivedInitialMetadata:(nullable NSDictionary *)initialMetadata; /** * Issued when a message is received from the server. The message is the deserialized proto object. - * The task must be scheduled onto the dispatch queue in property \a dispatchQueue. */ - (void)receivedProtoMessage:(nullable GPBMessage *)message; @@ -45,8 +43,7 @@ NS_ASSUME_NONNULL_BEGIN * Issued when a call finished. If the call finished successfully, \a error is nil and \a * trainingMetadata consists any trailing metadata received from the server. Otherwise, \a error * is non-nil and contains the corresponding error information, including gRPC error codes and - * error descriptions. The task must be scheduled onto the dispatch queue in property - * \a dispatchQueue. + * error descriptions. */ - (void)closedWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata error:(nullable NSError *)error; diff --git a/src/objective-c/tests/APIv2Tests/APIv2Tests.m b/src/objective-c/tests/APIv2Tests/APIv2Tests.m index 28f94cd8c77..e49f58ae9d3 100644 --- a/src/objective-c/tests/APIv2Tests/APIv2Tests.m +++ b/src/objective-c/tests/APIv2Tests/APIv2Tests.m @@ -82,28 +82,22 @@ static const NSTimeInterval kTestTimeout = 16; } - (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { - dispatch_async(_dispatchQueue, ^{ - if (self->_initialMetadataCallback) { - self->_initialMetadataCallback(initialMetadata); - } - }); + if (self->_initialMetadataCallback) { + self->_initialMetadataCallback(initialMetadata); + } } - (void)receivedRawMessage:(GPBMessage *_Nullable)message { - dispatch_async(_dispatchQueue, ^{ - if (self->_messageCallback) { - self->_messageCallback(message); - } - }); + if (self->_messageCallback) { + self->_messageCallback(message); + } } - (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata error:(NSError *_Nullable)error { - dispatch_async(_dispatchQueue, ^{ - if (self->_closeCallback) { - self->_closeCallback(trailingMetadata, error); - } - }); + if (self->_closeCallback) { + self->_closeCallback(trailingMetadata, error); + } } - (dispatch_queue_t)dispatchQueue { diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index dcc8f1b589a..8754bd5ccaf 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -103,28 +103,22 @@ BOOL isRemoteInteropTest(NSString *host) { } - (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { - dispatch_async(_dispatchQueue, ^{ - if (_initialMetadataCallback) { - _initialMetadataCallback(initialMetadata); - } - }); + if (_initialMetadataCallback) { + _initialMetadataCallback(initialMetadata); + } } - (void)receivedProtoMessage:(GPBMessage *)message { - dispatch_async(_dispatchQueue, ^{ - if (_messageCallback) { - _messageCallback(message); - } - }); + if (_messageCallback) { + _messageCallback(message); + } } - (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { - dispatch_async(_dispatchQueue, ^{ - if (_closeCallback) { - _closeCallback(trailingMetadata, error); - } - }); + if (_closeCallback) { + _closeCallback(trailingMetadata, error); + } } - (dispatch_queue_t)dispatchQueue { From ffeb0e682393e5b76d732e0b034c71f3837b9e57 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 15 Nov 2018 14:56:50 -0800 Subject: [PATCH 189/375] Add *if* after assert --- src/objective-c/GRPCClient/GRPCCall.m | 54 +++++++++++++++++++ .../GRPCClient/private/GRPCChannel.m | 25 +++++++-- .../GRPCClient/private/GRPCChannelPool.m | 3 ++ 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 68b51d8c846..f340e2bd8c2 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -69,6 +69,12 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety { NSAssert(host.length != 0 && path.length != 0, @"Host and Path cannot be empty"); + if (host.length == 0) { + host = [NSString string]; + } + if (path.length == 0) { + path = [NSString string]; + } if ((self = [super init])) { _host = [host copy]; _path = [path copy]; @@ -120,6 +126,16 @@ const char *kCFStreamVarName = "grpc_cfstream"; NSAssert(requestOptions.safety <= GRPCCallSafetyCacheableRequest, @"Invalid call safety value."); NSAssert(responseHandler != nil, @"Response handler required."); + if (requestOptions.host.length == 0 || requestOptions.path.length == 0) { + return nil; + } + if (requestOptions.safety > GRPCCallSafetyCacheableRequest) { + return nil; + } + if (responseHandler == nil) { + return nil; + } + if ((self = [super init])) { _requestOptions = [requestOptions copy]; @@ -158,6 +174,13 @@ const char *kCFStreamVarName = "grpc_cfstream"; dispatch_async(_dispatchQueue, ^{ NSAssert(!self->_started, @"Call already started."); NSAssert(!self->_canceled, @"Call already canceled."); + if (self->_started) { + return; + } + if (self->_canceled) { + return; + } + self->_started = YES; if (!self->_callOptions) { self->_callOptions = [[GRPCCallOptions alloc] init]; @@ -218,6 +241,10 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)cancel { dispatch_async(_dispatchQueue, ^{ NSAssert(!self->_canceled, @"Call already canceled."); + if (self->_canceled) { + return; + } + self->_canceled = YES; if (self->_call) { [self->_call cancel]; @@ -248,6 +275,13 @@ const char *kCFStreamVarName = "grpc_cfstream"; dispatch_async(_dispatchQueue, ^{ NSAssert(!self->_canceled, @"Call arleady canceled."); NSAssert(!self->_finished, @"Call is half-closed before sending data."); + if (self->_canceled) { + return; + } + if (self->_finished) { + return; + } + if (self->_pipe) { [self->_pipe writeValue:data]; } @@ -259,6 +293,16 @@ const char *kCFStreamVarName = "grpc_cfstream"; NSAssert(self->_started, @"Call not started."); NSAssert(!self->_canceled, @"Call arleady canceled."); NSAssert(!self->_finished, @"Call already half-closed."); + if (!self->_started) { + return; + } + if (self->_canceled) { + return; + } + if (self->_finished) { + return; + } + if (self->_pipe) { [self->_pipe writesFinishedWithError:nil]; } @@ -412,6 +456,16 @@ const char *kCFStreamVarName = "grpc_cfstream"; @"Invalid call safety value."); NSAssert(requestWriter.state == GRXWriterStateNotStarted, @"The requests writer can't be already started."); + if (!host || !path) { + return nil; + } + if (safety > GRPCCallSafetyCacheableRequest) { + return nil; + } + if (requestWriter.state != GRXWriterStateNotStarted) { + return nil; + } + if ((self = [super init])) { _host = [host copy]; _path = [path copy]; diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index de3302598ef..a19802b0106 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -40,8 +40,11 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; @implementation GRPCChannelConfiguration - (instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { - NSAssert(host.length, @"Host must not be empty."); + NSAssert(host.length > 0, @"Host must not be empty."); NSAssert(callOptions != nil, @"callOptions must not be empty."); + if (host.length == 0) return nil; + if (callOptions == nil) return nil; + if ((self = [super init])) { _host = [host copy]; _callOptions = [callOptions copy]; @@ -196,6 +199,9 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; NSAssert(channelConfiguration != nil, @"channelConfiguration must not be empty."); NSAssert(destroyDelay > 0, @"destroyDelay must be greater than 0."); + if (channelConfiguration == nil) return nil; + if (destroyDelay <= 0) return nil; + if ((self = [super init])) { _configuration = [channelConfiguration copy]; if (@available(iOS 8.0, *)) { @@ -219,6 +225,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } id factory = channelConfiguration.channelFactory; _unmanagedChannel = [factory createChannelWithHost:host channelArgs:channelArgs]; + NSAssert(_unmanagedChannel != NULL, @"Failed to create channel"); if (_unmanagedChannel == NULL) { NSLog(@"Unable to create channel."); return nil; @@ -233,9 +240,13 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; completionQueue:(GRPCCompletionQueue *)queue callOptions:(GRPCCallOptions *)callOptions disconnected:(BOOL *)disconnected { - NSAssert(path.length, @"path must not be empty."); - NSAssert(queue, @"completionQueue must not be empty."); - NSAssert(callOptions, @"callOptions must not be empty."); + NSAssert(path.length > 0, @"path must not be empty."); + NSAssert(queue != nil, @"completionQueue must not be empty."); + NSAssert(callOptions != nil, @"callOptions must not be empty."); + if (path.length == 0) return nil; + if (queue == nil) return nil; + if (callOptions == nil) return nil; + __block BOOL isDisconnected = NO; __block grpc_call *call = NULL; dispatch_sync(_dispatchQueue, ^{ @@ -244,11 +255,13 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } else { NSAssert(self->_unmanagedChannel != NULL, @"Channel should have valid unmanaged channel."); + if (self->_unmanagedChannel == NULL) return; NSString *serverAuthority = callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; NSTimeInterval timeout = callOptions.timeout; NSAssert(timeout >= 0, @"Invalid timeout"); + if (timeout < 0) return; grpc_slice host_slice = grpc_empty_slice(); if (serverAuthority) { host_slice = grpc_slice_from_copied_string(serverAuthority.UTF8String); @@ -292,6 +305,10 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; NSLog(@"unref"); dispatch_async(_dispatchQueue, ^{ NSAssert(self->_refcount > 0, @"Illegal reference count."); + if (self->_refcount == 0) { + NSLog(@"Illegal reference count."); + return; + } self->_refcount--; if (self->_refcount == 0 && !self->_disconnected) { // Start timer. diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 72554ca6dc8..5e2e9bcfebb 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -71,6 +71,9 @@ static dispatch_once_t gInitChannelPool; destroyDelay:(NSTimeInterval)destroyDelay { NSAssert(host.length > 0, @"Host must not be empty."); NSAssert(callOptions != nil, @"callOptions must not be empty."); + if (host.length == 0) return nil; + if (callOptions == nil) return nil; + GRPCChannel *channel; GRPCChannelConfiguration *configuration = [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; From d4ebd30eb2eb94f77ac9b52c44880e3d70c6aef0 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 15 Nov 2018 15:57:43 -0800 Subject: [PATCH 190/375] Add method to get status of send message op on POST_SEND_MESSAGE --- include/grpcpp/impl/codegen/call_op_set.h | 18 ++++++++++++++++-- include/grpcpp/impl/codegen/interceptor.h | 6 +++++- .../grpcpp/impl/codegen/interceptor_common.h | 10 ++++++++++ .../client_interceptors_end2end_test.cc | 18 ++++++++++++++++-- 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index 1f2b88e9e14..f330679ffc9 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -315,9 +315,16 @@ class CallOpSendMessage { write_options_.Clear(); } void FinishOp(bool* status) { - send_buf_.Clear(); + if (!send_buf_.Valid()) { + return; + } if (hijacked_ && failed_send_) { + // Hijacking interceptor failed this Op *status = false; + } else if (!*status) { + // This Op was passed down to core and the Op failed + gpr_log(GPR_ERROR, "failure status"); + failed_send_ = true; } } @@ -330,7 +337,14 @@ class CallOpSendMessage { } void SetFinishInterceptionHookPoint( - InterceptorBatchMethodsImpl* interceptor_methods) {} + InterceptorBatchMethodsImpl* interceptor_methods) { + if (send_buf_.Valid()) { + interceptor_methods->AddInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_SEND_MESSAGE); + // We had already registered failed_send_ earlier. No need to do it again. + } + send_buf_.Clear(); + } void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) { hijacked_ = true; diff --git a/include/grpcpp/impl/codegen/interceptor.h b/include/grpcpp/impl/codegen/interceptor.h index 47239332c86..154172dd814 100644 --- a/include/grpcpp/impl/codegen/interceptor.h +++ b/include/grpcpp/impl/codegen/interceptor.h @@ -41,9 +41,10 @@ class InterceptedMessage { }; enum class InterceptionHookPoints { - /* The first two in this list are for clients and servers */ + /* The first three in this list are for clients and servers */ PRE_SEND_INITIAL_METADATA, PRE_SEND_MESSAGE, + POST_SEND_MESSAGE, PRE_SEND_STATUS /* server only */, PRE_SEND_CLOSE /* client only */, /* The following three are for hijacked clients only and can only be @@ -85,6 +86,9 @@ class InterceptorBatchMethods { // sent virtual ByteBuffer* GetSendMessage() = 0; + // Checks whether the SEND MESSAGE op succeeded + virtual bool GetSendMessageStatus() = 0; + // Returns a modifiable multimap of the initial metadata to be sent virtual std::multimap* GetSendInitialMetadata() = 0; diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index 601a929afe6..21326df73be 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -81,6 +81,8 @@ class InterceptorBatchMethodsImpl ByteBuffer* GetSendMessage() override { return send_message_; } + bool GetSendMessageStatus() override { return !*fail_send_message_; } + std::multimap* GetSendInitialMetadata() override { return send_initial_metadata_; } @@ -113,6 +115,7 @@ class InterceptorBatchMethodsImpl void FailHijackedSendMessage() override { GPR_CODEGEN_ASSERT(hooks_[static_cast( experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)]); + gpr_log(GPR_ERROR, "failing"); *fail_send_message_ = true; } @@ -396,6 +399,13 @@ class CancelInterceptorBatchMethods return nullptr; } + bool GetSendMessageStatus() override { + GPR_CODEGEN_ASSERT( + false && + "It is illegal to call GetSendMessageStatus on a method which " + "has a Cancel notification"); + } + std::multimap* GetSendInitialMetadata() override { GPR_CODEGEN_ASSERT(false && "It is illegal to call GetSendInitialMetadata on a " diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 81efd154525..97947e73931 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -287,6 +287,13 @@ class ClientStreamingRpcHijackingInterceptor methods->FailHijackedSendMessage(); } } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_SEND_MESSAGE)) { + EXPECT_FALSE(got_failed_send_); + gpr_log(GPR_ERROR, "%d", got_failed_send_); + got_failed_send_ = !methods->GetSendMessageStatus(); + gpr_log(GPR_ERROR, "%d", got_failed_send_); + } if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { auto* status = methods->GetRecvStatus(); @@ -299,10 +306,16 @@ class ClientStreamingRpcHijackingInterceptor } } + static bool GotFailedSend() { return got_failed_send_; } + private: experimental::ClientRpcInfo* info_; int count_ = 0; + static bool got_failed_send_; }; + +bool ClientStreamingRpcHijackingInterceptor::got_failed_send_ = false; + class ClientStreamingRpcHijackingInterceptorFactory : public experimental::ClientInterceptorFactoryInterface { public: @@ -602,10 +615,11 @@ TEST_F(ClientInterceptorsStreamingEnd2endTest, ClientStreamingHijackingTest) { EXPECT_TRUE(writer->Write(req)); expected_resp += "Hello"; } - // Expect that the interceptor will reject the 11th message - EXPECT_FALSE(writer->Write(req)); + // The interceptor will reject the 11th message + writer->Write(req); Status s = writer->Finish(); EXPECT_EQ(s.ok(), false); + EXPECT_TRUE(ClientStreamingRpcHijackingInterceptor::GotFailedSend()); } TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingTest) { From 00c9c40004d011f01c72d253a530edb3364992bf Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 15 Nov 2018 16:00:33 -0800 Subject: [PATCH 191/375] Remove extraneous logging statements --- include/grpcpp/impl/codegen/call_op_set.h | 1 - include/grpcpp/impl/codegen/interceptor_common.h | 1 - test/cpp/end2end/client_interceptors_end2end_test.cc | 2 -- 3 files changed, 4 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index f330679ffc9..ac3ba17bd9d 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -323,7 +323,6 @@ class CallOpSendMessage { *status = false; } else if (!*status) { // This Op was passed down to core and the Op failed - gpr_log(GPR_ERROR, "failure status"); failed_send_ = true; } } diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index 21326df73be..321691236be 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -115,7 +115,6 @@ class InterceptorBatchMethodsImpl void FailHijackedSendMessage() override { GPR_CODEGEN_ASSERT(hooks_[static_cast( experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)]); - gpr_log(GPR_ERROR, "failing"); *fail_send_message_ = true; } diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 97947e73931..3708c11235a 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -290,9 +290,7 @@ class ClientStreamingRpcHijackingInterceptor if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::POST_SEND_MESSAGE)) { EXPECT_FALSE(got_failed_send_); - gpr_log(GPR_ERROR, "%d", got_failed_send_); got_failed_send_ = !methods->GetSendMessageStatus(); - gpr_log(GPR_ERROR, "%d", got_failed_send_); } if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { From 512c01bc574ab09129608bc501d80f06503c79a3 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 15 Nov 2018 16:59:31 -0800 Subject: [PATCH 192/375] Polish threading + something else --- src/objective-c/GRPCClient/GRPCCall.m | 241 ++++++++++-------- .../GRPCClient/private/GRPCChannel.m | 1 - src/objective-c/ProtoRPC/ProtoRPC.h | 1 + src/objective-c/ProtoRPC/ProtoRPC.m | 123 +++++---- 4 files changed, 209 insertions(+), 157 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index f340e2bd8c2..ede16b42e8c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -155,7 +155,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Fallback on earlier versions _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); } - dispatch_set_target_queue(responseHandler.dispatchQueue, _dispatchQueue); + dispatch_set_target_queue(_dispatchQueue ,responseHandler.dispatchQueue); _started = NO; _canceled = NO; _finished = NO; @@ -171,161 +171,194 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)start { - dispatch_async(_dispatchQueue, ^{ - NSAssert(!self->_started, @"Call already started."); - NSAssert(!self->_canceled, @"Call already canceled."); - if (self->_started) { + GRPCCall *call = nil; + @synchronized (self) { + NSAssert(!_started, @"Call already started."); + NSAssert(!_canceled, @"Call already canceled."); + if (_started) { return; } - if (self->_canceled) { + if (_canceled) { return; } - self->_started = YES; - if (!self->_callOptions) { - self->_callOptions = [[GRPCCallOptions alloc] init]; + _started = YES; + if (!_callOptions) { + _callOptions = [[GRPCCallOptions alloc] init]; } - self->_call = [[GRPCCall alloc] initWithHost:self->_requestOptions.host - path:self->_requestOptions.path - callSafety:self->_requestOptions.safety - requestsWriter:self->_pipe - callOptions:self->_callOptions]; - if (self->_callOptions.initialMetadata) { - [self->_call.requestHeaders addEntriesFromDictionary:self->_callOptions.initialMetadata]; + _call = [[GRPCCall alloc] initWithHost:_requestOptions.host + path:_requestOptions.path + callSafety:_requestOptions.safety + requestsWriter:_pipe + callOptions:_callOptions]; + if (_callOptions.initialMetadata) { + [_call.requestHeaders addEntriesFromDictionary:_callOptions.initialMetadata]; } + call = _call; + } - void (^valueHandler)(id value) = ^(id value) { - dispatch_async(self->_dispatchQueue, ^{ - if (self->_handler) { - if (!self->_initialMetadataPublished) { - self->_initialMetadataPublished = YES; - [self issueInitialMetadata:self->_call.responseHeaders]; - } - if (value) { - [self issueMessage:value]; - } + void (^valueHandler)(id value) = ^(id value) { + @synchronized (self) { + if (self->_handler) { + if (!self->_initialMetadataPublished) { + self->_initialMetadataPublished = YES; + [self issueInitialMetadata:self->_call.responseHeaders]; } - }); - }; - void (^completionHandler)(NSError *errorOrNil) = ^(NSError *errorOrNil) { - dispatch_async(self->_dispatchQueue, ^{ - if (self->_handler) { - if (!self->_initialMetadataPublished) { - self->_initialMetadataPublished = YES; - [self issueInitialMetadata:self->_call.responseHeaders]; - } - [self issueClosedWithTrailingMetadata:self->_call.responseTrailers error:errorOrNil]; - - // Clean up _handler so that no more responses are reported to the handler. - self->_handler = nil; + if (value) { + [self issueMessage:value]; } - // Clearing _call must happen *after* dispatching close in order to get trailing - // metadata from _call. - if (self->_call) { - // Clean up the request writers. This should have no effect to _call since its - // response writeable is already nullified. - [self->_pipe writesFinishedWithError:nil]; - self->_call = nil; - self->_pipe = nil; + } + } + }; + void (^completionHandler)(NSError *errorOrNil) = ^(NSError *errorOrNil) { + @synchronized(self) { + if (self->_handler) { + if (!self->_initialMetadataPublished) { + self->_initialMetadataPublished = YES; + [self issueInitialMetadata:self->_call.responseHeaders]; } - }); - }; - id responseWriteable = - [[GRXWriteable alloc] initWithValueHandler:valueHandler - completionHandler:completionHandler]; - [self->_call startWithWriteable:responseWriteable]; - }); + [self issueClosedWithTrailingMetadata:self->_call.responseTrailers error:errorOrNil]; + + } + // Clearing _call must happen *after* dispatching close in order to get trailing + // metadata from _call. + if (self->_call) { + // Clean up the request writers. This should have no effect to _call since its + // response writeable is already nullified. + [self->_pipe writesFinishedWithError:nil]; + self->_call = nil; + self->_pipe = nil; + } + } + }; + id responseWriteable = + [[GRXWriteable alloc] initWithValueHandler:valueHandler + completionHandler:completionHandler]; + [call startWithWriteable:responseWriteable]; } - (void)cancel { - dispatch_async(_dispatchQueue, ^{ - NSAssert(!self->_canceled, @"Call already canceled."); - if (self->_canceled) { + GRPCCall *call = nil; + @synchronized (self) { + if (_canceled) { return; } - self->_canceled = YES; - if (self->_call) { - [self->_call cancel]; - self->_call = nil; - self->_pipe = nil; - } - if (self->_handler) { - id handler = self->_handler; - dispatch_async(handler.dispatchQueue, ^{ - if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - [handler closedWithTrailingMetadata:nil - error:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeCancelled - userInfo:@{ - NSLocalizedDescriptionKey : - @"Canceled by app" - }]]; + _canceled = YES; + + call = _call; + _call = nil; + _pipe = nil; + + if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + dispatch_async(_dispatchQueue, ^{ + // Copy to local so that block is freed after cancellation completes. + id copiedHandler = nil; + @synchronized (self) { + copiedHandler = self->_handler; + self->_handler = nil; } - }); - // Clean up _handler so that no more responses are reported to the handler. - self->_handler = nil; + [copiedHandler closedWithTrailingMetadata:nil + error:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeCancelled + userInfo:@{ + NSLocalizedDescriptionKey : + @"Canceled by app" + }]]; + }); } - }); + } + [call cancel]; } - (void)writeData:(NSData *)data { - dispatch_async(_dispatchQueue, ^{ - NSAssert(!self->_canceled, @"Call arleady canceled."); - NSAssert(!self->_finished, @"Call is half-closed before sending data."); - if (self->_canceled) { + GRXBufferedPipe *pipe = nil; + @synchronized(self) { + NSAssert(!_canceled, @"Call arleady canceled."); + NSAssert(!_finished, @"Call is half-closed before sending data."); + if (_canceled) { return; } - if (self->_finished) { + if (_finished) { return; } - if (self->_pipe) { - [self->_pipe writeValue:data]; + if (_pipe) { + pipe = _pipe; } - }); + } + [pipe writeValue:data]; } - (void)finish { - dispatch_async(_dispatchQueue, ^{ - NSAssert(self->_started, @"Call not started."); - NSAssert(!self->_canceled, @"Call arleady canceled."); - NSAssert(!self->_finished, @"Call already half-closed."); - if (!self->_started) { + GRXBufferedPipe *pipe = nil; + @synchronized(self) { + NSAssert(_started, @"Call not started."); + NSAssert(!_canceled, @"Call arleady canceled."); + NSAssert(!_finished, @"Call already half-closed."); + if (!_started) { return; } - if (self->_canceled) { + if (_canceled) { return; } - if (self->_finished) { + if (_finished) { return; } - if (self->_pipe) { - [self->_pipe writesFinishedWithError:nil]; + if (_pipe) { + pipe = _pipe; + _pipe = nil; } - self->_pipe = nil; - self->_finished = YES; - }); + _finished = YES; + } + [pipe writesFinishedWithError:nil]; } - (void)issueInitialMetadata:(NSDictionary *)initialMetadata { - if (initialMetadata != nil && [_handler respondsToSelector:@selector(receivedInitialMetadata:)]) { - [_handler receivedInitialMetadata:initialMetadata]; + @synchronized (self) { + if (initialMetadata != nil && [_handler respondsToSelector:@selector(receivedInitialMetadata:)]) { + dispatch_async(_dispatchQueue, ^{ + id handler = nil; + @synchronized (self) { + handler = self->_handler; + } + [handler receivedInitialMetadata:initialMetadata]; + }); + } } } - (void)issueMessage:(id)message { - if (message != nil && [_handler respondsToSelector:@selector(receivedRawMessage:)]) { - [_handler receivedRawMessage:message]; + @synchronized (self) { + if (message != nil && [_handler respondsToSelector:@selector(receivedRawMessage:)]) { + dispatch_async(_dispatchQueue, ^{ + id handler = nil; + @synchronized (self) { + handler = self->_handler; + } + [handler receivedRawMessage:message]; + }); + } } } - (void)issueClosedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { - if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - [_handler closedWithTrailingMetadata:trailingMetadata error:error]; + @synchronized (self) { + if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + dispatch_async(_dispatchQueue, ^{ + id handler = nil; + @synchronized (self) { + handler = self->_handler; + // Clean up _handler so that no more responses are reported to the handler. + self->_handler = nil; + } + [handler closedWithTrailingMetadata:trailingMetadata + error:error]; + }); + } } } diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index a19802b0106..997d1ff663c 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -302,7 +302,6 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } - (void)unref { - NSLog(@"unref"); dispatch_async(_dispatchQueue, ^{ NSAssert(self->_refcount > 0, @"Illegal reference count."); if (self->_refcount == 0) { diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 569aaa79e4d..98b60c3f727 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -32,6 +32,7 @@ NS_ASSUME_NONNULL_BEGIN /** * Issued when initial metadata is received from the server. + */ - (void)receivedInitialMetadata:(nullable NSDictionary *)initialMetadata; /** diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index f99da45fef9..9f45bdfcd46 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -112,7 +112,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } else { _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); } - dispatch_set_target_queue(handler.dispatchQueue, _dispatchQueue); + dispatch_set_target_queue(_dispatchQueue, handler.dispatchQueue); [self start]; } @@ -127,15 +127,17 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } - (void)cancel { - dispatch_async(_dispatchQueue, ^{ - if (_call) { - [_call cancel]; - _call = nil; - } - if (_handler) { - id handler = _handler; - if ([handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - dispatch_async(handler.dispatchQueue, ^{ + GRPCCall2 *call; + @synchronized(self) { + call = _call; + _call = nil; + if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + dispatch_async(_handler.dispatchQueue, ^{ + id handler = nil; + @synchronized(self) { + handler = self->_handler; + self->_handler = nil; + } [handler closedWithTrailingMetadata:nil error:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeCancelled @@ -145,9 +147,8 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing }]]; }); } - _handler = nil; - } - }); + } + [call cancel]; } - (void)writeMessage:(GPBMessage *)message { @@ -155,63 +156,81 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing [NSException raise:NSInvalidArgumentException format:@"Data must be a valid protobuf type."]; } - dispatch_async(_dispatchQueue, ^{ - if (_call) { - [_call writeData:[message data]]; - } - }); + GRPCCall2 *call; + @synchronized(self) { + call = _call; + } + [call writeData:[message data]]; } - (void)finish { - dispatch_async(_dispatchQueue, ^{ - if (_call) { - [_call finish]; - _call = nil; - } - }); + GRPCCall2 *call; + @synchronized(self) { + call = _call; + _call = nil; + } + [call finish]; } - (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { - dispatch_async(_dispatchQueue, ^{ - if (initialMetadata != nil && [self->_handler respondsToSelector:@selector(initialMetadata:)]) { - [self->_handler receivedInitialMetadata:initialMetadata]; + @synchronized (self) { + if (initialMetadata != nil && [_handler respondsToSelector:@selector(initialMetadata:)]) { + dispatch_async(_dispatchQueue, ^{ + id handler = nil; + @synchronized (self) { + handler = self->_handler; + } + [handler receivedInitialMetadata:initialMetadata]; + }); } - }); + } } - (void)receivedRawMessage:(NSData *)message { - dispatch_async(_dispatchQueue, ^{ - if (self->_handler && message != nil) { - NSError *error = nil; - GPBMessage *parsed = [self->_responseClass parseFromData:message error:&error]; - if (parsed) { - if ([self->_handler respondsToSelector:@selector(receivedProtoMessage:)]) { - [self->_handler receivedProtoMessage:parsed]; + if (message == nil) return; + + NSError *error = nil; + GPBMessage *parsed = [_responseClass parseFromData:message error:&error]; + @synchronized (self) { + if (parsed && [_handler respondsToSelector:@selector(receivedProtoMessage:)]) { + dispatch_async(_dispatchQueue, ^{ + id handler = nil; + @synchronized (self) { + handler = self->_handler; } - } else { - if ([self->_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - [self->_handler - closedWithTrailingMetadata:nil - error:ErrorForBadProto(message, _responseClass, error)]; + [handler receivedProtoMessage:parsed]; + }); + } else if (!parsed && [_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]){ + dispatch_async(_dispatchQueue, ^{ + id handler = nil; + @synchronized (self) { + handler = self->_handler; + self->_handler = nil; } - self->_handler = nil; - [self->_call cancel]; - self->_call = nil; - } + [handler closedWithTrailingMetadata:nil + error:ErrorForBadProto(message, _responseClass, error)]; + }); + [_call cancel]; + _call = nil; } - }); + } } - (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { - dispatch_async(_dispatchQueue, ^{ - if ([self->_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - [self->_handler closedWithTrailingMetadata:trailingMetadata error:error]; + @synchronized (self) { + if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + dispatch_async(_dispatchQueue, ^{ + id handler = nil; + @synchronized (self) { + handler = self->_handler; + self->_handler = nil; + } + [handler closedWithTrailingMetadata:trailingMetadata error:error]; + }); } - self->_handler = nil; - [self->_call cancel]; - self->_call = nil; - }); + _call = nil; + } } - (dispatch_queue_t)dispatchQueue { From 87abab45c99ab4b40718557cbc1c25dcd7f5a418 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 15 Nov 2018 17:44:26 -0800 Subject: [PATCH 193/375] Fix version availability --- src/objective-c/GRPCClient/GRPCCall.m | 8 ++++++-- src/objective-c/GRPCClient/private/GRPCChannel.m | 7 +++++-- src/objective-c/ProtoRPC/ProtoRPC.m | 8 +++++++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index ede16b42e8c..19de004cbcd 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -147,12 +147,16 @@ const char *kCFStreamVarName = "grpc_cfstream"; _handler = responseHandler; _initialMetadataPublished = NO; _pipe = [GRXBufferedPipe pipe]; - if (@available(iOS 8.0, *)) { + // Set queue QoS only when iOS version is 8.0 or above and Xcode version is 9.0 or above +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + if (@available(iOS 8.0, macOS 10.10, *)) { _dispatchQueue = dispatch_queue_create( NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); } else { - // Fallback on earlier versions +#else + { +#endif _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); } dispatch_set_target_queue(_dispatchQueue ,responseHandler.dispatchQueue); diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 997d1ff663c..0220141db04 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -204,14 +204,17 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; if ((self = [super init])) { _configuration = [channelConfiguration copy]; - if (@available(iOS 8.0, *)) { +#if __IPHONE_OS_VERSION_MAX_ALLOWED < 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED < 101300 + if (@available(iOS 8.0, macOS 10.10, *)) { _dispatchQueue = dispatch_queue_create( NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); } else { +#else + { +#endif _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); } - // Create gRPC core channel object. NSString *host = channelConfiguration.host; NSAssert(host.length != 0, @"host cannot be nil"); diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 9f45bdfcd46..9164f2320bf 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -105,11 +105,17 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing _handler = handler; _callOptions = [callOptions copy]; _responseClass = responseClass; - if (@available(iOS 8.0, *)) { + + // Set queue QoS only when iOS version is 8.0 or above and Xcode version is 9.0 or above +#if __IPHONE_OS_VERSION_MAX_ALLOWED < 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED < 101300 + if (@available(iOS 8.0, macOS 10.10, *)) { _dispatchQueue = dispatch_queue_create( NULL, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); } else { +#else + { +#endif _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); } dispatch_set_target_queue(_dispatchQueue, handler.dispatchQueue); From f0cbcde73195b8e17130538c3479d4c0e3bcd2a2 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sun, 18 Nov 2018 22:47:35 -0800 Subject: [PATCH 194/375] New channel pool design --- .../GRPCClient/GRPCCall+ChannelArg.m | 2 +- src/objective-c/GRPCClient/GRPCCall.m | 2 +- .../GRPCClient/private/GRPCChannel.h | 36 +-- .../GRPCClient/private/GRPCChannel.m | 169 +++-------- .../GRPCClient/private/GRPCChannelPool.h | 74 ++++- .../GRPCClient/private/GRPCChannelPool.m | 263 ++++++++++++++++-- .../GRPCClient/private/GRPCWrappedCall.m | 31 +-- .../tests/ChannelTests/ChannelPoolTest.m | 222 +++++++++------ .../tests/ChannelTests/ChannelTests.m | 126 +++++---- 9 files changed, 573 insertions(+), 352 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m index 971c2803e29..703cff63bb0 100644 --- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m +++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m @@ -36,7 +36,7 @@ } + (void)closeOpenConnections { - [GRPCChannelPool closeOpenConnections]; + [[GRPCChannelPool sharedInstance] closeOpenConnections]; } + (void)setDefaultCompressMethod:(GRPCCompressAlgorithm)algorithm forhost:(nonnull NSString *)host { diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 19de004cbcd..6f4b1647a5a 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -488,7 +488,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; requestsWriter:(GRXWriter *)requestWriter callOptions:(GRPCCallOptions *)callOptions { // Purposely using pointer rather than length ([host length] == 0) for backwards compatibility. - NSAssert(host && path, @"Neither host nor path can be nil."); + NSAssert(host != nil && path != nil, @"Neither host nor path can be nil."); NSAssert(safety <= GRPCCallSafetyCacheableRequest, @"Invalid call safety value."); NSAssert(requestWriter.state == GRXWriterStateNotStarted, diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index 4dbe0c276ce..de6d1bf4a24 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -61,47 +61,19 @@ NS_ASSUME_NONNULL_BEGIN + (nullable instancetype) new NS_UNAVAILABLE; /** - * Create a channel with remote \a host and signature \a channelConfigurations. Destroy delay is - * defaulted to 30 seconds. - */ -- (nullable instancetype)initWithChannelConfiguration: - (GRPCChannelConfiguration *)channelConfiguration; - -/** - * Create a channel with remote \a host, signature \a channelConfigurations, and destroy delay of - * \a destroyDelay. + * Create a channel with remote \a host and signature \a channelConfigurations. */ - (nullable instancetype)initWithChannelConfiguration: (GRPCChannelConfiguration *)channelConfiguration - destroyDelay:(NSTimeInterval)destroyDelay NS_DESIGNATED_INITIALIZER; /** - * Create a grpc core call object from this channel. The channel's refcount is added by 1. If no - * call is created, NULL is returned, and if the reason is because the channel is already - * disconnected, \a disconnected is set to YES. When the returned call is unreffed, the caller is - * obligated to call \a unref method once. \a disconnected may be null. + * Create a grpc core call object (grpc_call) from this channel. If no call is created, NULL is + * returned. */ - (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue - callOptions:(GRPCCallOptions *)callOptions - disconnected:(nullable BOOL *)disconnected; - -/** - * Unref the channel when a call is done. It also decreases the channel's refcount. If the refcount - * of the channel decreases to 0, the channel is destroyed after the destroy delay. - */ -- (void)unref; - -/** - * Force the channel to be disconnected and destroyed. - */ -- (void)disconnect; - -/** - * Return whether the channel is already disconnected. - */ -@property(readonly) BOOL disconnected; + callOptions:(GRPCCallOptions *)callOptions; @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 0220141db04..81e53d48e34 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -34,9 +34,6 @@ #import #import -/** When all calls of a channel are destroyed, destroy the channel after this much seconds. */ -static const NSTimeInterval kDefaultChannelDestroyDelay = 30; - @implementation GRPCChannelConfiguration - (instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { @@ -178,43 +175,18 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; @implementation GRPCChannel { GRPCChannelConfiguration *_configuration; - dispatch_queue_t _dispatchQueue; grpc_channel *_unmanagedChannel; - NSTimeInterval _destroyDelay; - - NSUInteger _refcount; - NSDate *_lastDispatch; -} -@synthesize disconnected = _disconnected; - -- (instancetype)initWithChannelConfiguration: - (GRPCChannelConfiguration *)channelConfiguration { - return [self initWithChannelConfiguration:channelConfiguration - destroyDelay:kDefaultChannelDestroyDelay]; } - (instancetype)initWithChannelConfiguration: - (GRPCChannelConfiguration *)channelConfiguration - destroyDelay:(NSTimeInterval)destroyDelay { + (GRPCChannelConfiguration *)channelConfiguration { NSAssert(channelConfiguration != nil, @"channelConfiguration must not be empty."); - NSAssert(destroyDelay > 0, @"destroyDelay must be greater than 0."); if (channelConfiguration == nil) return nil; - if (destroyDelay <= 0) return nil; if ((self = [super init])) { _configuration = [channelConfiguration copy]; -#if __IPHONE_OS_VERSION_MAX_ALLOWED < 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED < 101300 - if (@available(iOS 8.0, macOS 10.10, *)) { - _dispatchQueue = dispatch_queue_create( - NULL, - dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); - } else { -#else - { -#endif - _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); - } + // Create gRPC core channel object. NSString *host = channelConfiguration.host; NSAssert(host.length != 0, @"host cannot be nil"); @@ -233,119 +205,54 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; NSLog(@"Unable to create channel."); return nil; } - _destroyDelay = destroyDelay; - _disconnected = NO; } return self; } - (grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue - callOptions:(GRPCCallOptions *)callOptions - disconnected:(BOOL *)disconnected { + callOptions:(GRPCCallOptions *)callOptions { NSAssert(path.length > 0, @"path must not be empty."); NSAssert(queue != nil, @"completionQueue must not be empty."); NSAssert(callOptions != nil, @"callOptions must not be empty."); - if (path.length == 0) return nil; - if (queue == nil) return nil; - if (callOptions == nil) return nil; - - __block BOOL isDisconnected = NO; - __block grpc_call *call = NULL; - dispatch_sync(_dispatchQueue, ^{ - if (self->_disconnected) { - isDisconnected = YES; - } else { - NSAssert(self->_unmanagedChannel != NULL, - @"Channel should have valid unmanaged channel."); - if (self->_unmanagedChannel == NULL) return; - - NSString *serverAuthority = - callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; - NSTimeInterval timeout = callOptions.timeout; - NSAssert(timeout >= 0, @"Invalid timeout"); - if (timeout < 0) return; - grpc_slice host_slice = grpc_empty_slice(); - if (serverAuthority) { - host_slice = grpc_slice_from_copied_string(serverAuthority.UTF8String); - } - grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); - gpr_timespec deadline_ms = - timeout == 0 - ? gpr_inf_future(GPR_CLOCK_REALTIME) - : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); - call = grpc_channel_create_call(self->_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, - queue.unmanagedQueue, path_slice, - serverAuthority ? &host_slice : NULL, deadline_ms, NULL); - if (serverAuthority) { - grpc_slice_unref(host_slice); - } - grpc_slice_unref(path_slice); - if (call == NULL) { - NSLog(@"Unable to create call."); - } else { - // Ref the channel; - [self ref]; - } + if (path.length == 0) return NULL; + if (queue == nil) return NULL; + if (callOptions == nil) return NULL; + + grpc_call *call = NULL; + @synchronized(self) { + NSAssert(_unmanagedChannel != NULL, + @"Channel should have valid unmanaged channel."); + if (_unmanagedChannel == NULL) return NULL; + + NSString *serverAuthority = + callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; + NSTimeInterval timeout = callOptions.timeout; + NSAssert(timeout >= 0, @"Invalid timeout"); + if (timeout < 0) return NULL; + grpc_slice host_slice = grpc_empty_slice(); + if (serverAuthority) { + host_slice = grpc_slice_from_copied_string(serverAuthority.UTF8String); } - }); - if (disconnected != nil) { - *disconnected = isDisconnected; - } - return call; -} - -// This function should be called on _dispatchQueue. -- (void)ref { - _refcount++; - if (_refcount == 1 && _lastDispatch != nil) { - _lastDispatch = nil; - } -} - -- (void)unref { - dispatch_async(_dispatchQueue, ^{ - NSAssert(self->_refcount > 0, @"Illegal reference count."); - if (self->_refcount == 0) { - NSLog(@"Illegal reference count."); - return; + grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); + gpr_timespec deadline_ms = + timeout == 0 + ? gpr_inf_future(GPR_CLOCK_REALTIME) + : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); + call = grpc_channel_create_call(_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, + queue.unmanagedQueue, path_slice, + serverAuthority ? &host_slice : NULL, deadline_ms, NULL); + if (serverAuthority) { + grpc_slice_unref(host_slice); } - self->_refcount--; - if (self->_refcount == 0 && !self->_disconnected) { - // Start timer. - dispatch_time_t delay = - dispatch_time(DISPATCH_TIME_NOW, (int64_t)self->_destroyDelay * NSEC_PER_SEC); - NSDate *now = [NSDate date]; - self->_lastDispatch = now; - dispatch_after(delay, self->_dispatchQueue, ^{ - // Timed disconnection. - if (!self->_disconnected && self->_lastDispatch == now) { - grpc_channel_destroy(self->_unmanagedChannel); - self->_unmanagedChannel = NULL; - self->_disconnected = YES; - } - }); + grpc_slice_unref(path_slice); + NSAssert(call != nil, @"Unable to create call."); + if (call == NULL) { + NSLog(@"Unable to create call."); } - }); -} - -- (void)disconnect { - dispatch_async(_dispatchQueue, ^{ - if (!self->_disconnected) { - grpc_channel_destroy(self->_unmanagedChannel); - self->_unmanagedChannel = nil; - self->_disconnected = YES; - } - }); -} - -- (BOOL)disconnected { - __block BOOL disconnected; - dispatch_sync(_dispatchQueue, ^{ - disconnected = self->_disconnected; - }); - return disconnected; + } + return call; } - (void)dealloc { diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 48779c44497..887bd5f89f7 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -27,7 +27,53 @@ NS_ASSUME_NONNULL_BEGIN +@protocol GRPCChannel; @class GRPCChannel; +@class GRPCChannelPool; +@class GRPCCompletionQueue; +@class GRPCChannelConfiguration; + +/** + * Channel proxy that can be retained and automatically reestablish connection when the channel is + * disconnected. + */ +@interface GRPCPooledChannel : NSObject + +/** + * Initialize with an actual channel object \a channel and a reference to the channel pool. + */ +- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration + channelPool:(GRPCChannelPool *)channelPool; + + +/** + * Create a grpc core call object (grpc_call) from this channel. If channel is disconnected, get a + * new channel object from the channel pool. + */ +- (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path + completionQueue:(GRPCCompletionQueue *)queue + callOptions:(GRPCCallOptions *)callOptions; + +/** + * Return ownership and destroy the grpc_call object created by + * \a unmanagedCallWithPath:completionQueue:callOptions: and decrease channel refcount. If refcount + * of the channel becomes 0, return the channel object to channel pool. + */ +- (void)unrefUnmanagedCall:(grpc_call *)unmanagedCall; + +/** + * Force the channel to disconnect immediately. + */ +- (void)disconnect; + +// The following methods and properties are for test only + +/** + * Return the pointer to the real channel wrapped by the proxy. + */ +@property(atomic, readonly) GRPCChannel *wrappedChannel; + +@end /** * Manage the pool of connected channels. When a channel is no longer referenced by any call, @@ -36,37 +82,41 @@ NS_ASSUME_NONNULL_BEGIN @interface GRPCChannelPool : NSObject /** - * Get the singleton instance + * Get the global channel pool. */ + (nullable instancetype)sharedInstance; /** - * Return a channel with a particular configuration. If the channel does not exist, execute \a - * createChannel then add it in the pool. If the channel exists, increase its reference count. + * Return a channel with a particular configuration. The channel may be a cached channel. */ -- (GRPCChannel *)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; +- (GRPCPooledChannel *)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; /** * This method is deprecated. * * Destroy all open channels and close their connections. */ -+ (void)closeOpenConnections; +- (void)closeOpenConnections; // Test-only methods below /** - * Return a channel with a special destroy delay. If \a destroyDelay is 0, use the default destroy - * delay. + * Get an instance of pool isolated from the global shared pool. This method is for test only. + * Global pool should be used in production. + */ +- (nullable instancetype)init; + +/** + * Simulate a network transition event and destroy all channels. This method is for internal and + * test only. */ -- (GRPCChannel *)channelWithHost:(NSString *)host - callOptions:(GRPCCallOptions *)callOptions - destroyDelay:(NSTimeInterval)destroyDelay; +- (void)disconnectAllChannels; /** - * Simulate a network transition event and destroy all channels. + * Set the destroy delay of channels. A channel should be destroyed if it stayed idle (no active + * call on it) for this period of time. This property is for test only. */ -- (void)destroyAllChannels; +@property(atomic) NSTimeInterval destroyDelay; @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 5e2e9bcfebb..92dd4c86aee 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -37,8 +37,150 @@ extern const char *kCFStreamVarName; static GRPCChannelPool *gChannelPool; static dispatch_once_t gInitChannelPool; +/** When all calls of a channel are destroyed, destroy the channel after this much seconds. */ +static const NSTimeInterval kDefaultChannelDestroyDelay = 30; + +@interface GRPCChannelPool() + +- (GRPCChannel *)refChannelWithConfiguration:(GRPCChannelConfiguration *)configuration; + +- (void)unrefChannelWithConfiguration:(GRPCChannelConfiguration *)configuration; + +@end + +@implementation GRPCPooledChannel { + __weak GRPCChannelPool *_channelPool; + GRPCChannelConfiguration *_channelConfiguration; + NSMutableSet *_unmanagedCalls; +} + +@synthesize wrappedChannel = _wrappedChannel; + +- (instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration + channelPool:(GRPCChannelPool *)channelPool { + NSAssert(channelConfiguration != nil, @"channelConfiguration cannot be empty."); + NSAssert(channelPool != nil, @"channelPool cannot be empty."); + if (channelPool == nil || channelConfiguration == nil) { + return nil; + } + + if ((self = [super init])) { + _channelPool = channelPool; + _channelConfiguration = channelConfiguration; + _unmanagedCalls = [NSMutableSet set]; + } + + return self; +} + +- (grpc_call *)unmanagedCallWithPath:(NSString *)path + completionQueue:(GRPCCompletionQueue *)queue + callOptions:(GRPCCallOptions *)callOptions { + NSAssert(path.length > 0, @"path must not be empty."); + NSAssert(queue != nil, @"completionQueue must not be empty."); + NSAssert(callOptions, @"callOptions must not be empty."); + if (path.length == 0 || queue == nil || callOptions == nil) return NULL; + + grpc_call *call = NULL; + @synchronized(self) { + if (_wrappedChannel == nil) { + __strong GRPCChannelPool *strongPool = _channelPool; + if (strongPool) { + _wrappedChannel = [strongPool refChannelWithConfiguration:_channelConfiguration]; + } + NSAssert(_wrappedChannel != nil, @"Unable to get a raw channel for proxy."); + } + call = [_wrappedChannel unmanagedCallWithPath:path completionQueue:queue callOptions:callOptions]; + if (call != NULL) { + [_unmanagedCalls addObject:[NSValue valueWithPointer:call]]; + } + } + return call; +} + +- (void)unrefUnmanagedCall:(grpc_call *)unmanagedCall { + if (unmanagedCall == nil) return; + + grpc_call_unref(unmanagedCall); + BOOL timedDestroy = NO; + @synchronized(self) { + if ([_unmanagedCalls containsObject:[NSValue valueWithPointer:unmanagedCall]]) { + [_unmanagedCalls removeObject:[NSValue valueWithPointer:unmanagedCall]]; + if ([_unmanagedCalls count] == 0) { + timedDestroy = YES; + } + } + } + if (timedDestroy) { + [self timedDestroy]; + } +} + +- (void)disconnect { + @synchronized(self) { + _wrappedChannel = nil; + [_unmanagedCalls removeAllObjects]; + } +} + +- (GRPCChannel *)wrappedChannel { + GRPCChannel *channel = nil; + @synchronized (self) { + channel = _wrappedChannel; + } + return channel; +} + +- (void)timedDestroy { + __strong GRPCChannelPool *pool = nil; + @synchronized(self) { + // Check if we still want to destroy the channel. + if ([_unmanagedCalls count] == 0) { + pool = _channelPool; + _wrappedChannel = nil; + } + } + [pool unrefChannelWithConfiguration:_channelConfiguration]; +} + +@end + +/** + * A convenience value type for cached channel. + */ +@interface GRPCChannelRecord : NSObject + +/** Pointer to the raw channel. May be nil when the channel has been destroyed. */ +@property GRPCChannel *channel; + +/** Channel proxy corresponding to this channel configuration. */ +@property GRPCPooledChannel *proxy; + +/** Last time when a timed destroy is initiated on the channel. */ +@property NSDate *timedDestroyDate; + +/** Reference count of the proxy to the channel. */ +@property NSUInteger refcount; + +@end + +@implementation GRPCChannelRecord + +- (id)copyWithZone:(NSZone *)zone { + GRPCChannelRecord *newRecord = [[GRPCChannelRecord allocWithZone:zone] init]; + newRecord.channel = _channel; + newRecord.proxy = _proxy; + newRecord.timedDestroyDate = _timedDestroyDate; + newRecord.refcount = _refcount; + + return newRecord; +} + +@end + @implementation GRPCChannelPool { - NSMutableDictionary *_channelPool; + NSMutableDictionary *_channelPool; + dispatch_queue_t _dispatchQueue; } + (instancetype)sharedInstance { @@ -52,6 +194,18 @@ static dispatch_once_t gInitChannelPool; - (instancetype)init { if ((self = [super init])) { _channelPool = [NSMutableDictionary dictionary]; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + if (@available(iOS 8.0, macOS 10.10, *)) { + _dispatchQueue = dispatch_queue_create( + NULL, + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); + } else { +#else + { +#endif + _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + } + _destroyDelay = kDefaultChannelDestroyDelay; // Connectivity monitor is not required for CFStream char *enableCFStream = getenv(kCFStreamVarName); @@ -62,51 +216,106 @@ static dispatch_once_t gInitChannelPool; return self; } -- (GRPCChannel *)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { - return [self channelWithHost:host callOptions:callOptions destroyDelay:0]; -} - -- (GRPCChannel *)channelWithHost:(NSString *)host - callOptions:(GRPCCallOptions *)callOptions - destroyDelay:(NSTimeInterval)destroyDelay { +- (GRPCPooledChannel *)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { NSAssert(host.length > 0, @"Host must not be empty."); NSAssert(callOptions != nil, @"callOptions must not be empty."); if (host.length == 0) return nil; if (callOptions == nil) return nil; - GRPCChannel *channel; + GRPCPooledChannel *channelProxy = nil; GRPCChannelConfiguration *configuration = [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; @synchronized(self) { - channel = _channelPool[configuration]; - if (channel == nil || channel.disconnected) { - if (destroyDelay == 0) { - channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration]; - } else { - channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration - destroyDelay:destroyDelay]; - } - _channelPool[configuration] = channel; + GRPCChannelRecord *record = _channelPool[configuration]; + if (record == nil) { + record = [[GRPCChannelRecord alloc] init]; + record.proxy = [[GRPCPooledChannel alloc] initWithChannelConfiguration:configuration + channelPool:self]; + record.timedDestroyDate = nil; + _channelPool[configuration] = record; + channelProxy = record.proxy; + } else { + channelProxy = record.proxy; } } - return channel; + return channelProxy; } -+ (void)closeOpenConnections { - [[GRPCChannelPool sharedInstance] destroyAllChannels]; +- (void)closeOpenConnections { + [self disconnectAllChannels]; } -- (void)destroyAllChannels { - @synchronized(self) { - for (id key in _channelPool) { - [_channelPool[key] disconnect]; +- (GRPCChannel *)refChannelWithConfiguration:(GRPCChannelConfiguration *)configuration { + GRPCChannel *ret = nil; + @synchronized (self) { + NSAssert(configuration != nil, @"configuration cannot be empty."); + if (configuration == nil) return nil; + + GRPCChannelRecord *record = _channelPool[configuration]; + NSAssert(record != nil, @"No record corresponding to a proxy."); + if (record == nil) return nil; + + if (record.channel == nil) { + // Channel is already destroyed; + record.channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration]; + record.timedDestroyDate = nil; + record.refcount = 1; + ret = record.channel; + } else { + ret = record.channel; + record.timedDestroyDate = nil; + record.refcount++; } - _channelPool = [NSMutableDictionary dictionary]; } + return ret; +} + +- (void)unrefChannelWithConfiguration:(GRPCChannelConfiguration *)configuration { + @synchronized (self) { + GRPCChannelRecord *record = _channelPool[configuration]; + NSAssert(record != nil, @"No record corresponding to a proxy."); + if (record == nil) return; + NSAssert(record.refcount > 0, @"Inconsistent channel refcount."); + if (record.refcount > 0) { + record.refcount--; + if (record.refcount == 0) { + NSDate *now = [NSDate date]; + record.timedDestroyDate = now; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_destroyDelay * NSEC_PER_SEC)), + _dispatchQueue, + ^{ + @synchronized (self) { + if (now == record.timedDestroyDate) { + // Destroy the raw channel and reset related records. + record.timedDestroyDate = nil; + record.refcount = 0; + record.channel = nil; + } + } + }); + } + } + } +} + +- (void)disconnectAllChannels { + NSMutableSet *proxySet = [NSMutableSet set]; + @synchronized (self) { + [_channelPool enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration * _Nonnull key, GRPCChannelRecord * _Nonnull obj, BOOL * _Nonnull stop) { + obj.channel = nil; + obj.timedDestroyDate = nil; + obj.refcount = 0; + [proxySet addObject:obj.proxy]; + }]; + } + // Disconnect proxies + [proxySet enumerateObjectsUsingBlock:^(GRPCPooledChannel * _Nonnull obj, BOOL * _Nonnull stop) { + [obj disconnect]; + }]; } - (void)connectivityChange:(NSNotification *)note { - [self destroyAllChannels]; + [self disconnectAllChannels]; } - (void)dealloc { diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index ae7f07f1192..5c402250ccf 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -238,7 +238,7 @@ @implementation GRPCWrappedCall { GRPCCompletionQueue *_queue; - GRPCChannel *_channel; + GRPCPooledChannel *_channel; grpc_call *_call; } @@ -257,21 +257,15 @@ // consuming too many threads and having contention of multiple calls in a single completion // queue. Currently we use a singleton queue. _queue = [GRPCCompletionQueue completionQueue]; - BOOL disconnected = NO; - do { - _channel = [[GRPCChannelPool sharedInstance] channelWithHost:host callOptions:callOptions]; - if (_channel == nil) { - NSAssert(_channel != nil, @"Failed to get a channel for the host."); - NSLog(@"Failed to get a channel for the host."); - return nil; - } - _call = [_channel unmanagedCallWithPath:path - completionQueue:_queue - callOptions:callOptions - disconnected:&disconnected]; - // Try create another channel if the current channel is disconnected (due to idleness or - // connectivity monitor disconnection). - } while (_call == NULL && disconnected); + _channel = [[GRPCChannelPool sharedInstance] channelWithHost:host callOptions:callOptions]; + if (_channel == nil) { + NSAssert(_channel != nil, @"Failed to get a channel for the host."); + NSLog(@"Failed to get a channel for the host."); + return nil; + } + _call = [_channel unmanagedCallWithPath:path + completionQueue:_queue + callOptions:callOptions]; if (_call == nil) { NSAssert(_channel != nil, @"Failed to get a channel for the host."); NSLog(@"Failed to create a call."); @@ -326,10 +320,7 @@ } - (void)dealloc { - if (_call) { - grpc_call_unref(_call); - } - [_channel unref]; + [_channel unrefUnmanagedCall:_call]; _channel = nil; } diff --git a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m index b85e62feb5f..51819b12c2f 100644 --- a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m +++ b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m @@ -25,6 +25,8 @@ #define TEST_TIMEOUT 32 NSString *kDummyHost = @"dummy.host"; +NSString *kDummyHost2 = @"dummy.host.2"; +NSString *kDummyPath = @"/dummy/path"; @interface ChannelPoolTest : XCTestCase @@ -36,94 +38,156 @@ NSString *kDummyHost = @"dummy.host"; grpc_init(); } -- (void)testChannelPooling { - NSString *kDummyHost = @"dummy.host"; - NSString *kDummyHost2 = @"dummy.host2"; +- (void)testCreateChannelAndCall { + GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; + GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; + GRPCPooledChannel *channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost + callOptions:options]; + XCTAssertNil(channel.wrappedChannel); + GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; + grpc_call *call = [channel unmanagedCallWithPath:kDummyPath + completionQueue:cq callOptions:options]; + XCTAssert(call != NULL); + XCTAssertNotNil(channel.wrappedChannel); + [channel unrefUnmanagedCall:call]; + XCTAssertNil(channel.wrappedChannel); +} - GRPCMutableCallOptions *options1 = [[GRPCMutableCallOptions alloc] init]; +- (void)testCacheChannel { + GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; + GRPCCallOptions *options1 = [[GRPCCallOptions alloc] init]; GRPCCallOptions *options2 = [options1 copy]; - GRPCMutableCallOptions *options3 = [options2 mutableCopy]; + GRPCMutableCallOptions *options3 = [options1 mutableCopy]; options3.transportType = GRPCTransportTypeInsecure; - - GRPCChannelPool *pool = [GRPCChannelPool sharedInstance]; - - GRPCChannel *channel1 = [pool channelWithHost:kDummyHost callOptions:options1]; - GRPCChannel *channel2 = [pool channelWithHost:kDummyHost callOptions:options2]; - GRPCChannel *channel3 = [pool channelWithHost:kDummyHost2 callOptions:options1]; - GRPCChannel *channel4 = [pool channelWithHost:kDummyHost callOptions:options3]; - XCTAssertEqual(channel1, channel2); - XCTAssertNotEqual(channel1, channel3); - XCTAssertNotEqual(channel1, channel4); - XCTAssertNotEqual(channel3, channel4); -} - -- (void)testDestroyAllChannels { - NSString *kDummyHost = @"dummy.host"; - - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - GRPCChannelPool *pool = [GRPCChannelPool sharedInstance]; - GRPCChannel *channel = [pool channelWithHost:kDummyHost callOptions:options]; - grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" - completionQueue:[GRPCCompletionQueue completionQueue] - callOptions:options - disconnected:nil]; - [pool destroyAllChannels]; - XCTAssertTrue(channel.disconnected); - GRPCChannel *channel2 = [pool channelWithHost:kDummyHost callOptions:options]; - XCTAssertNotEqual(channel, channel2); - grpc_call_unref(call); + GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; + GRPCPooledChannel *channel1 = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost + callOptions:options1]; + grpc_call *call1 = [channel1 unmanagedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options1]; + GRPCPooledChannel *channel2 = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost + callOptions:options2]; + grpc_call *call2 = [channel2 unmanagedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options2]; + GRPCPooledChannel *channel3 = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost + callOptions:options3]; + grpc_call *call3 = [channel3 unmanagedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options3]; + GRPCPooledChannel *channel4 = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost2 + callOptions:options1]; + grpc_call *call4 = [channel4 unmanagedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options1]; + XCTAssertEqual(channel1.wrappedChannel, channel2.wrappedChannel); + XCTAssertNotEqual(channel1.wrappedChannel, channel3.wrappedChannel); + XCTAssertNotEqual(channel1.wrappedChannel, channel4.wrappedChannel); + XCTAssertNotEqual(channel3.wrappedChannel, channel4.wrappedChannel); + [channel1 unrefUnmanagedCall:call1]; + [channel2 unrefUnmanagedCall:call2]; + [channel3 unrefUnmanagedCall:call3]; + [channel4 unrefUnmanagedCall:call4]; } -- (void)testGetChannelBeforeChannelTimedDisconnection { - NSString *kDummyHost = @"dummy.host"; - const NSTimeInterval kDestroyDelay = 1; - - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - GRPCChannelPool *pool = [GRPCChannelPool sharedInstance]; - GRPCChannel *channel = - [pool channelWithHost:kDummyHost callOptions:options destroyDelay:kDestroyDelay]; - grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" - completionQueue:[GRPCCompletionQueue completionQueue] - callOptions:options - disconnected:nil]; - grpc_call_unref(call); - [channel unref]; - - // Test that we can still get the channel at this time - GRPCChannel *channel2 = - [pool channelWithHost:kDummyHost callOptions:options destroyDelay:kDestroyDelay]; - XCTAssertEqual(channel, channel2); - call = [channel2 unmanagedCallWithPath:@"dummy.path" - completionQueue:[GRPCCompletionQueue completionQueue] - callOptions:options - disconnected:nil]; - - // Test that after the destroy delay, the channel is still alive +- (void)testTimedDestroyChannel { + const NSTimeInterval kDestroyDelay = 1.0; + + GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; + pool.destroyDelay = kDestroyDelay; + GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; + GRPCPooledChannel *channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost + callOptions:options]; + GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; + grpc_call *call = [channel unmanagedCallWithPath:kDummyPath + completionQueue:cq callOptions:options]; + GRPCChannel *wrappedChannel = channel.wrappedChannel; + + [channel unrefUnmanagedCall:call]; + // Confirm channel is not destroyed at this time + call = [channel unmanagedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + XCTAssertEqual(wrappedChannel, channel.wrappedChannel); + + [channel unrefUnmanagedCall:call]; sleep(kDestroyDelay + 1); - XCTAssertFalse(channel.disconnected); + // Confirm channel is new at this time + call = [channel unmanagedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + XCTAssertNotEqual(wrappedChannel, channel.wrappedChannel); + + // Confirm the new channel can create call + call = [channel unmanagedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + XCTAssert(call != NULL); + [channel unrefUnmanagedCall:call]; } -- (void)testGetChannelAfterChannelTimedDisconnection { - NSString *kDummyHost = @"dummy.host"; - const NSTimeInterval kDestroyDelay = 1; - - GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; - GRPCChannelPool *pool = [GRPCChannelPool sharedInstance]; - GRPCChannel *channel = - [pool channelWithHost:kDummyHost callOptions:options destroyDelay:kDestroyDelay]; - grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" - completionQueue:[GRPCCompletionQueue completionQueue] - callOptions:options - disconnected:nil]; - grpc_call_unref(call); - [channel unref]; - - sleep(kDestroyDelay + 1); +- (void)testPoolDisconnection { + GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; + GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; + GRPCPooledChannel *channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost + callOptions:options]; + GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; + grpc_call *call = [channel unmanagedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + XCTAssertNotNil(channel.wrappedChannel); + GRPCChannel *wrappedChannel = channel.wrappedChannel; + + // Test a new channel is created by requesting a channel from pool + [pool disconnectAllChannels]; + channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost + callOptions:options]; + call = [channel unmanagedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + XCTAssertNotNil(channel.wrappedChannel); + XCTAssertNotEqual(wrappedChannel, channel.wrappedChannel); + wrappedChannel = channel.wrappedChannel; + + // Test a new channel is created by requesting a new call from the previous proxy + [pool disconnectAllChannels]; + grpc_call *call2 = [channel unmanagedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + XCTAssertNotNil(channel.wrappedChannel); + XCTAssertNotEqual(channel.wrappedChannel, wrappedChannel); + [channel unrefUnmanagedCall:call]; + [channel unrefUnmanagedCall:call2]; +} - // Test that we get new channel to the same host and with the same callOptions - GRPCChannel *channel2 = - [pool channelWithHost:kDummyHost callOptions:options destroyDelay:kDestroyDelay]; - XCTAssertNotEqual(channel, channel2); +- (void)testUnrefCallFromStaleChannel { + GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; + GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; + GRPCPooledChannel *channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost + callOptions:options]; + GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; + grpc_call *call = [channel unmanagedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + + [pool disconnectAllChannels]; + channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost + callOptions:options]; + + grpc_call *call2 = [channel unmanagedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + // Test unref the call of a stale channel will not cause the current channel going into timed + // destroy state + XCTAssertNotNil(channel.wrappedChannel); + GRPCChannel *wrappedChannel = channel.wrappedChannel; + [channel unrefUnmanagedCall:call]; + XCTAssertNotNil(channel.wrappedChannel); + XCTAssertEqual(wrappedChannel, channel.wrappedChannel); + // Test unref the call of the current channel will cause the channel going into timed destroy + // state + [channel unrefUnmanagedCall:call2]; + XCTAssertNil(channel.wrappedChannel); } @end diff --git a/src/objective-c/tests/ChannelTests/ChannelTests.m b/src/objective-c/tests/ChannelTests/ChannelTests.m index 5daafcdf3f3..212db2f653a 100644 --- a/src/objective-c/tests/ChannelTests/ChannelTests.m +++ b/src/objective-c/tests/ChannelTests/ChannelTests.m @@ -20,65 +20,93 @@ #import "../../GRPCClient/GRPCCallOptions.h" #import "../../GRPCClient/private/GRPCChannel.h" +#import "../../GRPCClient/private/GRPCChannelPool.h" #import "../../GRPCClient/private/GRPCCompletionQueue.h" -@interface ChannelTests : XCTestCase +/* +#define TEST_TIMEOUT 8 + +@interface GRPCChannelFake : NSObject + +- (instancetype)initWithCreateExpectation:(XCTestExpectation *)createExpectation + unrefExpectation:(XCTestExpectation *)unrefExpectation; + +- (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path + completionQueue:(GRPCCompletionQueue *)queue + callOptions:(GRPCCallOptions *)callOptions; + +- (void)unrefUnmanagedCall:(grpc_call *)unmanagedCall; @end -@implementation ChannelTests +@implementation GRPCChannelFake { + __weak XCTestExpectation *_createExpectation; + __weak XCTestExpectation *_unrefExpectation; + long _grpcCallCounter; +} -+ (void)setUp { - grpc_init(); +- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration { + return nil; } -- (void)testTimedDisconnection { - NSString *const kHost = @"grpc-test.sandbox.googleapis.com"; - const NSTimeInterval kDestroyDelay = 1; - GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCChannelConfiguration *configuration = - [[GRPCChannelConfiguration alloc] initWithHost:kHost callOptions:options]; - GRPCChannel *channel = - [[GRPCChannel alloc] initWithChannelConfiguration:configuration destroyDelay:kDestroyDelay]; - BOOL disconnected; - grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" - completionQueue:[GRPCCompletionQueue completionQueue] - callOptions:options - disconnected:&disconnected]; - XCTAssertFalse(disconnected); - grpc_call_unref(call); - [channel unref]; - XCTAssertFalse(channel.disconnected, @"Channel is pre-maturely disconnected."); - sleep(kDestroyDelay + 1); - XCTAssertTrue(channel.disconnected, @"Channel is not disconnected after delay."); - - // Check another call creation returns null and indicates disconnected. - call = [channel unmanagedCallWithPath:@"dummy.path" - completionQueue:[GRPCCompletionQueue completionQueue] - callOptions:options - disconnected:&disconnected]; - XCTAssert(call == NULL); - XCTAssertTrue(disconnected); +- (instancetype)initWithCreateExpectation:(XCTestExpectation *)createExpectation + unrefExpectation:(XCTestExpectation *)unrefExpectation { + if ((self = [super init])) { + _createExpectation = createExpectation; + _unrefExpectation = unrefExpectation; + _grpcCallCounter = 0; + } + return self; } -- (void)testForceDisconnection { - NSString *const kHost = @"grpc-test.sandbox.googleapis.com"; - const NSTimeInterval kDestroyDelay = 1; - GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCChannelConfiguration *configuration = - [[GRPCChannelConfiguration alloc] initWithHost:kHost callOptions:options]; - GRPCChannel *channel = - [[GRPCChannel alloc] initWithChannelConfiguration:configuration destroyDelay:kDestroyDelay]; - grpc_call *call = [channel unmanagedCallWithPath:@"dummy.path" - completionQueue:[GRPCCompletionQueue completionQueue] - callOptions:options - disconnected:nil]; - grpc_call_unref(call); - [channel disconnect]; - XCTAssertTrue(channel.disconnected, @"Channel is not disconnected."); - - // Test calling another unref here will not crash - [channel unref]; +- (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path + completionQueue:(GRPCCompletionQueue *)queue + callOptions:(GRPCCallOptions *)callOptions { + if (_createExpectation) [_createExpectation fulfill]; + return (grpc_call *)(++_grpcCallCounter); +} + +- (void)unrefUnmanagedCall:(grpc_call *)unmanagedCall { + if (_unrefExpectation) [_unrefExpectation fulfill]; +} + +@end + +@interface GRPCChannelPoolFake : NSObject + +- (instancetype)initWithDelayedDestroyExpectation:(XCTestExpectation *)delayedDestroyExpectation; + +- (GRPCChannel *)rawChannelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; + +- (void)delayedDestroyChannel; + +@end + +@implementation GRPCChannelPoolFake { + __weak XCTestExpectation *_delayedDestroyExpectation; +} + +- (instancetype)initWithDelayedDestroyExpectation:(XCTestExpectation *)delayedDestroyExpectation { + if ((self = [super init])) { + _delayedDestroyExpectation = delayedDestroyExpectation; + } + return self; +} + +- (void)delayedDestroyChannel { + if (_delayedDestroyExpectation) [_delayedDestroyExpectation fulfill]; +} + +@end */ + +@interface ChannelTests : XCTestCase + +@end + +@implementation ChannelTests + ++ (void)setUp { + grpc_init(); } @end From 680b53f7ad7c93947003dcf8d377f2b33c7623e9 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sun, 18 Nov 2018 23:00:08 -0800 Subject: [PATCH 195/375] clang-format --- src/objective-c/GRPCClient/GRPCCall.h | 4 +- src/objective-c/GRPCClient/GRPCCall.m | 59 +++++----- .../GRPCClient/private/GRPCChannel.h | 3 +- .../GRPCClient/private/GRPCChannel.m | 18 ++-- .../GRPCClient/private/GRPCChannelPool.h | 4 +- .../GRPCClient/private/GRPCChannelPool.m | 58 +++++----- .../private/GRPCCronetChannelFactory.m | 6 +- src/objective-c/GRPCClient/private/GRPCHost.m | 3 +- .../private/GRPCInsecureChannelFactory.m | 3 +- .../private/GRPCSecureChannelFactory.m | 15 ++- .../GRPCClient/private/GRPCWrappedCall.m | 7 +- .../GRPCClient/private/utilities.h | 3 +- src/objective-c/ProtoRPC/ProtoRPC.m | 50 ++++----- .../tests/ChannelTests/ChannelPoolTest.m | 102 ++++++++---------- .../tests/ChannelTests/ChannelTests.m | 4 +- src/objective-c/tests/InteropTests.m | 3 +- 16 files changed, 153 insertions(+), 189 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 7f80c17f1f3..4c8c11eded2 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -340,8 +340,8 @@ NS_ASSUME_NONNULL_END * and the port number, for example @"localhost:5050". */ - (null_unspecified instancetype)initWithHost:(null_unspecified NSString *)host - path:(null_unspecified NSString *)path - requestsWriter:(null_unspecified GRXWriter *)requestWriter; + path:(null_unspecified NSString *)path + requestsWriter:(null_unspecified GRXWriter *)requestWriter; /** * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 6f4b1647a5a..94e470d4ed9 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -122,9 +122,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; responseHandler:(id)responseHandler callOptions:(GRPCCallOptions *)callOptions { NSAssert(requestOptions.host.length != 0 && requestOptions.path.length != 0, - @"Neither host nor path can be nil."); - NSAssert(requestOptions.safety <= GRPCCallSafetyCacheableRequest, - @"Invalid call safety value."); + @"Neither host nor path can be nil."); + NSAssert(requestOptions.safety <= GRPCCallSafetyCacheableRequest, @"Invalid call safety value."); NSAssert(responseHandler != nil, @"Response handler required."); if (requestOptions.host.length == 0 || requestOptions.path.length == 0) { return nil; @@ -136,7 +135,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; return nil; } - if ((self = [super init])) { _requestOptions = [requestOptions copy]; if (callOptions == nil) { @@ -159,7 +157,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; #endif _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); } - dispatch_set_target_queue(_dispatchQueue ,responseHandler.dispatchQueue); + dispatch_set_target_queue(_dispatchQueue, responseHandler.dispatchQueue); _started = NO; _canceled = NO; _finished = NO; @@ -176,7 +174,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)start { GRPCCall *call = nil; - @synchronized (self) { + @synchronized(self) { NSAssert(!_started, @"Call already started."); NSAssert(!_canceled, @"Call already canceled."); if (_started) { @@ -192,10 +190,10 @@ const char *kCFStreamVarName = "grpc_cfstream"; } _call = [[GRPCCall alloc] initWithHost:_requestOptions.host - path:_requestOptions.path - callSafety:_requestOptions.safety - requestsWriter:_pipe - callOptions:_callOptions]; + path:_requestOptions.path + callSafety:_requestOptions.safety + requestsWriter:_pipe + callOptions:_callOptions]; if (_callOptions.initialMetadata) { [_call.requestHeaders addEntriesFromDictionary:_callOptions.initialMetadata]; } @@ -203,7 +201,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } void (^valueHandler)(id value) = ^(id value) { - @synchronized (self) { + @synchronized(self) { if (self->_handler) { if (!self->_initialMetadataPublished) { self->_initialMetadataPublished = YES; @@ -223,7 +221,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; [self issueInitialMetadata:self->_call.responseHeaders]; } [self issueClosedWithTrailingMetadata:self->_call.responseTrailers error:errorOrNil]; - } // Clearing _call must happen *after* dispatching close in order to get trailing // metadata from _call. @@ -237,14 +234,13 @@ const char *kCFStreamVarName = "grpc_cfstream"; } }; id responseWriteable = - [[GRXWriteable alloc] initWithValueHandler:valueHandler - completionHandler:completionHandler]; + [[GRXWriteable alloc] initWithValueHandler:valueHandler completionHandler:completionHandler]; [call startWithWriteable:responseWriteable]; } - (void)cancel { GRPCCall *call = nil; - @synchronized (self) { + @synchronized(self) { if (_canceled) { return; } @@ -259,7 +255,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; dispatch_async(_dispatchQueue, ^{ // Copy to local so that block is freed after cancellation completes. id copiedHandler = nil; - @synchronized (self) { + @synchronized(self) { copiedHandler = self->_handler; self->_handler = nil; } @@ -268,9 +264,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; error:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeCancelled userInfo:@{ - NSLocalizedDescriptionKey : - @"Canceled by app" - }]]; + NSLocalizedDescriptionKey : + @"Canceled by app" + }]]; }); } } @@ -322,11 +318,12 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)issueInitialMetadata:(NSDictionary *)initialMetadata { - @synchronized (self) { - if (initialMetadata != nil && [_handler respondsToSelector:@selector(receivedInitialMetadata:)]) { + @synchronized(self) { + if (initialMetadata != nil && + [_handler respondsToSelector:@selector(receivedInitialMetadata:)]) { dispatch_async(_dispatchQueue, ^{ id handler = nil; - @synchronized (self) { + @synchronized(self) { handler = self->_handler; } [handler receivedInitialMetadata:initialMetadata]; @@ -336,11 +333,11 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)issueMessage:(id)message { - @synchronized (self) { + @synchronized(self) { if (message != nil && [_handler respondsToSelector:@selector(receivedRawMessage:)]) { dispatch_async(_dispatchQueue, ^{ id handler = nil; - @synchronized (self) { + @synchronized(self) { handler = self->_handler; } [handler receivedRawMessage:message]; @@ -350,17 +347,16 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)issueClosedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { - @synchronized (self) { + @synchronized(self) { if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { dispatch_async(_dispatchQueue, ^{ id handler = nil; - @synchronized (self) { + @synchronized(self) { handler = self->_handler; // Clean up _handler so that no more responses are reported to the handler. self->_handler = nil; } - [handler closedWithTrailingMetadata:trailingMetadata - error:error]; + [handler closedWithTrailingMetadata:trailingMetadata error:error]; }); } } @@ -489,10 +485,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; callOptions:(GRPCCallOptions *)callOptions { // Purposely using pointer rather than length ([host length] == 0) for backwards compatibility. NSAssert(host != nil && path != nil, @"Neither host nor path can be nil."); - NSAssert(safety <= GRPCCallSafetyCacheableRequest, - @"Invalid call safety value."); + NSAssert(safety <= GRPCCallSafetyCacheableRequest, @"Invalid call safety value."); NSAssert(requestWriter.state == GRXWriterStateNotStarted, - @"The requests writer can't be already started."); + @"The requests writer can't be already started."); if (!host || !path) { return nil; } @@ -888,7 +883,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } NSAssert(_callOptions.authTokenProvider == nil || _callOptions.oauth2AccessToken == nil, - @"authTokenProvider and oauth2AccessToken cannot be set at the same time"); + @"authTokenProvider and oauth2AccessToken cannot be set at the same time"); if (_callOptions.authTokenProvider != nil) { @synchronized(self) { self.isWaitingForToken = YES; diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index de6d1bf4a24..5426b28d758 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -64,8 +64,7 @@ NS_ASSUME_NONNULL_BEGIN * Create a channel with remote \a host and signature \a channelConfigurations. */ - (nullable instancetype)initWithChannelConfiguration: - (GRPCChannelConfiguration *)channelConfiguration - NS_DESIGNATED_INITIALIZER; + (GRPCChannelConfiguration *)channelConfiguration NS_DESIGNATED_INITIALIZER; /** * Create a grpc core call object (grpc_call) from this channel. If no call is created, NULL is diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 81e53d48e34..e4cefc338c6 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -178,10 +178,8 @@ grpc_channel *_unmanagedChannel; } -- (instancetype)initWithChannelConfiguration: - (GRPCChannelConfiguration *)channelConfiguration { - NSAssert(channelConfiguration != nil, - @"channelConfiguration must not be empty."); +- (instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration { + NSAssert(channelConfiguration != nil, @"channelConfiguration must not be empty."); if (channelConfiguration == nil) return nil; if ((self = [super init])) { @@ -221,12 +219,11 @@ grpc_call *call = NULL; @synchronized(self) { - NSAssert(_unmanagedChannel != NULL, - @"Channel should have valid unmanaged channel."); + NSAssert(_unmanagedChannel != NULL, @"Channel should have valid unmanaged channel."); if (_unmanagedChannel == NULL) return NULL; NSString *serverAuthority = - callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; + callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; NSTimeInterval timeout = callOptions.timeout; NSAssert(timeout >= 0, @"Invalid timeout"); if (timeout < 0) return NULL; @@ -236,10 +233,9 @@ } grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); gpr_timespec deadline_ms = - timeout == 0 - ? gpr_inf_future(GPR_CLOCK_REALTIME) - : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); + timeout == 0 ? gpr_inf_future(GPR_CLOCK_REALTIME) + : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); call = grpc_channel_create_call(_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, queue.unmanagedQueue, path_slice, serverAuthority ? &host_slice : NULL, deadline_ms, NULL); diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 887bd5f89f7..1e3c1d7d976 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -42,10 +42,10 @@ NS_ASSUME_NONNULL_BEGIN /** * Initialize with an actual channel object \a channel and a reference to the channel pool. */ -- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration +- (nullable instancetype)initWithChannelConfiguration: + (GRPCChannelConfiguration *)channelConfiguration channelPool:(GRPCChannelPool *)channelPool; - /** * Create a grpc core call object (grpc_call) from this channel. If channel is disconnected, get a * new channel object from the channel pool. diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 92dd4c86aee..7c139b37176 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -40,7 +40,7 @@ static dispatch_once_t gInitChannelPool; /** When all calls of a channel are destroyed, destroy the channel after this much seconds. */ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; -@interface GRPCChannelPool() +@interface GRPCChannelPool () - (GRPCChannel *)refChannelWithConfiguration:(GRPCChannelConfiguration *)configuration; @@ -74,7 +74,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } - (grpc_call *)unmanagedCallWithPath:(NSString *)path - completionQueue:(GRPCCompletionQueue *)queue + completionQueue:(GRPCCompletionQueue *)queue callOptions:(GRPCCallOptions *)callOptions { NSAssert(path.length > 0, @"path must not be empty."); NSAssert(queue != nil, @"completionQueue must not be empty."); @@ -90,7 +90,8 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } NSAssert(_wrappedChannel != nil, @"Unable to get a raw channel for proxy."); } - call = [_wrappedChannel unmanagedCallWithPath:path completionQueue:queue callOptions:callOptions]; + call = + [_wrappedChannel unmanagedCallWithPath:path completionQueue:queue callOptions:callOptions]; if (call != NULL) { [_unmanagedCalls addObject:[NSValue valueWithPointer:call]]; } @@ -100,7 +101,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; - (void)unrefUnmanagedCall:(grpc_call *)unmanagedCall { if (unmanagedCall == nil) return; - + grpc_call_unref(unmanagedCall); BOOL timedDestroy = NO; @synchronized(self) { @@ -125,7 +126,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; - (GRPCChannel *)wrappedChannel { GRPCChannel *channel = nil; - @synchronized (self) { + @synchronized(self) { channel = _wrappedChannel; } return channel; @@ -148,7 +149,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; /** * A convenience value type for cached channel. */ -@interface GRPCChannelRecord : NSObject +@interface GRPCChannelRecord : NSObject /** Pointer to the raw channel. May be nil when the channel has been destroyed. */ @property GRPCChannel *channel; @@ -197,14 +198,14 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 if (@available(iOS 8.0, macOS 10.10, *)) { _dispatchQueue = dispatch_queue_create( - NULL, - dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); + NULL, + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); } else { #else - { + { #endif - _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); - } + _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + } _destroyDelay = kDefaultChannelDestroyDelay; // Connectivity monitor is not required for CFStream @@ -221,7 +222,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; NSAssert(callOptions != nil, @"callOptions must not be empty."); if (host.length == 0) return nil; if (callOptions == nil) return nil; - + GRPCPooledChannel *channelProxy = nil; GRPCChannelConfiguration *configuration = [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; @@ -229,8 +230,8 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; GRPCChannelRecord *record = _channelPool[configuration]; if (record == nil) { record = [[GRPCChannelRecord alloc] init]; - record.proxy = [[GRPCPooledChannel alloc] initWithChannelConfiguration:configuration - channelPool:self]; + record.proxy = + [[GRPCPooledChannel alloc] initWithChannelConfiguration:configuration channelPool:self]; record.timedDestroyDate = nil; _channelPool[configuration] = record; channelProxy = record.proxy; @@ -247,7 +248,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; - (GRPCChannel *)refChannelWithConfiguration:(GRPCChannelConfiguration *)configuration { GRPCChannel *ret = nil; - @synchronized (self) { + @synchronized(self) { NSAssert(configuration != nil, @"configuration cannot be empty."); if (configuration == nil) return nil; @@ -271,7 +272,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } - (void)unrefChannelWithConfiguration:(GRPCChannelConfiguration *)configuration { - @synchronized (self) { + @synchronized(self) { GRPCChannelRecord *record = _channelPool[configuration]; NSAssert(record != nil, @"No record corresponding to a proxy."); if (record == nil) return; @@ -282,9 +283,8 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; NSDate *now = [NSDate date]; record.timedDestroyDate = now; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_destroyDelay * NSEC_PER_SEC)), - _dispatchQueue, - ^{ - @synchronized (self) { + _dispatchQueue, ^{ + @synchronized(self) { if (now == record.timedDestroyDate) { // Destroy the raw channel and reset related records. record.timedDestroyDate = nil; @@ -292,7 +292,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; record.channel = nil; } } - }); + }); } } } @@ -300,16 +300,18 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; - (void)disconnectAllChannels { NSMutableSet *proxySet = [NSMutableSet set]; - @synchronized (self) { - [_channelPool enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration * _Nonnull key, GRPCChannelRecord * _Nonnull obj, BOOL * _Nonnull stop) { - obj.channel = nil; - obj.timedDestroyDate = nil; - obj.refcount = 0; - [proxySet addObject:obj.proxy]; - }]; + @synchronized(self) { + [_channelPool + enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration *_Nonnull key, + GRPCChannelRecord *_Nonnull obj, BOOL *_Nonnull stop) { + obj.channel = nil; + obj.timedDestroyDate = nil; + obj.refcount = 0; + [proxySet addObject:obj.proxy]; + }]; } // Disconnect proxies - [proxySet enumerateObjectsUsingBlock:^(GRPCPooledChannel * _Nonnull obj, BOOL * _Nonnull stop) { + [proxySet enumerateObjectsUsingBlock:^(GRPCPooledChannel *_Nonnull obj, BOOL *_Nonnull stop) { [obj disconnect]; }]; } diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m index 74ea9723b3d..0aeb67b1426 100644 --- a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m @@ -50,8 +50,7 @@ return self; } -- (grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *)args { +- (grpc_channel *)createChannelWithHost:(NSString *)host channelArgs:(NSDictionary *)args { grpc_channel_args *channelArgs = GRPCBuildChannelArgs(args); grpc_channel *unmanagedChannel = grpc_cronet_secure_channel_create(_cronetEngine, host.UTF8String, channelArgs, NULL); @@ -71,8 +70,7 @@ return nil; } -- (grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *)args { +- (grpc_channel *)createChannelWithHost:(NSString *)host channelArgs:(NSDictionary *)args { [NSException raise:NSInvalidArgumentException format:@"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."]; return NULL; diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index b693b926bad..0f2281ede85 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -122,8 +122,7 @@ static NSMutableDictionary *gHostCache; if (_transportType == GRPCTransportTypeInsecure) { options.transportType = GRPCTransportTypeInsecure; } else { - NSAssert(_transportType == GRPCTransportTypeDefault, - @"Invalid transport type"); + NSAssert(_transportType == GRPCTransportTypeDefault, @"Invalid transport type"); options.transportType = GRPCTransportTypeCronet; } } else diff --git a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m index 3e9ebe7ae02..b802137c13a 100644 --- a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m @@ -32,8 +32,7 @@ return instance; } -- (grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *)args { +- (grpc_channel *)createChannelWithHost:(NSString *)host channelArgs:(NSDictionary *)args { grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs([args copy]); grpc_channel *unmanagedChannel = grpc_insecure_channel_create(host.UTF8String, coreChannelArgs, NULL); diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 2e7f1a0dbe2..69f70de17d1 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -29,9 +29,9 @@ } + (instancetype)factoryWithPEMRootCertificates:(NSString *)rootCerts - privateKey:(NSString *)privateKey - certChain:(NSString *)certChain - error:(NSError **)errorPtr { + privateKey:(NSString *)privateKey + certChain:(NSString *)certChain + error:(NSError **)errorPtr { return [[self alloc] initWithPEMRootCerts:rootCerts privateKey:privateKey certChain:certChain @@ -50,9 +50,9 @@ } - (instancetype)initWithPEMRootCerts:(NSString *)rootCerts - privateKey:(NSString *)privateKey - certChain:(NSString *)certChain - error:(NSError **)errorPtr { + privateKey:(NSString *)privateKey + certChain:(NSString *)certChain + error:(NSError **)errorPtr { static NSData *defaultRootsASCII; static NSError *defaultRootsError; static dispatch_once_t loading; @@ -115,8 +115,7 @@ return self; } -- (grpc_channel *)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *)args { +- (grpc_channel *)createChannelWithHost:(NSString *)host channelArgs:(NSDictionary *)args { grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs([args copy]); grpc_channel *unmanagedChannel = grpc_secure_channel_create(_channelCreds, host.UTF8String, coreChannelArgs, NULL); diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 5c402250ccf..615dfc85569 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -249,8 +249,7 @@ - (instancetype)initWithHost:(NSString *)host path:(NSString *)path callOptions:(GRPCCallOptions *)callOptions { - NSAssert(host.length != 0 && path.length != 0, - @"path and host cannot be nil."); + NSAssert(host.length != 0 && path.length != 0, @"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 @@ -263,9 +262,7 @@ NSLog(@"Failed to get a channel for the host."); return nil; } - _call = [_channel unmanagedCallWithPath:path - completionQueue:_queue - callOptions:callOptions]; + _call = [_channel unmanagedCallWithPath:path completionQueue:_queue callOptions:callOptions]; if (_call == nil) { NSAssert(_channel != nil, @"Failed to get a channel for the host."); NSLog(@"Failed to create a call."); diff --git a/src/objective-c/GRPCClient/private/utilities.h b/src/objective-c/GRPCClient/private/utilities.h index 8f6baadcf7b..8e3dd793586 100644 --- a/src/objective-c/GRPCClient/private/utilities.h +++ b/src/objective-c/GRPCClient/private/utilities.h @@ -19,5 +19,4 @@ #import /** Raise exception when condition not met. */ -#define GRPCAssert(condition, errorString) \ - NSAssert(condition, errorString) +#define GRPCAssert(condition, errorString) NSAssert(condition, errorString) diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 9164f2320bf..2de2932072a 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -138,21 +138,21 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing call = _call; _call = nil; if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { - dispatch_async(_handler.dispatchQueue, ^{ - id handler = nil; - @synchronized(self) { - handler = self->_handler; - self->_handler = nil; - } - [handler closedWithTrailingMetadata:nil - error:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeCancelled - userInfo:@{ - NSLocalizedDescriptionKey : - @"Canceled by app" - }]]; - }); - } + dispatch_async(_handler.dispatchQueue, ^{ + id handler = nil; + @synchronized(self) { + handler = self->_handler; + self->_handler = nil; + } + [handler closedWithTrailingMetadata:nil + error:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeCancelled + userInfo:@{ + NSLocalizedDescriptionKey : + @"Canceled by app" + }]]; + }); + } } [call cancel]; } @@ -179,11 +179,11 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } - (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { - @synchronized (self) { + @synchronized(self) { if (initialMetadata != nil && [_handler respondsToSelector:@selector(initialMetadata:)]) { dispatch_async(_dispatchQueue, ^{ id handler = nil; - @synchronized (self) { + @synchronized(self) { handler = self->_handler; } [handler receivedInitialMetadata:initialMetadata]; @@ -197,19 +197,20 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing NSError *error = nil; GPBMessage *parsed = [_responseClass parseFromData:message error:&error]; - @synchronized (self) { + @synchronized(self) { if (parsed && [_handler respondsToSelector:@selector(receivedProtoMessage:)]) { dispatch_async(_dispatchQueue, ^{ id handler = nil; - @synchronized (self) { + @synchronized(self) { handler = self->_handler; } [handler receivedProtoMessage:parsed]; }); - } else if (!parsed && [_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]){ + } else if (!parsed && + [_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { dispatch_async(_dispatchQueue, ^{ id handler = nil; - @synchronized (self) { + @synchronized(self) { handler = self->_handler; self->_handler = nil; } @@ -222,13 +223,12 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } } -- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata - error:(NSError *)error { - @synchronized (self) { +- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { + @synchronized(self) { if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { dispatch_async(_dispatchQueue, ^{ id handler = nil; - @synchronized (self) { + @synchronized(self) { handler = self->_handler; self->_handler = nil; } diff --git a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m index 51819b12c2f..4424801c110 100644 --- a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m +++ b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m @@ -41,12 +41,12 @@ NSString *kDummyPath = @"/dummy/path"; - (void)testCreateChannelAndCall { GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCPooledChannel *channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost - callOptions:options]; + GRPCPooledChannel *channel = + (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; XCTAssertNil(channel.wrappedChannel); GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; - grpc_call *call = [channel unmanagedCallWithPath:kDummyPath - completionQueue:cq callOptions:options]; + grpc_call *call = + [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssert(call != NULL); XCTAssertNotNil(channel.wrappedChannel); [channel unrefUnmanagedCall:call]; @@ -60,26 +60,22 @@ NSString *kDummyPath = @"/dummy/path"; GRPCMutableCallOptions *options3 = [options1 mutableCopy]; options3.transportType = GRPCTransportTypeInsecure; GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; - GRPCPooledChannel *channel1 = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost - callOptions:options1]; - grpc_call *call1 = [channel1 unmanagedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options1]; - GRPCPooledChannel *channel2 = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost - callOptions:options2]; - grpc_call *call2 = [channel2 unmanagedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options2]; - GRPCPooledChannel *channel3 = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost - callOptions:options3]; - grpc_call *call3 = [channel3 unmanagedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options3]; - GRPCPooledChannel *channel4 = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost2 - callOptions:options1]; - grpc_call *call4 = [channel4 unmanagedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options1]; + GRPCPooledChannel *channel1 = + (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options1]; + grpc_call *call1 = + [channel1 unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options1]; + GRPCPooledChannel *channel2 = + (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options2]; + grpc_call *call2 = + [channel2 unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options2]; + GRPCPooledChannel *channel3 = + (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options3]; + grpc_call *call3 = + [channel3 unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options3]; + GRPCPooledChannel *channel4 = + (GRPCPooledChannel *)[pool channelWithHost:kDummyHost2 callOptions:options1]; + grpc_call *call4 = + [channel4 unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options1]; XCTAssertEqual(channel1.wrappedChannel, channel2.wrappedChannel); XCTAssertNotEqual(channel1.wrappedChannel, channel3.wrappedChannel); XCTAssertNotEqual(channel1.wrappedChannel, channel4.wrappedChannel); @@ -96,32 +92,26 @@ NSString *kDummyPath = @"/dummy/path"; GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; pool.destroyDelay = kDestroyDelay; GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCPooledChannel *channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost - callOptions:options]; + GRPCPooledChannel *channel = + (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; - grpc_call *call = [channel unmanagedCallWithPath:kDummyPath - completionQueue:cq callOptions:options]; + grpc_call *call = + [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; GRPCChannel *wrappedChannel = channel.wrappedChannel; [channel unrefUnmanagedCall:call]; // Confirm channel is not destroyed at this time - call = [channel unmanagedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + call = [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertEqual(wrappedChannel, channel.wrappedChannel); [channel unrefUnmanagedCall:call]; sleep(kDestroyDelay + 1); // Confirm channel is new at this time - call = [channel unmanagedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + call = [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertNotEqual(wrappedChannel, channel.wrappedChannel); // Confirm the new channel can create call - call = [channel unmanagedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + call = [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssert(call != NULL); [channel unrefUnmanagedCall:call]; } @@ -129,31 +119,26 @@ NSString *kDummyPath = @"/dummy/path"; - (void)testPoolDisconnection { GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCPooledChannel *channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost - callOptions:options]; + GRPCPooledChannel *channel = + (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; - grpc_call *call = [channel unmanagedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + grpc_call *call = + [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertNotNil(channel.wrappedChannel); GRPCChannel *wrappedChannel = channel.wrappedChannel; // Test a new channel is created by requesting a channel from pool [pool disconnectAllChannels]; - channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost - callOptions:options]; - call = [channel unmanagedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; + call = [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertNotNil(channel.wrappedChannel); XCTAssertNotEqual(wrappedChannel, channel.wrappedChannel); wrappedChannel = channel.wrappedChannel; // Test a new channel is created by requesting a new call from the previous proxy [pool disconnectAllChannels]; - grpc_call *call2 = [channel unmanagedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + grpc_call *call2 = + [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertNotNil(channel.wrappedChannel); XCTAssertNotEqual(channel.wrappedChannel, wrappedChannel); [channel unrefUnmanagedCall:call]; @@ -163,20 +148,17 @@ NSString *kDummyPath = @"/dummy/path"; - (void)testUnrefCallFromStaleChannel { GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCPooledChannel *channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost - callOptions:options]; + GRPCPooledChannel *channel = + (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; - grpc_call *call = [channel unmanagedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + grpc_call *call = + [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; [pool disconnectAllChannels]; - channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost - callOptions:options]; + channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; - grpc_call *call2 = [channel unmanagedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + grpc_call *call2 = + [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; // Test unref the call of a stale channel will not cause the current channel going into timed // destroy state XCTAssertNotNil(channel.wrappedChannel); diff --git a/src/objective-c/tests/ChannelTests/ChannelTests.m b/src/objective-c/tests/ChannelTests/ChannelTests.m index 212db2f653a..c07c8e69834 100644 --- a/src/objective-c/tests/ChannelTests/ChannelTests.m +++ b/src/objective-c/tests/ChannelTests/ChannelTests.m @@ -45,8 +45,8 @@ long _grpcCallCounter; } -- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration { - return nil; +- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration +*)channelConfiguration { return nil; } - (instancetype)initWithCreateExpectation:(XCTestExpectation *)createExpectation diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 8754bd5ccaf..a9f33aab6f1 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -114,8 +114,7 @@ BOOL isRemoteInteropTest(NSString *host) { } } -- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata - error:(NSError *)error { +- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { if (_closeCallback) { _closeCallback(trailingMetadata, error); } From 00ff5805a3c00e9d29cb71dfd5365c36dd5bf96c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 19 Nov 2018 09:43:24 -0800 Subject: [PATCH 196/375] null_unspecified -> nullable --- src/objective-c/GRPCClient/GRPCCall.h | 26 +++++++++++++------------- src/objective-c/ProtoRPC/ProtoRPC.h | 10 +++++----- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 4c8c11eded2..214969af230 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -306,7 +306,7 @@ NS_ASSUME_NONNULL_END * * The property is initialized to an empty NSMutableDictionary. */ -@property(null_unspecified, atomic, readonly) NSMutableDictionary *requestHeaders; +@property(nullable, atomic, readonly) NSMutableDictionary *requestHeaders; /** * This dictionary is populated with the HTTP headers received from the server. This happens before @@ -317,7 +317,7 @@ NS_ASSUME_NONNULL_END * 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(null_unspecified, atomic, readonly) NSDictionary *responseHeaders; +@property(nullable, atomic, readonly) NSDictionary *responseHeaders; /** * Same as responseHeaders, but populated with the HTTP trailers received from the server before the @@ -326,7 +326,7 @@ NS_ASSUME_NONNULL_END * The value of this property is nil until all response trailers are received, and will change * before -writesFinishedWithError: is sent to the writeable. */ -@property(null_unspecified, atomic, readonly) NSDictionary *responseTrailers; +@property(nullable, atomic, readonly) NSDictionary *responseTrailers; /** * The request writer has to write NSData objects into the provided Writeable. The server will @@ -339,9 +339,9 @@ NS_ASSUME_NONNULL_END * host parameter should not contain the scheme (http:// or https://), only the name or IP addr * and the port number, for example @"localhost:5050". */ -- (null_unspecified instancetype)initWithHost:(null_unspecified NSString *)host - path:(null_unspecified NSString *)path - requestsWriter:(null_unspecified GRXWriter *)requestWriter; +- (nullable instancetype)initWithHost:(nullable NSString *)host + path:(nullable NSString *)path + requestsWriter:(nullable GRXWriter *)requestWriter; /** * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and @@ -353,11 +353,11 @@ NS_ASSUME_NONNULL_END * The following methods are deprecated. */ + (void)setCallSafety:(GRPCCallSafety)callSafety - host:(null_unspecified NSString *)host - path:(null_unspecified NSString *)path; -@property(null_unspecified, atomic, copy, readwrite) NSString *serverName; + host:(nullable NSString *)host + path:(nullable NSString *)path; +@property(nullable, atomic, copy, readwrite) NSString *serverName; @property NSTimeInterval timeout; -- (void)setResponseDispatchQueue:(null_unspecified dispatch_queue_t)queue; +- (void)setResponseDispatchQueue:(nullable dispatch_queue_t)queue; @end @@ -368,11 +368,11 @@ DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.") @protocol GRPCRequestHeaders @property(nonatomic, readonly) NSUInteger count; -- (null_unspecified id)objectForKeyedSubscript:(null_unspecified id)key; -- (void)setObject:(null_unspecified id)obj forKeyedSubscript:(null_unspecified id)key; +- (nullable id)objectForKeyedSubscript:(nullable id)key; +- (void)setObject:(nullable id)obj forKeyedSubscript:(nullable id)key; - (void)removeAllObjects; -- (void)removeObjectForKey:(null_unspecified id)key; +- (void)removeObjectForKey:(nullable id)key; @end #pragma clang diagnostic push diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 98b60c3f727..2623aecb82f 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -132,11 +132,11 @@ __attribute__((deprecated("Please use GRPCProtoCall."))) @interface ProtoRPC * addr and the port number, for example @"localhost:5050". */ - - (instancetype _Null_unspecified)initWithHost : (NSString *_Null_unspecified)host method - : (GRPCProtoMethod *_Null_unspecified)method requestsWriter - : (GRXWriter *_Null_unspecified)requestsWriter responseClass - : (Class _Null_unspecified)responseClass responsesWriteable - : (id _Null_unspecified)responsesWriteable NS_DESIGNATED_INITIALIZER; + (nullable instancetype)initWithHost : (nullable NSString *)host method + : (nullable GRPCProtoMethod *)method requestsWriter + : (nullable GRXWriter *)requestsWriter responseClass + : (nullable Class)responseClass responsesWriteable + : (nullable id)responsesWriteable NS_DESIGNATED_INITIALIZER; - (void)start; @end From 29e1591904539fcb6d92ba49e69ed27ee9d3349d Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 19 Nov 2018 09:52:29 -0800 Subject: [PATCH 197/375] _Nullable -> nullable --- .../GRPCClient/private/GRPCCronetChannelFactory.h | 8 ++++---- .../GRPCClient/private/GRPCInsecureChannelFactory.h | 8 ++++---- .../GRPCClient/private/GRPCSecureChannelFactory.h | 12 ++++++------ src/objective-c/tests/APIv2Tests/APIv2Tests.m | 8 ++++---- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h index 5e35576ea10..738dfdb7370 100644 --- a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.h @@ -24,12 +24,12 @@ NS_ASSUME_NONNULL_BEGIN @interface GRPCCronetChannelFactory : NSObject -+ (instancetype _Nullable)sharedInstance; ++ (nullable instancetype)sharedInstance; -- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *_Nullable)args; +- (nullable grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(nullable NSDictionary *)args; -- (instancetype _Nullable)init NS_UNAVAILABLE; +- (nullable instancetype)init NS_UNAVAILABLE; @end diff --git a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h index 98a985fe84d..2d471aebed6 100644 --- a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.h @@ -23,12 +23,12 @@ NS_ASSUME_NONNULL_BEGIN @interface GRPCInsecureChannelFactory : NSObject -+ (instancetype _Nullable)sharedInstance; ++ (nullable instancetype)sharedInstance; -- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *_Nullable)args; +- (nullable grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(nullable NSDictionary *)args; -- (instancetype _Nullable)init NS_UNAVAILABLE; +- (nullable instancetype)init NS_UNAVAILABLE; @end diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h index 02e7052996d..5dc5a973120 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h @@ -23,15 +23,15 @@ NS_ASSUME_NONNULL_BEGIN @interface GRPCSecureChannelFactory : NSObject -+ (instancetype _Nullable)factoryWithPEMRootCertificates:(NSString *_Nullable)rootCerts - privateKey:(NSString *_Nullable)privateKey - certChain:(NSString *_Nullable)certChain ++ (nullable instancetype)factoryWithPEMRootCertificates:(nullable NSString *)rootCerts + privateKey:(nullable NSString *)privateKey + certChain:(nullable NSString *)certChain error:(NSError **)errorPtr; -- (grpc_channel *_Nullable)createChannelWithHost:(NSString *)host - channelArgs:(NSDictionary *_Nullable)args; +- (nullable grpc_channel *)createChannelWithHost:(NSString *)host + channelArgs:(nullable NSDictionary *)args; -- (instancetype _Nullable)init NS_UNAVAILABLE; +- (nullable instancetype)init NS_UNAVAILABLE; @end diff --git a/src/objective-c/tests/APIv2Tests/APIv2Tests.m b/src/objective-c/tests/APIv2Tests/APIv2Tests.m index e49f58ae9d3..1b14043af92 100644 --- a/src/objective-c/tests/APIv2Tests/APIv2Tests.m +++ b/src/objective-c/tests/APIv2Tests/APIv2Tests.m @@ -81,20 +81,20 @@ static const NSTimeInterval kTestTimeout = 16; return self; } -- (void)receivedInitialMetadata:(NSDictionary *_Nullable)initialMetadata { +- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { if (self->_initialMetadataCallback) { self->_initialMetadataCallback(initialMetadata); } } -- (void)receivedRawMessage:(GPBMessage *_Nullable)message { +- (void)receivedRawMessage:(GPBMessage *)message { if (self->_messageCallback) { self->_messageCallback(message); } } -- (void)closedWithTrailingMetadata:(NSDictionary *_Nullable)trailingMetadata - error:(NSError *_Nullable)error { +- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata + error:(NSError *)error { if (self->_closeCallback) { self->_closeCallback(trailingMetadata, error); } From d806ce71d762a1a2fc03e41cc186d002ee604316 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 19 Nov 2018 10:08:23 -0800 Subject: [PATCH 198/375] more nullability --- src/objective-c/GRPCClient/GRPCCallOptions.h | 2 +- .../GRPCClient/private/GRPCSecureChannelFactory.h | 6 +++--- src/objective-c/tests/APIv2Tests/APIv2Tests.m | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 61d85642863..e88e28109cf 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -64,7 +64,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * This method is called when gRPC is about to start the call. When OAuth token is acquired, * \a handler is expected to be called with \a token being the new token to be used for this call. */ -- (void)getTokenWithHandler:(void (^)(NSString *token))handler; +- (void)getTokenWithHandler:(void (^)(NSString * _Nullable token))handler; @end @interface GRPCCallOptions : NSObject diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h index 5dc5a973120..588239b7064 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.h @@ -24,9 +24,9 @@ NS_ASSUME_NONNULL_BEGIN @interface GRPCSecureChannelFactory : NSObject + (nullable instancetype)factoryWithPEMRootCertificates:(nullable NSString *)rootCerts - privateKey:(nullable NSString *)privateKey - certChain:(nullable NSString *)certChain - error:(NSError **)errorPtr; + privateKey:(nullable NSString *)privateKey + certChain:(nullable NSString *)certChain + error:(NSError **)errorPtr; - (nullable grpc_channel *)createChannelWithHost:(NSString *)host channelArgs:(nullable NSDictionary *)args; diff --git a/src/objective-c/tests/APIv2Tests/APIv2Tests.m b/src/objective-c/tests/APIv2Tests/APIv2Tests.m index 1b14043af92..32f2122f79b 100644 --- a/src/objective-c/tests/APIv2Tests/APIv2Tests.m +++ b/src/objective-c/tests/APIv2Tests/APIv2Tests.m @@ -93,8 +93,7 @@ static const NSTimeInterval kTestTimeout = 16; } } -- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata - error:(NSError *)error { +- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { if (self->_closeCallback) { self->_closeCallback(trailingMetadata, error); } From 1d8550c4c27ca357195946759f161942a6e07589 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 19 Nov 2018 11:26:24 -0800 Subject: [PATCH 199/375] nit nullability fix --- src/objective-c/GRPCClient/GRPCCallOptions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index e88e28109cf..48bb11aeeb0 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -64,7 +64,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * This method is called when gRPC is about to start the call. When OAuth token is acquired, * \a handler is expected to be called with \a token being the new token to be used for this call. */ -- (void)getTokenWithHandler:(void (^)(NSString * _Nullable token))handler; +- (void)getTokenWithHandler:(void (^ _Nullable)(NSString * _Nullable token))handler; @end @interface GRPCCallOptions : NSObject From 195c042d3231d0ebbb1c2684ce32457b879062ef Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 19 Nov 2018 17:35:21 -0800 Subject: [PATCH 200/375] Replace PB_FIELD_16BIT with PB_FIELD_32BIT --- CMakeLists.txt | 2 +- gRPC-Core.podspec | 2 +- setup.py | 2 +- .../lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c | 4 ++-- src/core/tsi/alts/handshaker/altscontext.pb.c | 4 ++-- src/core/tsi/alts/handshaker/handshaker.pb.c | 4 ++-- src/core/tsi/alts/handshaker/transport_security_common.pb.c | 4 ++-- templates/CMakeLists.txt.template | 2 +- templates/gRPC-Core.podspec.template | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c2ba2048c0..f1bcb7b9f99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,7 +94,7 @@ endif() set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) -add_definitions(-DPB_FIELD_16BIT) +add_definitions(-DPB_FIELD_32BIT) if (MSVC) include(cmake/msvc_static_runtime.cmake) diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index f0a715cb585..bd48ea3825a 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -93,7 +93,7 @@ Pod::Spec.new do |s| } s.default_subspecs = 'Interface', 'Implementation' - s.compiler_flags = '-DGRPC_ARES=0', '-DPB_FIELD_16BIT' + s.compiler_flags = '-DGRPC_ARES=0', '-DPB_FIELD_32BIT' s.libraries = 'c++' # Like many other C libraries, gRPC-Core has its public headers under `include//` and its diff --git a/setup.py b/setup.py index ae86e6c9fb7..c3aae1696b9 100644 --- a/setup.py +++ b/setup.py @@ -144,7 +144,7 @@ if EXTRA_ENV_COMPILE_ARGS is None: EXTRA_ENV_COMPILE_ARGS += ' -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions' elif "darwin" in sys.platform: EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden -fno-wrapv -fno-exceptions' -EXTRA_ENV_COMPILE_ARGS += ' -DPB_FIELD_16BIT' +EXTRA_ENV_COMPILE_ARGS += ' -DPB_FIELD_32BIT' if EXTRA_ENV_LINK_ARGS is None: EXTRA_ENV_LINK_ARGS = '' diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c index f6538e1349f..a7b072420ec 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c @@ -75,14 +75,14 @@ PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) #endif #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) -/* If you get an error here, it means that you need to define PB_FIELD_16BIT +/* If you get an error here, it means that you need to define PB_FIELD_32BIT * compile-time option. You can do that in pb.h or on compiler command line. * * The reason you need to do this is that some of your messages contain tag * numbers or field sizes that are larger than what can fit in the default * 8 bit descriptors. */ -PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 256 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v1_ServerList, servers) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) +PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 256 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v1_ServerList, servers) < 256), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) #endif diff --git a/src/core/tsi/alts/handshaker/altscontext.pb.c b/src/core/tsi/alts/handshaker/altscontext.pb.c index 5fb152a558e..2320edb1eff 100644 --- a/src/core/tsi/alts/handshaker/altscontext.pb.c +++ b/src/core/tsi/alts/handshaker/altscontext.pb.c @@ -33,14 +33,14 @@ PB_STATIC_ASSERT((pb_membersize(grpc_gcp_AltsContext, peer_rpc_versions) < 65536 #endif #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) -/* If you get an error here, it means that you need to define PB_FIELD_16BIT +/* If you get an error here, it means that you need to define PB_FIELD_32BIT * compile-time option. You can do that in pb.h or on compiler command line. * * The reason you need to do this is that some of your messages contain tag * numbers or field sizes that are larger than what can fit in the default * 8 bit descriptors. */ -PB_STATIC_ASSERT((pb_membersize(grpc_gcp_AltsContext, peer_rpc_versions) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_gcp_AltsContext) +PB_STATIC_ASSERT((pb_membersize(grpc_gcp_AltsContext, peer_rpc_versions) < 256), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_gcp_AltsContext) #endif diff --git a/src/core/tsi/alts/handshaker/handshaker.pb.c b/src/core/tsi/alts/handshaker/handshaker.pb.c index 5450b1602d4..8eda290e123 100644 --- a/src/core/tsi/alts/handshaker/handshaker.pb.c +++ b/src/core/tsi/alts/handshaker/handshaker.pb.c @@ -108,14 +108,14 @@ PB_STATIC_ASSERT((pb_membersize(grpc_gcp_StartClientHandshakeReq, target_identit #endif #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) -/* If you get an error here, it means that you need to define PB_FIELD_16BIT +/* If you get an error here, it means that you need to define PB_FIELD_32BIT * compile-time option. You can do that in pb.h or on compiler command line. * * The reason you need to do this is that some of your messages contain tag * numbers or field sizes that are larger than what can fit in the default * 8 bit descriptors. */ -PB_STATIC_ASSERT((pb_membersize(grpc_gcp_StartClientHandshakeReq, target_identities) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, local_identity) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, local_endpoint) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, remote_endpoint) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, rpc_versions) < 256 && pb_membersize(grpc_gcp_ServerHandshakeParameters, local_identities) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, handshake_parameters[0]) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, local_endpoint) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, remote_endpoint) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, rpc_versions) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry, value) < 256 && pb_membersize(grpc_gcp_HandshakerReq, client_start) < 256 && pb_membersize(grpc_gcp_HandshakerReq, server_start) < 256 && pb_membersize(grpc_gcp_HandshakerReq, next) < 256 && pb_membersize(grpc_gcp_HandshakerResult, peer_identity) < 256 && pb_membersize(grpc_gcp_HandshakerResult, local_identity) < 256 && pb_membersize(grpc_gcp_HandshakerResult, peer_rpc_versions) < 256 && pb_membersize(grpc_gcp_HandshakerResp, result) < 256 && pb_membersize(grpc_gcp_HandshakerResp, status) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_gcp_Endpoint_grpc_gcp_Identity_grpc_gcp_StartClientHandshakeReq_grpc_gcp_ServerHandshakeParameters_grpc_gcp_StartServerHandshakeReq_grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_grpc_gcp_NextHandshakeMessageReq_grpc_gcp_HandshakerReq_grpc_gcp_HandshakerResult_grpc_gcp_HandshakerStatus_grpc_gcp_HandshakerResp) +PB_STATIC_ASSERT((pb_membersize(grpc_gcp_StartClientHandshakeReq, target_identities) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, local_identity) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, local_endpoint) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, remote_endpoint) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, rpc_versions) < 256 && pb_membersize(grpc_gcp_ServerHandshakeParameters, local_identities) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, handshake_parameters[0]) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, local_endpoint) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, remote_endpoint) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, rpc_versions) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry, value) < 256 && pb_membersize(grpc_gcp_HandshakerReq, client_start) < 256 && pb_membersize(grpc_gcp_HandshakerReq, server_start) < 256 && pb_membersize(grpc_gcp_HandshakerReq, next) < 256 && pb_membersize(grpc_gcp_HandshakerResult, peer_identity) < 256 && pb_membersize(grpc_gcp_HandshakerResult, local_identity) < 256 && pb_membersize(grpc_gcp_HandshakerResult, peer_rpc_versions) < 256 && pb_membersize(grpc_gcp_HandshakerResp, result) < 256 && pb_membersize(grpc_gcp_HandshakerResp, status) < 256), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_gcp_Endpoint_grpc_gcp_Identity_grpc_gcp_StartClientHandshakeReq_grpc_gcp_ServerHandshakeParameters_grpc_gcp_StartServerHandshakeReq_grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_grpc_gcp_NextHandshakeMessageReq_grpc_gcp_HandshakerReq_grpc_gcp_HandshakerResult_grpc_gcp_HandshakerStatus_grpc_gcp_HandshakerResp) #endif diff --git a/src/core/tsi/alts/handshaker/transport_security_common.pb.c b/src/core/tsi/alts/handshaker/transport_security_common.pb.c index 326b1b10ab7..aac699314e7 100644 --- a/src/core/tsi/alts/handshaker/transport_security_common.pb.c +++ b/src/core/tsi/alts/handshaker/transport_security_common.pb.c @@ -35,14 +35,14 @@ PB_STATIC_ASSERT((pb_membersize(grpc_gcp_RpcProtocolVersions, max_rpc_version) < #endif #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) -/* If you get an error here, it means that you need to define PB_FIELD_16BIT +/* If you get an error here, it means that you need to define PB_FIELD_32BIT * compile-time option. You can do that in pb.h or on compiler command line. * * The reason you need to do this is that some of your messages contain tag * numbers or field sizes that are larger than what can fit in the default * 8 bit descriptors. */ -PB_STATIC_ASSERT((pb_membersize(grpc_gcp_RpcProtocolVersions, max_rpc_version) < 256 && pb_membersize(grpc_gcp_RpcProtocolVersions, min_rpc_version) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_gcp_RpcProtocolVersions_grpc_gcp_RpcProtocolVersions_Version) +PB_STATIC_ASSERT((pb_membersize(grpc_gcp_RpcProtocolVersions, max_rpc_version) < 256 && pb_membersize(grpc_gcp_RpcProtocolVersions, min_rpc_version) < 256), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_gcp_RpcProtocolVersions_grpc_gcp_RpcProtocolVersions_Version) #endif diff --git a/templates/CMakeLists.txt.template b/templates/CMakeLists.txt.template index 1628493d000..f33d980cd00 100644 --- a/templates/CMakeLists.txt.template +++ b/templates/CMakeLists.txt.template @@ -143,7 +143,7 @@ ## Some libraries are shared even with BUILD_SHARED_LIBRARIES=OFF set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) - add_definitions(-DPB_FIELD_16BIT) + add_definitions(-DPB_FIELD_32BIT) if (MSVC) include(cmake/msvc_static_runtime.cmake) diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template index 98b6344a4bf..17178af4195 100644 --- a/templates/gRPC-Core.podspec.template +++ b/templates/gRPC-Core.podspec.template @@ -152,7 +152,7 @@ } s.default_subspecs = 'Interface', 'Implementation' - s.compiler_flags = '-DGRPC_ARES=0', '-DPB_FIELD_16BIT' + s.compiler_flags = '-DGRPC_ARES=0', '-DPB_FIELD_32BIT' s.libraries = 'c++' # Like many other C libraries, gRPC-Core has its public headers under `include//` and its From f62323aea28260d4233487dc84834dd26c48845c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 20 Nov 2018 13:21:07 -0800 Subject: [PATCH 201/375] Tests project fixes --- src/objective-c/tests/Tests.xcodeproj/project.pbxproj | 8 -------- .../xcshareddata/xcschemes/ChannelTests.xcscheme | 7 +++++-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj index 6d1932b0215..6f24d3512f8 100644 --- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj +++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj @@ -1276,15 +1276,11 @@ buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-APIv2Tests-checkManifestLockResult.txt", ); @@ -1856,15 +1852,11 @@ buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - ); outputPaths = ( "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle", ); diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/ChannelTests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/ChannelTests.xcscheme index 16ae481123b..8c8623d7b21 100644 --- a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/ChannelTests.xcscheme +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/ChannelTests.xcscheme @@ -26,7 +26,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + @@ -47,7 +51,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" From 726f044932c2ae096d05f4f6cac2850ae2be3f83 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 21 Nov 2018 14:24:22 -0800 Subject: [PATCH 202/375] Include linux/version.h for manylinux --- include/grpc/impl/codegen/port_platform.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index b2028a63053..6795f05a6d9 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -121,6 +121,7 @@ #else /* _LP64 */ #define GPR_ARCH_32 1 #endif /* _LP64 */ +#include #elif defined(ANDROID) || defined(__ANDROID__) #define GPR_PLATFORM_STRING "android" #define GPR_ANDROID 1 From 03c73e92f1dedb1de4bba0269e7c614b47cf8035 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 21 Nov 2018 15:31:10 -0800 Subject: [PATCH 203/375] Fix test failure due to NSAssert --- src/objective-c/tests/Podfile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile index 5df9d4e85bd..12112f95e14 100644 --- a/src/objective-c/tests/Podfile +++ b/src/objective-c/tests/Podfile @@ -148,5 +148,14 @@ post_install do |installer| end end end + + # Enable NSAssert on gRPC + if target.name == 'gRPC' || target.name == 'ProtoRPC' || target.name == 'RxLibrary' + target.build_configurations.each do |config| + if config.name != 'Release' + config.build_settings['ENABLE_NS_ASSERTIONS'] = 'YES' + end + end + end end end From 5ae61f5a5a267f5975248d4262133a740e09a66b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 26 Nov 2018 17:17:09 -0800 Subject: [PATCH 204/375] Multiple fixes --- .../GRPCClient/GRPCCall+ChannelArg.m | 2 +- src/objective-c/GRPCClient/GRPCCall.m | 53 +++---- .../GRPCClient/private/ChannelArgsUtil.m | 21 ++- .../GRPCClient/private/GRPCChannel.h | 6 +- .../GRPCClient/private/GRPCChannel.m | 66 ++++---- .../GRPCClient/private/GRPCChannelPool.h | 49 +++--- .../GRPCClient/private/GRPCChannelPool.m | 145 +++++++++--------- .../GRPCClient/private/GRPCWrappedCall.m | 2 +- src/objective-c/ProtoRPC/ProtoRPC.m | 38 ++--- .../tests/ChannelTests/ChannelPoolTest.m | 40 +++-- .../tests/ChannelTests/ChannelTests.m | 4 +- src/objective-c/tests/GRPCClientTests.m | 7 +- 12 files changed, 221 insertions(+), 212 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m index 703cff63bb0..ae60d6208e1 100644 --- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m +++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m @@ -36,7 +36,7 @@ } + (void)closeOpenConnections { - [[GRPCChannelPool sharedInstance] closeOpenConnections]; + [[GRPCChannelPool sharedInstance] disconnectAllChannels]; } + (void)setDefaultCompressMethod:(GRPCCompressAlgorithm)algorithm forhost:(nonnull NSString *)host { diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 94e470d4ed9..bf9441c27eb 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -69,11 +69,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety { NSAssert(host.length != 0 && path.length != 0, @"Host and Path cannot be empty"); - if (host.length == 0) { - host = [NSString string]; - } - if (path.length == 0) { - path = [NSString string]; + if (host.length == 0 || path.length == 0) { + return nil; } if ((self = [super init])) { _host = [host copy]; @@ -173,7 +170,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)start { - GRPCCall *call = nil; + GRPCCall *copiedCall = nil; @synchronized(self) { NSAssert(!_started, @"Call already started."); NSAssert(!_canceled, @"Call already canceled."); @@ -197,7 +194,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; if (_callOptions.initialMetadata) { [_call.requestHeaders addEntriesFromDictionary:_callOptions.initialMetadata]; } - call = _call; + copiedCall = _call; } void (^valueHandler)(id value) = ^(id value) { @@ -235,11 +232,11 @@ const char *kCFStreamVarName = "grpc_cfstream"; }; id responseWriteable = [[GRXWriteable alloc] initWithValueHandler:valueHandler completionHandler:completionHandler]; - [call startWithWriteable:responseWriteable]; + [copiedCall startWithWriteable:responseWriteable]; } - (void)cancel { - GRPCCall *call = nil; + GRPCCall *copiedCall = nil; @synchronized(self) { if (_canceled) { return; @@ -247,7 +244,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; _canceled = YES; - call = _call; + copiedCall = _call; _call = nil; _pipe = nil; @@ -268,13 +265,15 @@ const char *kCFStreamVarName = "grpc_cfstream"; @"Canceled by app" }]]; }); + } else { + _handler = nil; } } - [call cancel]; + [copiedCall cancel]; } - (void)writeData:(NSData *)data { - GRXBufferedPipe *pipe = nil; + GRXBufferedPipe *copiedPipe = nil; @synchronized(self) { NSAssert(!_canceled, @"Call arleady canceled."); NSAssert(!_finished, @"Call is half-closed before sending data."); @@ -286,14 +285,14 @@ const char *kCFStreamVarName = "grpc_cfstream"; } if (_pipe) { - pipe = _pipe; + copiedPipe = _pipe; } } - [pipe writeValue:data]; + [copiedPipe writeValue:data]; } - (void)finish { - GRXBufferedPipe *pipe = nil; + GRXBufferedPipe *copiedPipe = nil; @synchronized(self) { NSAssert(_started, @"Call not started."); NSAssert(!_canceled, @"Call arleady canceled."); @@ -309,12 +308,12 @@ const char *kCFStreamVarName = "grpc_cfstream"; } if (_pipe) { - pipe = _pipe; + copiedPipe = _pipe; _pipe = nil; } _finished = YES; } - [pipe writesFinishedWithError:nil]; + [copiedPipe writesFinishedWithError:nil]; } - (void)issueInitialMetadata:(NSDictionary *)initialMetadata { @@ -322,11 +321,11 @@ const char *kCFStreamVarName = "grpc_cfstream"; if (initialMetadata != nil && [_handler respondsToSelector:@selector(receivedInitialMetadata:)]) { dispatch_async(_dispatchQueue, ^{ - id handler = nil; + id copiedHandler = nil; @synchronized(self) { - handler = self->_handler; + copiedHandler = self->_handler; } - [handler receivedInitialMetadata:initialMetadata]; + [copiedHandler receivedInitialMetadata:initialMetadata]; }); } } @@ -336,11 +335,11 @@ const char *kCFStreamVarName = "grpc_cfstream"; @synchronized(self) { if (message != nil && [_handler respondsToSelector:@selector(receivedRawMessage:)]) { dispatch_async(_dispatchQueue, ^{ - id handler = nil; + id copiedHandler = nil; @synchronized(self) { - handler = self->_handler; + copiedHandler = self->_handler; } - [handler receivedRawMessage:message]; + [copiedHandler receivedRawMessage:message]; }); } } @@ -350,14 +349,16 @@ const char *kCFStreamVarName = "grpc_cfstream"; @synchronized(self) { if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { dispatch_async(_dispatchQueue, ^{ - id handler = nil; + id copiedHandler = nil; @synchronized(self) { - handler = self->_handler; + copiedHandler = self->_handler; // Clean up _handler so that no more responses are reported to the handler. self->_handler = nil; } - [handler closedWithTrailingMetadata:trailingMetadata error:error]; + [copiedHandler closedWithTrailingMetadata:trailingMetadata error:error]; }); + } else { + _handler = nil; } } } diff --git a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m index d9e44b557d1..3135fcff028 100644 --- a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m +++ b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m @@ -60,36 +60,35 @@ grpc_channel_args *GRPCBuildChannelArgs(NSDictionary *dictionary) { NSUInteger argCount = [keys count]; grpc_channel_args *channelArgs = gpr_malloc(sizeof(grpc_channel_args)); - channelArgs->num_args = argCount; channelArgs->args = gpr_malloc(argCount * sizeof(grpc_arg)); // TODO(kriswuollett) Check that keys adhere to GRPC core library requirements + NSUInteger j = 0; for (NSUInteger i = 0; i < argCount; ++i) { - grpc_arg *arg = &channelArgs->args[i]; + grpc_arg *arg = &channelArgs->args[j]; arg->key = gpr_strdup([keys[i] UTF8String]); id value = dictionary[keys[i]]; if ([value respondsToSelector:@selector(UTF8String)]) { arg->type = GRPC_ARG_STRING; arg->value.string = gpr_strdup([value UTF8String]); + j++; } else if ([value respondsToSelector:@selector(intValue)]) { - if ([value compare:[NSNumber numberWithInteger:INT_MAX]] == NSOrderedDescending || - [value compare:[NSNumber numberWithInteger:INT_MIN]] == NSOrderedAscending) { - [NSException raise:NSInvalidArgumentException - format:@"Out of range for a value-typed channel argument: %@", value]; + int64_t value64 = [value longLongValue]; + if (value64 <= INT_MAX || value64 >= INT_MIN) { + arg->type = GRPC_ARG_INTEGER; + arg->value.integer = [value intValue]; + j++; } - arg->type = GRPC_ARG_INTEGER; - arg->value.integer = [value intValue]; } else if (value != nil) { arg->type = GRPC_ARG_POINTER; arg->value.pointer.p = (__bridge_retained void *)value; arg->value.pointer.vtable = &objc_arg_vtable; - } else { - [NSException raise:NSInvalidArgumentException - format:@"Invalid channel argument type: %@", [value class]]; + j++; } } + channelArgs->num_args = j; return channelArgs; } diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index 5426b28d758..147015bed10 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -32,6 +32,10 @@ NS_ASSUME_NONNULL_BEGIN /** Caching signature of a channel. */ @interface GRPCChannelConfiguration : NSObject +- (instancetype)init NS_UNAVAILABLE; + ++ (instancetype) new NS_UNAVAILABLE; + /** The host that this channel is connected to. */ @property(copy, readonly) NSString *host; @@ -47,7 +51,7 @@ NS_ASSUME_NONNULL_BEGIN /** Acquire the dictionary of channel args with current configurations. */ @property(copy, readonly) NSDictionary *channelArgs; -- (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; +- (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index e4cefc338c6..24cf670d1b5 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -39,8 +39,9 @@ - (instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { NSAssert(host.length > 0, @"Host must not be empty."); NSAssert(callOptions != nil, @"callOptions must not be empty."); - if (host.length == 0) return nil; - if (callOptions == nil) return nil; + if (host.length == 0 || callOptions == nil) { + return nil; + } if ((self = [super init])) { _host = [host copy]; @@ -180,7 +181,9 @@ - (instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration { NSAssert(channelConfiguration != nil, @"channelConfiguration must not be empty."); - if (channelConfiguration == nil) return nil; + if (channelConfiguration == nil) { + return nil; + } if ((self = [super init])) { _configuration = [channelConfiguration copy]; @@ -218,35 +221,34 @@ if (callOptions == nil) return NULL; grpc_call *call = NULL; - @synchronized(self) { - NSAssert(_unmanagedChannel != NULL, @"Channel should have valid unmanaged channel."); - if (_unmanagedChannel == NULL) return NULL; - - NSString *serverAuthority = - callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; - NSTimeInterval timeout = callOptions.timeout; - NSAssert(timeout >= 0, @"Invalid timeout"); - if (timeout < 0) return NULL; - grpc_slice host_slice = grpc_empty_slice(); - if (serverAuthority) { - host_slice = grpc_slice_from_copied_string(serverAuthority.UTF8String); - } - grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); - gpr_timespec deadline_ms = - timeout == 0 ? gpr_inf_future(GPR_CLOCK_REALTIME) - : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); - call = grpc_channel_create_call(_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, - queue.unmanagedQueue, path_slice, - serverAuthority ? &host_slice : NULL, deadline_ms, NULL); - if (serverAuthority) { - grpc_slice_unref(host_slice); - } - grpc_slice_unref(path_slice); - NSAssert(call != nil, @"Unable to create call."); - if (call == NULL) { - NSLog(@"Unable to create call."); - } + // No need to lock here since _unmanagedChannel is only changed in _dealloc + NSAssert(_unmanagedChannel != NULL, @"Channel should have valid unmanaged channel."); + if (_unmanagedChannel == NULL) return NULL; + + NSString *serverAuthority = + callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; + NSTimeInterval timeout = callOptions.timeout; + NSAssert(timeout >= 0, @"Invalid timeout"); + if (timeout < 0) return NULL; + grpc_slice host_slice = grpc_empty_slice(); + if (serverAuthority) { + host_slice = grpc_slice_from_copied_string(serverAuthority.UTF8String); + } + grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); + gpr_timespec deadline_ms = + timeout == 0 ? gpr_inf_future(GPR_CLOCK_REALTIME) + : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); + call = grpc_channel_create_call(_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, + queue.unmanagedQueue, path_slice, + serverAuthority ? &host_slice : NULL, deadline_ms, NULL); + if (serverAuthority) { + grpc_slice_unref(host_slice); + } + grpc_slice_unref(path_slice); + NSAssert(call != nil, @"Unable to create call."); + if (call == NULL) { + NSLog(@"Unable to create call."); } return call; } diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 1e3c1d7d976..26600ef3a96 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -39,12 +39,16 @@ NS_ASSUME_NONNULL_BEGIN */ @interface GRPCPooledChannel : NSObject +- (nullable instancetype)init NS_UNAVAILABLE; + ++ (nullable instancetype)new NS_UNAVAILABLE; + /** * Initialize with an actual channel object \a channel and a reference to the channel pool. */ - (nullable instancetype)initWithChannelConfiguration: (GRPCChannelConfiguration *)channelConfiguration - channelPool:(GRPCChannelPool *)channelPool; + channelPool:(GRPCChannelPool *)channelPool NS_DESIGNATED_INITIALIZER; /** * Create a grpc core call object (grpc_call) from this channel. If channel is disconnected, get a @@ -59,17 +63,21 @@ NS_ASSUME_NONNULL_BEGIN * \a unmanagedCallWithPath:completionQueue:callOptions: and decrease channel refcount. If refcount * of the channel becomes 0, return the channel object to channel pool. */ -- (void)unrefUnmanagedCall:(grpc_call *)unmanagedCall; +- (void)destroyUnmanagedCall:(grpc_call *)unmanagedCall; /** - * Force the channel to disconnect immediately. + * Force the channel to disconnect immediately. Subsequent calls to unmanagedCallWithPath: will + * attempt to reconnect to the remote channel. */ - (void)disconnect; -// The following methods and properties are for test only +@end + +/** Test-only interface for \a GRPCPooledChannel. */ +@interface GRPCPooledChannel (Test) /** - * Return the pointer to the real channel wrapped by the proxy. + * Return the pointer to the raw channel wrapped. */ @property(atomic, readonly) GRPCChannel *wrappedChannel; @@ -81,6 +89,10 @@ NS_ASSUME_NONNULL_BEGIN */ @interface GRPCChannelPool : NSObject +- (nullable instancetype)init NS_UNAVAILABLE; + ++ (nullable instancetype)new NS_UNAVAILABLE; + /** * Get the global channel pool. */ @@ -92,31 +104,20 @@ NS_ASSUME_NONNULL_BEGIN - (GRPCPooledChannel *)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; /** - * This method is deprecated. - * - * Destroy all open channels and close their connections. + * Disconnect all channels in this pool. */ -- (void)closeOpenConnections; - -// Test-only methods below +- (void)disconnectAllChannels; -/** - * Get an instance of pool isolated from the global shared pool. This method is for test only. - * Global pool should be used in production. - */ -- (nullable instancetype)init; +@end -/** - * Simulate a network transition event and destroy all channels. This method is for internal and - * test only. - */ -- (void)disconnectAllChannels; +/** Test-only interface for \a GRPCChannelPool. */ +@interface GRPCChannelPool (Test) /** - * Set the destroy delay of channels. A channel should be destroyed if it stayed idle (no active - * call on it) for this period of time. This property is for test only. + * Get an instance of pool isolated from the global shared pool with channels' destroy delay being + * \a destroyDelay. */ -@property(atomic) NSTimeInterval destroyDelay; +- (nullable instancetype)initTestPoolWithDestroyDelay:(NSTimeInterval)destroyDelay; @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 7c139b37176..f6615b58405 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -52,10 +52,9 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; __weak GRPCChannelPool *_channelPool; GRPCChannelConfiguration *_channelConfiguration; NSMutableSet *_unmanagedCalls; + GRPCChannel *_wrappedChannel; } -@synthesize wrappedChannel = _wrappedChannel; - - (instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration channelPool:(GRPCChannelPool *)channelPool { NSAssert(channelConfiguration != nil, @"channelConfiguration cannot be empty."); @@ -68,11 +67,17 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; _channelPool = channelPool; _channelConfiguration = channelConfiguration; _unmanagedCalls = [NSMutableSet set]; + _wrappedChannel = nil; } return self; } +- (void)dealloc { + NSAssert([_unmanagedCalls count] == 0 && _wrappedChannel == nil, @"Pooled channel should only be" + "destroyed after the wrapped channel is destroyed"); +} + - (grpc_call *)unmanagedCallWithPath:(NSString *)path completionQueue:(GRPCCompletionQueue *)queue callOptions:(GRPCCallOptions *)callOptions { @@ -99,31 +104,38 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; return call; } -- (void)unrefUnmanagedCall:(grpc_call *)unmanagedCall { - if (unmanagedCall == nil) return; +- (void)destroyUnmanagedCall:(grpc_call *)unmanagedCall { + if (unmanagedCall == NULL) { + return; + } grpc_call_unref(unmanagedCall); - BOOL timedDestroy = NO; @synchronized(self) { - if ([_unmanagedCalls containsObject:[NSValue valueWithPointer:unmanagedCall]]) { - [_unmanagedCalls removeObject:[NSValue valueWithPointer:unmanagedCall]]; - if ([_unmanagedCalls count] == 0) { - timedDestroy = YES; - } + NSValue *removedCall = [NSValue valueWithPointer:unmanagedCall]; + [_unmanagedCalls removeObject:removedCall]; + if ([_unmanagedCalls count] == 0) { + _wrappedChannel = nil; + GRPCChannelPool *strongPool = _channelPool; + [strongPool unrefChannelWithConfiguration:_channelConfiguration]; } } - if (timedDestroy) { - [self timedDestroy]; - } } - (void)disconnect { @synchronized(self) { - _wrappedChannel = nil; - [_unmanagedCalls removeAllObjects]; + if (_wrappedChannel != nil) { + _wrappedChannel = nil; + [_unmanagedCalls removeAllObjects]; + GRPCChannelPool *strongPool = _channelPool; + [strongPool unrefChannelWithConfiguration:_channelConfiguration]; + } } } +@end + +@implementation GRPCPooledChannel (Test) + - (GRPCChannel *)wrappedChannel { GRPCChannel *channel = nil; @synchronized(self) { @@ -132,67 +144,52 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; return channel; } -- (void)timedDestroy { - __strong GRPCChannelPool *pool = nil; - @synchronized(self) { - // Check if we still want to destroy the channel. - if ([_unmanagedCalls count] == 0) { - pool = _channelPool; - _wrappedChannel = nil; - } - } - [pool unrefChannelWithConfiguration:_channelConfiguration]; -} - @end /** * A convenience value type for cached channel. */ -@interface GRPCChannelRecord : NSObject +@interface GRPCChannelRecord : NSObject /** Pointer to the raw channel. May be nil when the channel has been destroyed. */ @property GRPCChannel *channel; /** Channel proxy corresponding to this channel configuration. */ -@property GRPCPooledChannel *proxy; +@property GRPCPooledChannel *pooledChannel; /** Last time when a timed destroy is initiated on the channel. */ @property NSDate *timedDestroyDate; /** Reference count of the proxy to the channel. */ -@property NSUInteger refcount; +@property NSUInteger refCount; @end @implementation GRPCChannelRecord -- (id)copyWithZone:(NSZone *)zone { - GRPCChannelRecord *newRecord = [[GRPCChannelRecord allocWithZone:zone] init]; - newRecord.channel = _channel; - newRecord.proxy = _proxy; - newRecord.timedDestroyDate = _timedDestroyDate; - newRecord.refcount = _refcount; +@end - return newRecord; -} +@interface GRPCChannelPool () + +- (instancetype)initInstanceWithDestroyDelay:(NSTimeInterval)destroyDelay NS_DESIGNATED_INITIALIZER; @end @implementation GRPCChannelPool { NSMutableDictionary *_channelPool; dispatch_queue_t _dispatchQueue; + NSTimeInterval _destroyDelay; } + (instancetype)sharedInstance { dispatch_once(&gInitChannelPool, ^{ - gChannelPool = [[GRPCChannelPool alloc] init]; + gChannelPool = [[GRPCChannelPool alloc] initInstanceWithDestroyDelay:kDefaultChannelDestroyDelay]; NSAssert(gChannelPool != nil, @"Cannot initialize global channel pool."); }); return gChannelPool; } -- (instancetype)init { +- (instancetype)initInstanceWithDestroyDelay:(NSTimeInterval)destroyDelay { if ((self = [super init])) { _channelPool = [NSMutableDictionary dictionary]; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 @@ -206,7 +203,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; #endif _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); } - _destroyDelay = kDefaultChannelDestroyDelay; + _destroyDelay = destroyDelay; // Connectivity monitor is not required for CFStream char *enableCFStream = getenv(kCFStreamVarName); @@ -217,56 +214,56 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; return self; } +- (void)dealloc { + [GRPCConnectivityMonitor unregisterObserver:self]; +} + - (GRPCPooledChannel *)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions { NSAssert(host.length > 0, @"Host must not be empty."); NSAssert(callOptions != nil, @"callOptions must not be empty."); - if (host.length == 0) return nil; - if (callOptions == nil) return nil; + if (host.length == 0 || callOptions == nil) { + return nil; + } - GRPCPooledChannel *channelProxy = nil; + GRPCPooledChannel *pooledChannel = nil; GRPCChannelConfiguration *configuration = [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; @synchronized(self) { GRPCChannelRecord *record = _channelPool[configuration]; if (record == nil) { record = [[GRPCChannelRecord alloc] init]; - record.proxy = + record.pooledChannel = [[GRPCPooledChannel alloc] initWithChannelConfiguration:configuration channelPool:self]; - record.timedDestroyDate = nil; _channelPool[configuration] = record; - channelProxy = record.proxy; + pooledChannel = record.pooledChannel; } else { - channelProxy = record.proxy; + pooledChannel = record.pooledChannel; } } - return channelProxy; -} - -- (void)closeOpenConnections { - [self disconnectAllChannels]; + return pooledChannel; } - (GRPCChannel *)refChannelWithConfiguration:(GRPCChannelConfiguration *)configuration { GRPCChannel *ret = nil; @synchronized(self) { NSAssert(configuration != nil, @"configuration cannot be empty."); - if (configuration == nil) return nil; + if (configuration == nil) { + return nil; + } GRPCChannelRecord *record = _channelPool[configuration]; NSAssert(record != nil, @"No record corresponding to a proxy."); - if (record == nil) return nil; + if (record == nil) { + return nil; + } + record.refCount++; + record.timedDestroyDate = nil; if (record.channel == nil) { // Channel is already destroyed; record.channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration]; - record.timedDestroyDate = nil; - record.refcount = 1; - ret = record.channel; - } else { - ret = record.channel; - record.timedDestroyDate = nil; - record.refcount++; } + ret = record.channel; } return ret; } @@ -275,11 +272,13 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; @synchronized(self) { GRPCChannelRecord *record = _channelPool[configuration]; NSAssert(record != nil, @"No record corresponding to a proxy."); - if (record == nil) return; - NSAssert(record.refcount > 0, @"Inconsistent channel refcount."); - if (record.refcount > 0) { - record.refcount--; - if (record.refcount == 0) { + if (record == nil) { + return; + } + NSAssert(record.refCount > 0, @"Inconsistent channel refcount."); + if (record.refCount > 0) { + record.refCount--; + if (record.refCount == 0) { NSDate *now = [NSDate date]; record.timedDestroyDate = now; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_destroyDelay * NSEC_PER_SEC)), @@ -288,7 +287,6 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; if (now == record.timedDestroyDate) { // Destroy the raw channel and reset related records. record.timedDestroyDate = nil; - record.refcount = 0; record.channel = nil; } } @@ -306,8 +304,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; GRPCChannelRecord *_Nonnull obj, BOOL *_Nonnull stop) { obj.channel = nil; obj.timedDestroyDate = nil; - obj.refcount = 0; - [proxySet addObject:obj.proxy]; + [proxySet addObject:obj.pooledChannel]; }]; } // Disconnect proxies @@ -320,8 +317,12 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; [self disconnectAllChannels]; } -- (void)dealloc { - [GRPCConnectivityMonitor unregisterObserver:self]; +@end + +@implementation GRPCChannelPool (Test) + +- (instancetype)initTestPoolWithDestroyDelay:(NSTimeInterval)destroyDelay { + return [self initInstanceWithDestroyDelay:destroyDelay]; } @end diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 615dfc85569..5788d0a003f 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -317,7 +317,7 @@ } - (void)dealloc { - [_channel unrefUnmanagedCall:_call]; + [_channel destroyUnmanagedCall:_call]; _channel = nil; } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 2de2932072a..dff88b8591f 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -133,18 +133,18 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } - (void)cancel { - GRPCCall2 *call; + GRPCCall2 *copiedCall; @synchronized(self) { - call = _call; + copiedCall = _call; _call = nil; if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { dispatch_async(_handler.dispatchQueue, ^{ - id handler = nil; + id copiedHandler = nil; @synchronized(self) { - handler = self->_handler; + copiedHandler = self->_handler; self->_handler = nil; } - [handler closedWithTrailingMetadata:nil + [copiedHandler closedWithTrailingMetadata:nil error:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeCancelled userInfo:@{ @@ -152,9 +152,11 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing @"Canceled by app" }]]; }); + } else { + _handler = nil; } } - [call cancel]; + [copiedCall cancel]; } - (void)writeMessage:(GPBMessage *)message { @@ -182,11 +184,11 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing @synchronized(self) { if (initialMetadata != nil && [_handler respondsToSelector:@selector(initialMetadata:)]) { dispatch_async(_dispatchQueue, ^{ - id handler = nil; + id copiedHandler = nil; @synchronized(self) { - handler = self->_handler; + copiedHandler = self->_handler; } - [handler receivedInitialMetadata:initialMetadata]; + [copiedHandler receivedInitialMetadata:initialMetadata]; }); } } @@ -200,21 +202,21 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing @synchronized(self) { if (parsed && [_handler respondsToSelector:@selector(receivedProtoMessage:)]) { dispatch_async(_dispatchQueue, ^{ - id handler = nil; + id copiedHandler = nil; @synchronized(self) { - handler = self->_handler; + copiedHandler = self->_handler; } - [handler receivedProtoMessage:parsed]; + [copiedHandler receivedProtoMessage:parsed]; }); } else if (!parsed && [_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { dispatch_async(_dispatchQueue, ^{ - id handler = nil; + id copiedHandler = nil; @synchronized(self) { - handler = self->_handler; + copiedHandler = self->_handler; self->_handler = nil; } - [handler closedWithTrailingMetadata:nil + [copiedHandler closedWithTrailingMetadata:nil error:ErrorForBadProto(message, _responseClass, error)]; }); [_call cancel]; @@ -227,12 +229,12 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing @synchronized(self) { if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { dispatch_async(_dispatchQueue, ^{ - id handler = nil; + id copiedHandler = nil; @synchronized(self) { - handler = self->_handler; + copiedHandler = self->_handler; self->_handler = nil; } - [handler closedWithTrailingMetadata:trailingMetadata error:error]; + [copiedHandler closedWithTrailingMetadata:trailingMetadata error:error]; }); } _call = nil; diff --git a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m index 4424801c110..9461945560a 100644 --- a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m +++ b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m @@ -28,6 +28,8 @@ NSString *kDummyHost = @"dummy.host"; NSString *kDummyHost2 = @"dummy.host.2"; NSString *kDummyPath = @"/dummy/path"; +const NSTimeInterval kDestroyDelay = 1.0; + @interface ChannelPoolTest : XCTestCase @end @@ -39,7 +41,7 @@ NSString *kDummyPath = @"/dummy/path"; } - (void)testCreateChannelAndCall { - GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; + GRPCChannelPool *pool = [[GRPCChannelPool alloc] initTestPoolWithDestroyDelay:kDestroyDelay]; GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; GRPCPooledChannel *channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; @@ -49,12 +51,12 @@ NSString *kDummyPath = @"/dummy/path"; [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssert(call != NULL); XCTAssertNotNil(channel.wrappedChannel); - [channel unrefUnmanagedCall:call]; + [channel destroyUnmanagedCall:call]; XCTAssertNil(channel.wrappedChannel); } - (void)testCacheChannel { - GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; + GRPCChannelPool *pool = [[GRPCChannelPool alloc] initTestPoolWithDestroyDelay:kDestroyDelay]; GRPCCallOptions *options1 = [[GRPCCallOptions alloc] init]; GRPCCallOptions *options2 = [options1 copy]; GRPCMutableCallOptions *options3 = [options1 mutableCopy]; @@ -80,17 +82,14 @@ NSString *kDummyPath = @"/dummy/path"; XCTAssertNotEqual(channel1.wrappedChannel, channel3.wrappedChannel); XCTAssertNotEqual(channel1.wrappedChannel, channel4.wrappedChannel); XCTAssertNotEqual(channel3.wrappedChannel, channel4.wrappedChannel); - [channel1 unrefUnmanagedCall:call1]; - [channel2 unrefUnmanagedCall:call2]; - [channel3 unrefUnmanagedCall:call3]; - [channel4 unrefUnmanagedCall:call4]; + [channel1 destroyUnmanagedCall:call1]; + [channel2 destroyUnmanagedCall:call2]; + [channel3 destroyUnmanagedCall:call3]; + [channel4 destroyUnmanagedCall:call4]; } - (void)testTimedDestroyChannel { - const NSTimeInterval kDestroyDelay = 1.0; - - GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; - pool.destroyDelay = kDestroyDelay; + GRPCChannelPool *pool = [[GRPCChannelPool alloc] initTestPoolWithDestroyDelay:kDestroyDelay]; GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; GRPCPooledChannel *channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; @@ -99,25 +98,24 @@ NSString *kDummyPath = @"/dummy/path"; [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; GRPCChannel *wrappedChannel = channel.wrappedChannel; - [channel unrefUnmanagedCall:call]; + [channel destroyUnmanagedCall:call]; // Confirm channel is not destroyed at this time call = [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertEqual(wrappedChannel, channel.wrappedChannel); - [channel unrefUnmanagedCall:call]; + [channel destroyUnmanagedCall:call]; sleep(kDestroyDelay + 1); // Confirm channel is new at this time call = [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertNotEqual(wrappedChannel, channel.wrappedChannel); // Confirm the new channel can create call - call = [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssert(call != NULL); - [channel unrefUnmanagedCall:call]; + [channel destroyUnmanagedCall:call]; } - (void)testPoolDisconnection { - GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; + GRPCChannelPool *pool = [[GRPCChannelPool alloc] initTestPoolWithDestroyDelay:kDestroyDelay]; GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; GRPCPooledChannel *channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; @@ -141,12 +139,12 @@ NSString *kDummyPath = @"/dummy/path"; [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertNotNil(channel.wrappedChannel); XCTAssertNotEqual(channel.wrappedChannel, wrappedChannel); - [channel unrefUnmanagedCall:call]; - [channel unrefUnmanagedCall:call2]; + [channel destroyUnmanagedCall:call]; + [channel destroyUnmanagedCall:call2]; } - (void)testUnrefCallFromStaleChannel { - GRPCChannelPool *pool = [[GRPCChannelPool alloc] init]; + GRPCChannelPool *pool = [[GRPCChannelPool alloc] initTestPoolWithDestroyDelay:kDestroyDelay]; GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; GRPCPooledChannel *channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; @@ -163,12 +161,12 @@ NSString *kDummyPath = @"/dummy/path"; // destroy state XCTAssertNotNil(channel.wrappedChannel); GRPCChannel *wrappedChannel = channel.wrappedChannel; - [channel unrefUnmanagedCall:call]; + [channel destroyUnmanagedCall:call]; XCTAssertNotNil(channel.wrappedChannel); XCTAssertEqual(wrappedChannel, channel.wrappedChannel); // Test unref the call of the current channel will cause the channel going into timed destroy // state - [channel unrefUnmanagedCall:call2]; + [channel destroyUnmanagedCall:call2]; XCTAssertNil(channel.wrappedChannel); } diff --git a/src/objective-c/tests/ChannelTests/ChannelTests.m b/src/objective-c/tests/ChannelTests/ChannelTests.m index c07c8e69834..55474490926 100644 --- a/src/objective-c/tests/ChannelTests/ChannelTests.m +++ b/src/objective-c/tests/ChannelTests/ChannelTests.m @@ -35,7 +35,7 @@ completionQueue:(GRPCCompletionQueue *)queue callOptions:(GRPCCallOptions *)callOptions; -- (void)unrefUnmanagedCall:(grpc_call *)unmanagedCall; +- (void)destroyUnmanagedCall:(grpc_call *)unmanagedCall; @end @@ -66,7 +66,7 @@ return (grpc_call *)(++_grpcCallCounter); } -- (void)unrefUnmanagedCall:(grpc_call *)unmanagedCall { +- (void)destroyUnmanagedCall:(grpc_call *)unmanagedCall { if (_unrefExpectation) [_unrefExpectation fulfill]; } diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 834bf6d661a..2cfdd1a003b 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -554,13 +554,14 @@ static GRPCProtoMethod *kFullDuplexCallMethod; __weak XCTestExpectation *completion = [self expectationWithDescription:@"Timeout in a second."]; NSString *const kDummyAddress = [NSString stringWithFormat:@"8.8.8.8:1"]; - GRPCCall *call = [[GRPCCall alloc] initWithHost:kDummyAddress - path:@"/dummyPath" - requestsWriter:[GRXWriter writerWithValue:[NSData data]]]; + [GRPCCall useInsecureConnectionsForHost:kDummyAddress]; [GRPCCall setMinConnectTimeout:timeout * 1000 initialBackoff:backoff * 1000 maxBackoff:0 forHost:kDummyAddress]; + GRPCCall *call = [[GRPCCall alloc] initWithHost:kDummyAddress + path:@"/dummyPath" + requestsWriter:[GRXWriter writerWithValue:[NSData data]]]; NSDate *startTime = [NSDate date]; id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(id value) { XCTAssert(NO, @"Received message. Should not reach here"); From fdf4b8f2f76cf13f9d41c24775b78727de3c994b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 26 Nov 2018 17:42:56 -0800 Subject: [PATCH 205/375] clang-format --- src/objective-c/GRPCClient/GRPCCallOptions.h | 2 +- src/objective-c/GRPCClient/private/GRPCChannel.h | 3 ++- src/objective-c/GRPCClient/private/GRPCChannel.m | 8 ++++---- .../GRPCClient/private/GRPCChannelPool.h | 7 ++++--- .../GRPCClient/private/GRPCChannelPool.m | 8 +++++--- src/objective-c/ProtoRPC/ProtoRPC.m | 14 +++++++------- 6 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 48bb11aeeb0..158a4745d23 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -64,7 +64,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * This method is called when gRPC is about to start the call. When OAuth token is acquired, * \a handler is expected to be called with \a token being the new token to be used for this call. */ -- (void)getTokenWithHandler:(void (^ _Nullable)(NSString * _Nullable token))handler; +- (void)getTokenWithHandler:(void (^_Nullable)(NSString *_Nullable token))handler; @end @interface GRPCCallOptions : NSObject diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index 147015bed10..c01aeccf81f 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -51,7 +51,8 @@ NS_ASSUME_NONNULL_BEGIN /** Acquire the dictionary of channel args with current configurations. */ @property(copy, readonly) NSDictionary *channelArgs; -- (nullable instancetype)initWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithHost:(NSString *)host + callOptions:(GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 24cf670d1b5..9432e7ab397 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -226,7 +226,7 @@ if (_unmanagedChannel == NULL) return NULL; NSString *serverAuthority = - callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; + callOptions.transportType == GRPCTransportTypeCronet ? nil : callOptions.serverAuthority; NSTimeInterval timeout = callOptions.timeout; NSAssert(timeout >= 0, @"Invalid timeout"); if (timeout < 0) return NULL; @@ -236,9 +236,9 @@ } grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); gpr_timespec deadline_ms = - timeout == 0 ? gpr_inf_future(GPR_CLOCK_REALTIME) - : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); + timeout == 0 ? gpr_inf_future(GPR_CLOCK_REALTIME) + : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN)); call = grpc_channel_create_call(_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS, queue.unmanagedQueue, path_slice, serverAuthority ? &host_slice : NULL, deadline_ms, NULL); diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 26600ef3a96..7f8ee19fe59 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -41,14 +41,15 @@ NS_ASSUME_NONNULL_BEGIN - (nullable instancetype)init NS_UNAVAILABLE; -+ (nullable instancetype)new NS_UNAVAILABLE; ++ (nullable instancetype) new NS_UNAVAILABLE; /** * Initialize with an actual channel object \a channel and a reference to the channel pool. */ - (nullable instancetype)initWithChannelConfiguration: (GRPCChannelConfiguration *)channelConfiguration - channelPool:(GRPCChannelPool *)channelPool NS_DESIGNATED_INITIALIZER; + channelPool:(GRPCChannelPool *)channelPool + NS_DESIGNATED_INITIALIZER; /** * Create a grpc core call object (grpc_call) from this channel. If channel is disconnected, get a @@ -91,7 +92,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable instancetype)init NS_UNAVAILABLE; -+ (nullable instancetype)new NS_UNAVAILABLE; ++ (nullable instancetype) new NS_UNAVAILABLE; /** * Get the global channel pool. diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index f6615b58405..646f1e4b86e 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -74,8 +74,9 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } - (void)dealloc { - NSAssert([_unmanagedCalls count] == 0 && _wrappedChannel == nil, @"Pooled channel should only be" - "destroyed after the wrapped channel is destroyed"); + NSAssert([_unmanagedCalls count] == 0 && _wrappedChannel == nil, + @"Pooled channel should only be" + "destroyed after the wrapped channel is destroyed"); } - (grpc_call *)unmanagedCallWithPath:(NSString *)path @@ -183,7 +184,8 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; + (instancetype)sharedInstance { dispatch_once(&gInitChannelPool, ^{ - gChannelPool = [[GRPCChannelPool alloc] initInstanceWithDestroyDelay:kDefaultChannelDestroyDelay]; + gChannelPool = + [[GRPCChannelPool alloc] initInstanceWithDestroyDelay:kDefaultChannelDestroyDelay]; NSAssert(gChannelPool != nil, @"Cannot initialize global channel pool."); }); return gChannelPool; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index dff88b8591f..1db04894d5e 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -145,12 +145,12 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing self->_handler = nil; } [copiedHandler closedWithTrailingMetadata:nil - error:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeCancelled - userInfo:@{ - NSLocalizedDescriptionKey : - @"Canceled by app" - }]]; + error:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeCancelled + userInfo:@{ + NSLocalizedDescriptionKey : + @"Canceled by app" + }]]; }); } else { _handler = nil; @@ -217,7 +217,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing self->_handler = nil; } [copiedHandler closedWithTrailingMetadata:nil - error:ErrorForBadProto(message, _responseClass, error)]; + error:ErrorForBadProto(message, _responseClass, error)]; }); [_call cancel]; _call = nil; From fd69f74b2091ae66b609ec7592905d9b20dddf88 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 27 Nov 2018 17:48:55 -0800 Subject: [PATCH 206/375] use value64 --- src/objective-c/GRPCClient/private/ChannelArgsUtil.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m index 3135fcff028..c1c65c33841 100644 --- a/src/objective-c/GRPCClient/private/ChannelArgsUtil.m +++ b/src/objective-c/GRPCClient/private/ChannelArgsUtil.m @@ -78,7 +78,7 @@ grpc_channel_args *GRPCBuildChannelArgs(NSDictionary *dictionary) { int64_t value64 = [value longLongValue]; if (value64 <= INT_MAX || value64 >= INT_MIN) { arg->type = GRPC_ARG_INTEGER; - arg->value.integer = [value intValue]; + arg->value.integer = (int)value64; j++; } } else if (value != nil) { From a7c41346d8470e7eb5f10234daa08d09a48fa779 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 28 Nov 2018 11:22:33 -0800 Subject: [PATCH 207/375] Add one more cancel test --- src/objective-c/tests/InteropTests.m | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index a9f33aab6f1..2492718046f 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -655,6 +655,37 @@ BOOL isRemoteInteropTest(NSString *host) { [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } +- (void)testCancelAfterFirstRequestWithV2API { + XCTAssertNotNil([[self class] host]); + __weak XCTestExpectation *completionExpectation = + [self expectationWithDescription:@"Call completed."]; + + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.transportType = self.class.transportType; + options.PEMRootCertificates = self.class.PEMRootCertificates; + options.hostNameOverride = [[self class] hostNameOverride]; + + id request = + [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 requestedResponseSize:@31415]; + + __block GRPCStreamingProtoCall *call = [_service + fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] + initWithInitialMetadataCallback:nil + messageCallback:^(id message) { + XCTFail(@"Received unexpected response."); + } + closeCallback:^(NSDictionary *trailingMetadata, + NSError *error) { + XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); + [completionExpectation fulfill]; + }] + callOptions:options]; + + [call writeMessage:request]; + [call cancel]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + - (void)testRPCAfterClosingOpenConnections { XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = From 459da578db5ae9bd95f91be2888236c4870a7314 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 30 Nov 2018 13:43:56 -0800 Subject: [PATCH 208/375] Refactor channel pool --- src/objective-c/GRPCClient/GRPCCall.m | 15 +- .../GRPCClient/private/GRPCChannelPool.h | 35 ++- .../GRPCClient/private/GRPCChannelPool.m | 276 +++++++----------- .../GRPCClient/private/GRPCWrappedCall.h | 13 +- .../GRPCClient/private/GRPCWrappedCall.m | 117 ++++---- .../tests/ChannelTests/ChannelPoolTest.m | 146 ++------- .../tests/ChannelTests/ChannelTests.m | 152 +++++----- .../xcschemes/ChannelTests.xcscheme | 5 - 8 files changed, 306 insertions(+), 453 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index bf9441c27eb..dad8594a264 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -36,6 +36,8 @@ #import "private/NSDictionary+GRPC.h" #import "private/NSError+GRPC.h" #import "private/utilities.h" +#import "private/GRPCChannelPool.h" +#import "private/GRPCCompletionQueue.h" // At most 6 ops can be in an op batch for a client: SEND_INITIAL_METADATA, // SEND_MESSAGE, SEND_CLOSE_FROM_CLIENT, RECV_INITIAL_METADATA, RECV_MESSAGE, @@ -819,8 +821,11 @@ const char *kCFStreamVarName = "grpc_cfstream"; _responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable dispatchQueue:_responseQueue]; - GRPCWrappedCall *wrappedCall = - [[GRPCWrappedCall alloc] initWithHost:_host path:_path callOptions:_callOptions]; + GRPCPooledChannel *channel = [[GRPCChannelPool sharedInstance] channelWithHost:_host callOptions:_callOptions]; + GRPCWrappedCall *wrappedCall = [channel wrappedCallWithPath:_path + completionQueue:[GRPCCompletionQueue completionQueue] + callOptions:_callOptions]; + if (wrappedCall == nil) { [self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeUnavailable @@ -837,12 +842,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; [self sendHeaders]; [self invokeCall]; - - // Connectivity monitor is not required for CFStream - char *enableCFStream = getenv(kCFStreamVarName); - if (enableCFStream == nil || enableCFStream[0] != '1') { - [GRPCConnectivityMonitor registerObserver:self selector:@selector(connectivityChanged:)]; - } } - (void)startWithWriteable:(id)writeable { diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 7f8ee19fe59..338b6e440f3 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -32,10 +32,13 @@ NS_ASSUME_NONNULL_BEGIN @class GRPCChannelPool; @class GRPCCompletionQueue; @class GRPCChannelConfiguration; +@class GRPCWrappedCall; /** - * Channel proxy that can be retained and automatically reestablish connection when the channel is - * disconnected. + * A proxied channel object that can be retained and creates GRPCWrappedCall object from. If a + * raw channel is not present (i.e. no tcp connection to the server) when a GRPCWrappedCall object + * is requested, it issues a connection/reconnection. The behavior of this object is to mimic that + * of gRPC core's channel object. */ @interface GRPCPooledChannel : NSObject @@ -47,24 +50,21 @@ NS_ASSUME_NONNULL_BEGIN * Initialize with an actual channel object \a channel and a reference to the channel pool. */ - (nullable instancetype)initWithChannelConfiguration: - (GRPCChannelConfiguration *)channelConfiguration - channelPool:(GRPCChannelPool *)channelPool - NS_DESIGNATED_INITIALIZER; + (GRPCChannelConfiguration *)channelConfiguration; /** - * Create a grpc core call object (grpc_call) from this channel. If channel is disconnected, get a + * Create a GRPCWrappedCall object (grpc_call) from this channel. If channel is disconnected, get a * new channel object from the channel pool. */ -- (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path - completionQueue:(GRPCCompletionQueue *)queue - callOptions:(GRPCCallOptions *)callOptions; +- (nullable GRPCWrappedCall *)wrappedCallWithPath:(NSString *)path + completionQueue:(GRPCCompletionQueue *)queue + callOptions:(GRPCCallOptions *)callOptions; /** - * Return ownership and destroy the grpc_call object created by - * \a unmanagedCallWithPath:completionQueue:callOptions: and decrease channel refcount. If refcount - * of the channel becomes 0, return the channel object to channel pool. + * Notify the pooled channel that a wrapped call object is no longer referenced and will be + * dealloc'ed. */ -- (void)destroyUnmanagedCall:(grpc_call *)unmanagedCall; +- (void)notifyWrappedCallDealloc:(GRPCWrappedCall *)wrappedCall; /** * Force the channel to disconnect immediately. Subsequent calls to unmanagedCallWithPath: will @@ -77,6 +77,13 @@ NS_ASSUME_NONNULL_BEGIN /** Test-only interface for \a GRPCPooledChannel. */ @interface GRPCPooledChannel (Test) +/** + * Initialize a pooled channel with non-default destroy delay for testing purpose. + */ +- (nullable instancetype)initWithChannelConfiguration: +(GRPCChannelConfiguration *)channelConfiguration + destroyDelay:(NSTimeInterval)destroyDelay; + /** * Return the pointer to the raw channel wrapped. */ @@ -118,7 +125,7 @@ NS_ASSUME_NONNULL_BEGIN * Get an instance of pool isolated from the global shared pool with channels' destroy delay being * \a destroyDelay. */ -- (nullable instancetype)initTestPoolWithDestroyDelay:(NSTimeInterval)destroyDelay; +- (nullable instancetype)initTestPool; @end diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 646f1e4b86e..488766c0edc 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -28,6 +28,8 @@ #import "GRPCSecureChannelFactory.h" #import "utilities.h" #import "version.h" +#import "GRPCWrappedCall.h" +#import "GRPCCompletionQueue.h" #import #include @@ -40,103 +42,139 @@ static dispatch_once_t gInitChannelPool; /** When all calls of a channel are destroyed, destroy the channel after this much seconds. */ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; -@interface GRPCChannelPool () - -- (GRPCChannel *)refChannelWithConfiguration:(GRPCChannelConfiguration *)configuration; - -- (void)unrefChannelWithConfiguration:(GRPCChannelConfiguration *)configuration; - -@end - @implementation GRPCPooledChannel { - __weak GRPCChannelPool *_channelPool; GRPCChannelConfiguration *_channelConfiguration; - NSMutableSet *_unmanagedCalls; + NSTimeInterval _destroyDelay; + + NSHashTable *_wrappedCalls; GRPCChannel *_wrappedChannel; + NSDate *_lastTimedDestroy; + dispatch_queue_t _timerQueue; } -- (instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration - channelPool:(GRPCChannelPool *)channelPool { - NSAssert(channelConfiguration != nil, @"channelConfiguration cannot be empty."); - NSAssert(channelPool != nil, @"channelPool cannot be empty."); - if (channelPool == nil || channelConfiguration == nil) { - return nil; - } - - if ((self = [super init])) { - _channelPool = channelPool; - _channelConfiguration = channelConfiguration; - _unmanagedCalls = [NSMutableSet set]; - _wrappedChannel = nil; - } - - return self; +- (instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration { + return [self initWithChannelConfiguration:channelConfiguration destroyDelay:kDefaultChannelDestroyDelay]; } - (void)dealloc { - NSAssert([_unmanagedCalls count] == 0 && _wrappedChannel == nil, - @"Pooled channel should only be" - "destroyed after the wrapped channel is destroyed"); + if ([_wrappedCalls objectEnumerator].allObjects.count != 0) { + NSEnumerator *enumerator = [_wrappedCalls objectEnumerator]; + GRPCWrappedCall *wrappedCall; + while ((wrappedCall = [enumerator nextObject])) { + [wrappedCall channelDisconnected]; + }; + } } -- (grpc_call *)unmanagedCallWithPath:(NSString *)path - completionQueue:(GRPCCompletionQueue *)queue - callOptions:(GRPCCallOptions *)callOptions { +- (GRPCWrappedCall *)wrappedCallWithPath:(NSString *)path +completionQueue:(GRPCCompletionQueue *)queue +callOptions:(GRPCCallOptions *)callOptions { NSAssert(path.length > 0, @"path must not be empty."); NSAssert(queue != nil, @"completionQueue must not be empty."); NSAssert(callOptions, @"callOptions must not be empty."); if (path.length == 0 || queue == nil || callOptions == nil) return NULL; - grpc_call *call = NULL; + GRPCWrappedCall *call = nil; + @synchronized(self) { if (_wrappedChannel == nil) { - __strong GRPCChannelPool *strongPool = _channelPool; - if (strongPool) { - _wrappedChannel = [strongPool refChannelWithConfiguration:_channelConfiguration]; + _wrappedChannel = [[GRPCChannel alloc] initWithChannelConfiguration:_channelConfiguration]; + if (_wrappedChannel == nil) { + NSAssert(_wrappedChannel != nil, @"Unable to get a raw channel for proxy."); + return nil; } - NSAssert(_wrappedChannel != nil, @"Unable to get a raw channel for proxy."); } - call = - [_wrappedChannel unmanagedCallWithPath:path completionQueue:queue callOptions:callOptions]; - if (call != NULL) { - [_unmanagedCalls addObject:[NSValue valueWithPointer:call]]; + _lastTimedDestroy = nil; + + grpc_call *unmanagedCall = [_wrappedChannel unmanagedCallWithPath:path + completionQueue:[GRPCCompletionQueue completionQueue] + callOptions:callOptions]; + if (unmanagedCall == NULL) { + NSAssert(unmanagedCall != NULL, @"Unable to create grpc_call object"); + return nil; + } + + call = [[GRPCWrappedCall alloc] initWithUnmanagedCall:unmanagedCall pooledChannel:self]; + if (call == nil) { + NSAssert(call != nil, @"Unable to create GRPCWrappedCall object"); + return nil; } + + [_wrappedCalls addObject:call]; } return call; } -- (void)destroyUnmanagedCall:(grpc_call *)unmanagedCall { - if (unmanagedCall == NULL) { +- (void)notifyWrappedCallDealloc:(GRPCWrappedCall *)wrappedCall { + NSAssert(wrappedCall != nil, @"wrappedCall cannot be empty."); + if (wrappedCall == nil) { return; } - - grpc_call_unref(unmanagedCall); @synchronized(self) { - NSValue *removedCall = [NSValue valueWithPointer:unmanagedCall]; - [_unmanagedCalls removeObject:removedCall]; - if ([_unmanagedCalls count] == 0) { - _wrappedChannel = nil; - GRPCChannelPool *strongPool = _channelPool; - [strongPool unrefChannelWithConfiguration:_channelConfiguration]; + if ([_wrappedCalls objectEnumerator].allObjects.count == 0) { + NSDate *now = [NSDate date]; + _lastTimedDestroy = now; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)_destroyDelay * NSEC_PER_SEC), + _timerQueue, ^{ + @synchronized(self) { + if (self->_lastTimedDestroy == now) { + self->_wrappedChannel = nil; + self->_lastTimedDestroy = nil; + } + } + }); } } } - (void)disconnect { + NSHashTable *copiedWrappedCalls = nil; @synchronized(self) { if (_wrappedChannel != nil) { _wrappedChannel = nil; - [_unmanagedCalls removeAllObjects]; - GRPCChannelPool *strongPool = _channelPool; - [strongPool unrefChannelWithConfiguration:_channelConfiguration]; + copiedWrappedCalls = [_wrappedCalls copy]; + [_wrappedCalls removeAllObjects]; } } + NSEnumerator *enumerator = [copiedWrappedCalls objectEnumerator]; + GRPCWrappedCall *wrappedCall; + while ((wrappedCall = [enumerator nextObject])) { + [wrappedCall channelDisconnected]; + } } @end @implementation GRPCPooledChannel (Test) +- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration + destroyDelay:(NSTimeInterval)destroyDelay { + NSAssert(channelConfiguration != nil, @"channelConfiguration cannot be empty."); + if (channelConfiguration == nil) { + return nil; + } + + if ((self = [super init])) { + _channelConfiguration = channelConfiguration; + _destroyDelay = destroyDelay; + _wrappedCalls = [[NSHashTable alloc] initWithOptions:NSHashTableWeakMemory capacity:1]; + _wrappedChannel = nil; + _lastTimedDestroy = nil; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + if (@available(iOS 8.0, macOS 10.10, *)) { + _timerQueue = dispatch_queue_create(NULL, + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); + } else { +#else + { +#endif + _timerQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + } + } + + return self; +} + - (GRPCChannel *)wrappedChannel { GRPCChannel *channel = nil; @synchronized(self) { @@ -147,65 +185,28 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; @end -/** - * A convenience value type for cached channel. - */ -@interface GRPCChannelRecord : NSObject - -/** Pointer to the raw channel. May be nil when the channel has been destroyed. */ -@property GRPCChannel *channel; - -/** Channel proxy corresponding to this channel configuration. */ -@property GRPCPooledChannel *pooledChannel; - -/** Last time when a timed destroy is initiated on the channel. */ -@property NSDate *timedDestroyDate; - -/** Reference count of the proxy to the channel. */ -@property NSUInteger refCount; - -@end - -@implementation GRPCChannelRecord - -@end - @interface GRPCChannelPool () -- (instancetype)initInstanceWithDestroyDelay:(NSTimeInterval)destroyDelay NS_DESIGNATED_INITIALIZER; +- (instancetype)initInstance NS_DESIGNATED_INITIALIZER; @end @implementation GRPCChannelPool { - NSMutableDictionary *_channelPool; - dispatch_queue_t _dispatchQueue; - NSTimeInterval _destroyDelay; + NSMutableDictionary *_channelPool; } + (instancetype)sharedInstance { dispatch_once(&gInitChannelPool, ^{ gChannelPool = - [[GRPCChannelPool alloc] initInstanceWithDestroyDelay:kDefaultChannelDestroyDelay]; + [[GRPCChannelPool alloc] initInstance]; NSAssert(gChannelPool != nil, @"Cannot initialize global channel pool."); }); return gChannelPool; } -- (instancetype)initInstanceWithDestroyDelay:(NSTimeInterval)destroyDelay { +- (instancetype)initInstance { if ((self = [super init])) { _channelPool = [NSMutableDictionary dictionary]; -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 - if (@available(iOS 8.0, macOS 10.10, *)) { - _dispatchQueue = dispatch_queue_create( - NULL, - dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); - } else { -#else - { -#endif - _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); - } - _destroyDelay = destroyDelay; // Connectivity monitor is not required for CFStream char *enableCFStream = getenv(kCFStreamVarName); @@ -231,86 +232,23 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; GRPCChannelConfiguration *configuration = [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; @synchronized(self) { - GRPCChannelRecord *record = _channelPool[configuration]; - if (record == nil) { - record = [[GRPCChannelRecord alloc] init]; - record.pooledChannel = - [[GRPCPooledChannel alloc] initWithChannelConfiguration:configuration channelPool:self]; - _channelPool[configuration] = record; - pooledChannel = record.pooledChannel; - } else { - pooledChannel = record.pooledChannel; + pooledChannel = _channelPool[configuration]; + if (pooledChannel == nil) { + pooledChannel = [[GRPCPooledChannel alloc] initWithChannelConfiguration:configuration]; + _channelPool[configuration] = pooledChannel; } } return pooledChannel; } -- (GRPCChannel *)refChannelWithConfiguration:(GRPCChannelConfiguration *)configuration { - GRPCChannel *ret = nil; - @synchronized(self) { - NSAssert(configuration != nil, @"configuration cannot be empty."); - if (configuration == nil) { - return nil; - } - - GRPCChannelRecord *record = _channelPool[configuration]; - NSAssert(record != nil, @"No record corresponding to a proxy."); - if (record == nil) { - return nil; - } - - record.refCount++; - record.timedDestroyDate = nil; - if (record.channel == nil) { - // Channel is already destroyed; - record.channel = [[GRPCChannel alloc] initWithChannelConfiguration:configuration]; - } - ret = record.channel; - } - return ret; -} - -- (void)unrefChannelWithConfiguration:(GRPCChannelConfiguration *)configuration { - @synchronized(self) { - GRPCChannelRecord *record = _channelPool[configuration]; - NSAssert(record != nil, @"No record corresponding to a proxy."); - if (record == nil) { - return; - } - NSAssert(record.refCount > 0, @"Inconsistent channel refcount."); - if (record.refCount > 0) { - record.refCount--; - if (record.refCount == 0) { - NSDate *now = [NSDate date]; - record.timedDestroyDate = now; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_destroyDelay * NSEC_PER_SEC)), - _dispatchQueue, ^{ - @synchronized(self) { - if (now == record.timedDestroyDate) { - // Destroy the raw channel and reset related records. - record.timedDestroyDate = nil; - record.channel = nil; - } - } - }); - } - } - } -} - - (void)disconnectAllChannels { - NSMutableSet *proxySet = [NSMutableSet set]; + NSDictionary *copiedPooledChannels; @synchronized(self) { - [_channelPool - enumerateKeysAndObjectsUsingBlock:^(GRPCChannelConfiguration *_Nonnull key, - GRPCChannelRecord *_Nonnull obj, BOOL *_Nonnull stop) { - obj.channel = nil; - obj.timedDestroyDate = nil; - [proxySet addObject:obj.pooledChannel]; - }]; + copiedPooledChannels = [NSDictionary dictionaryWithDictionary:_channelPool]; } - // Disconnect proxies - [proxySet enumerateObjectsUsingBlock:^(GRPCPooledChannel *_Nonnull obj, BOOL *_Nonnull stop) { + + // Disconnect pooled channels. + [copiedPooledChannels enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { [obj disconnect]; }]; } @@ -323,8 +261,8 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; @implementation GRPCChannelPool (Test) -- (instancetype)initTestPoolWithDestroyDelay:(NSTimeInterval)destroyDelay { - return [self initInstanceWithDestroyDelay:destroyDelay]; +- (instancetype)initTestPool { + return [self initInstance]; } @end diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h index 19aa5367c77..0432190528f 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h @@ -71,11 +71,16 @@ #pragma mark GRPCWrappedCall +@class GRPCPooledChannel; + @interface GRPCWrappedCall : NSObject -- (instancetype)initWithHost:(NSString *)host - path:(NSString *)path - callOptions:(GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; + ++ (instancetype)new NS_UNAVAILABLE; + +- (instancetype)initWithUnmanagedCall:(grpc_call *)unmanagedCall + pooledChannel:(GRPCPooledChannel *)pooledChannel NS_DESIGNATED_INITIALIZER; - (void)startBatchWithOperations:(NSArray *)ops errorHandler:(void (^)(void))errorHandler; @@ -83,4 +88,6 @@ - (void)cancel; +- (void)channelDisconnected; + @end diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 5788d0a003f..7e2d9d3c6d3 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -237,37 +237,21 @@ #pragma mark GRPCWrappedCall @implementation GRPCWrappedCall { - GRPCCompletionQueue *_queue; - GRPCPooledChannel *_channel; + __weak GRPCPooledChannel *_channel; grpc_call *_call; } -- (instancetype)init { - return [self initWithHost:nil path:nil callOptions:[[GRPCCallOptions alloc] init]]; -} - -- (instancetype)initWithHost:(NSString *)host - path:(NSString *)path - callOptions:(GRPCCallOptions *)callOptions { - NSAssert(host.length != 0 && path.length != 0, @"path and host cannot be nil."); +- (instancetype)initWithUnmanagedCall:(grpc_call *)unmanagedCall + pooledChannel:(GRPCPooledChannel *)pooledChannel { + NSAssert(unmanagedCall != NULL, @"unmanagedCall cannot be empty."); + NSAssert(pooledChannel != nil, @"pooledChannel cannot be empty."); + if (unmanagedCall == NULL || pooledChannel == nil) { + return 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. - _queue = [GRPCCompletionQueue completionQueue]; - _channel = [[GRPCChannelPool sharedInstance] channelWithHost:host callOptions:callOptions]; - if (_channel == nil) { - NSAssert(_channel != nil, @"Failed to get a channel for the host."); - NSLog(@"Failed to get a channel for the host."); - return nil; - } - _call = [_channel unmanagedCallWithPath:path completionQueue:_queue callOptions:callOptions]; - if (_call == nil) { - NSAssert(_channel != nil, @"Failed to get a channel for the host."); - NSLog(@"Failed to create a call."); - return nil; - } + _call = unmanagedCall; + _channel = pooledChannel; } return self; } @@ -283,42 +267,67 @@ [GRPCOpBatchLog addOpBatchToLog:operations]; #endif - 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); - gpr_free(ops_array); - - if (error != GRPC_CALL_OK) { - [NSException + @synchronized (self) { + if (_call != NULL) { + 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; + 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]; + } + } } } - (void)cancel { - grpc_call_cancel(_call, NULL); + @synchronized (self) { + if (_call != NULL) { + grpc_call_cancel(_call, NULL); + } + } +} + +- (void)channelDisconnected { + @synchronized (self) { + if (_call != NULL) { + grpc_call_unref(_call); + _call = NULL; + } + } } - (void)dealloc { - [_channel destroyUnmanagedCall:_call]; - _channel = nil; + @synchronized (self) { + if (_call != NULL) { + grpc_call_unref(_call); + _call = NULL; + } + } + __strong GRPCPooledChannel *channel = _channel; + if (channel != nil) { + [channel notifyWrappedCallDealloc:self]; + } } @end diff --git a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m index 9461945560a..dc42d7c341d 100644 --- a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m +++ b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m @@ -24,11 +24,9 @@ #define TEST_TIMEOUT 32 -NSString *kDummyHost = @"dummy.host"; -NSString *kDummyHost2 = @"dummy.host.2"; -NSString *kDummyPath = @"/dummy/path"; - -const NSTimeInterval kDestroyDelay = 1.0; +static NSString *kDummyHost = @"dummy.host"; +static NSString *kDummyHost2 = @"dummy.host.2"; +static NSString *kDummyPath = @"/dummy/path"; @interface ChannelPoolTest : XCTestCase @@ -40,134 +38,26 @@ const NSTimeInterval kDestroyDelay = 1.0; grpc_init(); } -- (void)testCreateChannelAndCall { - GRPCChannelPool *pool = [[GRPCChannelPool alloc] initTestPoolWithDestroyDelay:kDestroyDelay]; - GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCPooledChannel *channel = - (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; - XCTAssertNil(channel.wrappedChannel); - GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; - grpc_call *call = - [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; - XCTAssert(call != NULL); - XCTAssertNotNil(channel.wrappedChannel); - [channel destroyUnmanagedCall:call]; - XCTAssertNil(channel.wrappedChannel); -} - -- (void)testCacheChannel { - GRPCChannelPool *pool = [[GRPCChannelPool alloc] initTestPoolWithDestroyDelay:kDestroyDelay]; +- (void)testCreateAndCacheChannel { + GRPCChannelPool *pool = [[GRPCChannelPool alloc] initTestPool]; GRPCCallOptions *options1 = [[GRPCCallOptions alloc] init]; GRPCCallOptions *options2 = [options1 copy]; GRPCMutableCallOptions *options3 = [options1 mutableCopy]; options3.transportType = GRPCTransportTypeInsecure; - GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; - GRPCPooledChannel *channel1 = - (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options1]; - grpc_call *call1 = - [channel1 unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options1]; - GRPCPooledChannel *channel2 = - (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options2]; - grpc_call *call2 = - [channel2 unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options2]; - GRPCPooledChannel *channel3 = - (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options3]; - grpc_call *call3 = - [channel3 unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options3]; - GRPCPooledChannel *channel4 = - (GRPCPooledChannel *)[pool channelWithHost:kDummyHost2 callOptions:options1]; - grpc_call *call4 = - [channel4 unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options1]; - XCTAssertEqual(channel1.wrappedChannel, channel2.wrappedChannel); - XCTAssertNotEqual(channel1.wrappedChannel, channel3.wrappedChannel); - XCTAssertNotEqual(channel1.wrappedChannel, channel4.wrappedChannel); - XCTAssertNotEqual(channel3.wrappedChannel, channel4.wrappedChannel); - [channel1 destroyUnmanagedCall:call1]; - [channel2 destroyUnmanagedCall:call2]; - [channel3 destroyUnmanagedCall:call3]; - [channel4 destroyUnmanagedCall:call4]; -} - -- (void)testTimedDestroyChannel { - GRPCChannelPool *pool = [[GRPCChannelPool alloc] initTestPoolWithDestroyDelay:kDestroyDelay]; - GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCPooledChannel *channel = - (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; - GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; - grpc_call *call = - [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; - GRPCChannel *wrappedChannel = channel.wrappedChannel; - - [channel destroyUnmanagedCall:call]; - // Confirm channel is not destroyed at this time - call = [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; - XCTAssertEqual(wrappedChannel, channel.wrappedChannel); - - [channel destroyUnmanagedCall:call]; - sleep(kDestroyDelay + 1); - // Confirm channel is new at this time - call = [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; - XCTAssertNotEqual(wrappedChannel, channel.wrappedChannel); - - // Confirm the new channel can create call - XCTAssert(call != NULL); - [channel destroyUnmanagedCall:call]; -} - -- (void)testPoolDisconnection { - GRPCChannelPool *pool = [[GRPCChannelPool alloc] initTestPoolWithDestroyDelay:kDestroyDelay]; - GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCPooledChannel *channel = - (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; - GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; - grpc_call *call = - [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; - XCTAssertNotNil(channel.wrappedChannel); - GRPCChannel *wrappedChannel = channel.wrappedChannel; - - // Test a new channel is created by requesting a channel from pool - [pool disconnectAllChannels]; - channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; - call = [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; - XCTAssertNotNil(channel.wrappedChannel); - XCTAssertNotEqual(wrappedChannel, channel.wrappedChannel); - wrappedChannel = channel.wrappedChannel; - - // Test a new channel is created by requesting a new call from the previous proxy - [pool disconnectAllChannels]; - grpc_call *call2 = - [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; - XCTAssertNotNil(channel.wrappedChannel); - XCTAssertNotEqual(channel.wrappedChannel, wrappedChannel); - [channel destroyUnmanagedCall:call]; - [channel destroyUnmanagedCall:call2]; -} - -- (void)testUnrefCallFromStaleChannel { - GRPCChannelPool *pool = [[GRPCChannelPool alloc] initTestPoolWithDestroyDelay:kDestroyDelay]; - GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCPooledChannel *channel = - (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; - GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; - grpc_call *call = - [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; - - [pool disconnectAllChannels]; - channel = (GRPCPooledChannel *)[pool channelWithHost:kDummyHost callOptions:options]; - grpc_call *call2 = - [channel unmanagedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; - // Test unref the call of a stale channel will not cause the current channel going into timed - // destroy state - XCTAssertNotNil(channel.wrappedChannel); - GRPCChannel *wrappedChannel = channel.wrappedChannel; - [channel destroyUnmanagedCall:call]; - XCTAssertNotNil(channel.wrappedChannel); - XCTAssertEqual(wrappedChannel, channel.wrappedChannel); - // Test unref the call of the current channel will cause the channel going into timed destroy - // state - [channel destroyUnmanagedCall:call2]; - XCTAssertNil(channel.wrappedChannel); + GRPCPooledChannel *channel1 = [pool channelWithHost:kDummyHost callOptions:options1]; + GRPCPooledChannel *channel2 = [pool channelWithHost:kDummyHost callOptions:options2]; + GRPCPooledChannel *channel3 = [pool channelWithHost:kDummyHost callOptions:options3]; + GRPCPooledChannel *channel4 = [pool channelWithHost:kDummyHost2 callOptions:options1]; + + XCTAssertNotNil(channel1); + XCTAssertNotNil(channel2); + XCTAssertNotNil(channel3); + XCTAssertNotNil(channel4); + XCTAssertEqual(channel1, channel2); + XCTAssertNotEqual(channel1, channel3); + XCTAssertNotEqual(channel1, channel4); + XCTAssertNotEqual(channel3, channel4); } @end diff --git a/src/objective-c/tests/ChannelTests/ChannelTests.m b/src/objective-c/tests/ChannelTests/ChannelTests.m index 55474490926..ee7f8b6fddb 100644 --- a/src/objective-c/tests/ChannelTests/ChannelTests.m +++ b/src/objective-c/tests/ChannelTests/ChannelTests.m @@ -22,91 +22,99 @@ #import "../../GRPCClient/private/GRPCChannel.h" #import "../../GRPCClient/private/GRPCChannelPool.h" #import "../../GRPCClient/private/GRPCCompletionQueue.h" +#import "../../GRPCClient/private/GRPCWrappedCall.h" -/* -#define TEST_TIMEOUT 8 - -@interface GRPCChannelFake : NSObject - -- (instancetype)initWithCreateExpectation:(XCTestExpectation *)createExpectation - unrefExpectation:(XCTestExpectation *)unrefExpectation; +static NSString *kDummyHost = @"dummy.host"; +static NSString *kDummyPath = @"/dummy/path"; -- (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path - completionQueue:(GRPCCompletionQueue *)queue - callOptions:(GRPCCallOptions *)callOptions; - -- (void)destroyUnmanagedCall:(grpc_call *)unmanagedCall; +@interface ChannelTests : XCTestCase @end -@implementation GRPCChannelFake { - __weak XCTestExpectation *_createExpectation; - __weak XCTestExpectation *_unrefExpectation; - long _grpcCallCounter; -} - -- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration -*)channelConfiguration { return nil; -} - -- (instancetype)initWithCreateExpectation:(XCTestExpectation *)createExpectation - unrefExpectation:(XCTestExpectation *)unrefExpectation { - if ((self = [super init])) { - _createExpectation = createExpectation; - _unrefExpectation = unrefExpectation; - _grpcCallCounter = 0; - } - return self; -} +@implementation ChannelTests -- (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path - completionQueue:(GRPCCompletionQueue *)queue - callOptions:(GRPCCallOptions *)callOptions { - if (_createExpectation) [_createExpectation fulfill]; - return (grpc_call *)(++_grpcCallCounter); ++ (void)setUp { + grpc_init(); } -- (void)destroyUnmanagedCall:(grpc_call *)unmanagedCall { - if (_unrefExpectation) [_unrefExpectation fulfill]; +- (void)testPooledChannelCreatingChannel { + GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; + GRPCChannelConfiguration *config = [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost + callOptions:options]; + GRPCPooledChannel *channel = [[GRPCPooledChannel alloc] initWithChannelConfiguration:config]; + GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; + GRPCWrappedCall *wrappedCall = [channel wrappedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + XCTAssertNotNil(channel.wrappedChannel); + (void)wrappedCall; } -@end - -@interface GRPCChannelPoolFake : NSObject - -- (instancetype)initWithDelayedDestroyExpectation:(XCTestExpectation *)delayedDestroyExpectation; - -- (GRPCChannel *)rawChannelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; - -- (void)delayedDestroyChannel; - -@end - -@implementation GRPCChannelPoolFake { - __weak XCTestExpectation *_delayedDestroyExpectation; -} - -- (instancetype)initWithDelayedDestroyExpectation:(XCTestExpectation *)delayedDestroyExpectation { - if ((self = [super init])) { - _delayedDestroyExpectation = delayedDestroyExpectation; +- (void)testTimedDestroyChannel { + const NSTimeInterval kDestroyDelay = 1.0; + GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; + GRPCChannelConfiguration *config = [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost + callOptions:options]; + GRPCPooledChannel *channel = [[GRPCPooledChannel alloc] initWithChannelConfiguration:config + destroyDelay:kDestroyDelay]; + GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; + GRPCWrappedCall *wrappedCall; + GRPCChannel *wrappedChannel; + @autoreleasepool { + wrappedCall = [channel wrappedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + XCTAssertNotNil(channel.wrappedChannel); + + // Unref and ref channel immediately; expect using the same raw channel. + wrappedChannel = channel.wrappedChannel; + + wrappedCall = nil; + wrappedCall = [channel wrappedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + XCTAssertEqual(channel.wrappedChannel, wrappedChannel); + + // Unref and ref channel after destroy delay; expect a new raw channel. + wrappedCall = nil; } - return self; -} - -- (void)delayedDestroyChannel { - if (_delayedDestroyExpectation) [_delayedDestroyExpectation fulfill]; + sleep(kDestroyDelay + 1); + XCTAssertNil(channel.wrappedChannel); + wrappedCall = [channel wrappedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + XCTAssertNotEqual(channel.wrappedChannel, wrappedChannel); } -@end */ - -@interface ChannelTests : XCTestCase - -@end - -@implementation ChannelTests - -+ (void)setUp { - grpc_init(); +- (void)testDisconnect { + const NSTimeInterval kDestroyDelay = 1.0; + GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; + GRPCChannelConfiguration *config = [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost + callOptions:options]; + GRPCPooledChannel *channel = [[GRPCPooledChannel alloc] initWithChannelConfiguration:config + destroyDelay:kDestroyDelay]; + GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; + GRPCWrappedCall *wrappedCall = [channel wrappedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + XCTAssertNotNil(channel.wrappedChannel); + + // Disconnect; expect wrapped channel to be dropped + [channel disconnect]; + XCTAssertNil(channel.wrappedChannel); + + // Create a new call and unref the old call; confirm that destroy of the old call does not make + // the channel disconnect, even after the destroy delay. + GRPCWrappedCall *wrappedCall2 = [channel wrappedCallWithPath:kDummyPath + completionQueue:cq + callOptions:options]; + XCTAssertNotNil(channel.wrappedChannel); + GRPCChannel *wrappedChannel = channel.wrappedChannel; + wrappedCall = nil; + sleep(kDestroyDelay + 1); + XCTAssertNotNil(channel.wrappedChannel); + XCTAssertEqual(wrappedChannel, channel.wrappedChannel); + (void)wrappedCall2; } @end diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/ChannelTests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/ChannelTests.xcscheme index 8c8623d7b21..acae965bed0 100644 --- a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/ChannelTests.xcscheme +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/ChannelTests.xcscheme @@ -37,11 +37,6 @@ BlueprintName = "ChannelTests" ReferencedContainer = "container:Tests.xcodeproj"> - - - - From dfec57a9a9ebfbe92709498074eb184527ef599e Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 5 Dec 2018 22:52:12 -0800 Subject: [PATCH 209/375] Channel pool polishments --- .../GRPCClient/private/GRPCChannelPool.h | 5 ++- .../GRPCClient/private/GRPCChannelPool.m | 41 ++++++++++--------- .../GRPCClient/private/GRPCWrappedCall.m | 10 ++--- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 338b6e440f3..7c6f2b3bbfa 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -67,8 +67,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)notifyWrappedCallDealloc:(GRPCWrappedCall *)wrappedCall; /** - * Force the channel to disconnect immediately. Subsequent calls to unmanagedCallWithPath: will - * attempt to reconnect to the remote channel. + * Force the channel to disconnect immediately. GRPCWrappedCall objects previously created with + * \a wrappedCallWithPath are failed if not already finished. Subsequent calls to + * unmanagedCallWithPath: will attempt to reconnect to the remote channel. */ - (void)disconnect; diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 488766c0edc..391022efd19 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -57,7 +57,8 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } - (void)dealloc { - if ([_wrappedCalls objectEnumerator].allObjects.count != 0) { + // Disconnect GRPCWrappedCall objects created but not yet removed + if (_wrappedCalls.allObjects.count != 0) { NSEnumerator *enumerator = [_wrappedCalls objectEnumerator]; GRPCWrappedCall *wrappedCall; while ((wrappedCall = [enumerator nextObject])) { @@ -111,13 +112,17 @@ callOptions:(GRPCCallOptions *)callOptions { return; } @synchronized(self) { - if ([_wrappedCalls objectEnumerator].allObjects.count == 0) { + // Detect if all objects weakly referenced in _wrappedCalls are (implicitly) removed. In such + // case the channel is no longer referenced by a grpc_call object and can be destroyed after + // a certain delay. + if (_wrappedCalls.allObjects.count == 0) { NSDate *now = [NSDate date]; + NSAssert(now != nil, @"Unable to create NSDate object 'now'."); _lastTimedDestroy = now; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)_destroyDelay * NSEC_PER_SEC), _timerQueue, ^{ @synchronized(self) { - if (self->_lastTimedDestroy == now) { + if (now != nil && self->_lastTimedDestroy == now) { self->_wrappedChannel = nil; self->_lastTimedDestroy = nil; } @@ -128,17 +133,15 @@ callOptions:(GRPCCallOptions *)callOptions { } - (void)disconnect { - NSHashTable *copiedWrappedCalls = nil; + NSArray *copiedWrappedCalls = nil; @synchronized(self) { if (_wrappedChannel != nil) { _wrappedChannel = nil; - copiedWrappedCalls = [_wrappedCalls copy]; + copiedWrappedCalls = _wrappedCalls.allObjects; [_wrappedCalls removeAllObjects]; } } - NSEnumerator *enumerator = [copiedWrappedCalls objectEnumerator]; - GRPCWrappedCall *wrappedCall; - while ((wrappedCall = [enumerator nextObject])) { + for (GRPCWrappedCall *wrappedCall in copiedWrappedCalls) { [wrappedCall channelDisconnected]; } } @@ -155,9 +158,9 @@ callOptions:(GRPCCallOptions *)callOptions { } if ((self = [super init])) { - _channelConfiguration = channelConfiguration; + _channelConfiguration = [channelConfiguration copy]; _destroyDelay = destroyDelay; - _wrappedCalls = [[NSHashTable alloc] initWithOptions:NSHashTableWeakMemory capacity:1]; + _wrappedCalls = [NSHashTable weakObjectsHashTable]; _wrappedChannel = nil; _lastTimedDestroy = nil; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 @@ -187,7 +190,7 @@ callOptions:(GRPCCallOptions *)callOptions { @interface GRPCChannelPool () -- (instancetype)initInstance NS_DESIGNATED_INITIALIZER; +- (instancetype)initPrivate NS_DESIGNATED_INITIALIZER; @end @@ -198,13 +201,13 @@ callOptions:(GRPCCallOptions *)callOptions { + (instancetype)sharedInstance { dispatch_once(&gInitChannelPool, ^{ gChannelPool = - [[GRPCChannelPool alloc] initInstance]; + [[GRPCChannelPool alloc] initPrivate]; NSAssert(gChannelPool != nil, @"Cannot initialize global channel pool."); }); return gChannelPool; } -- (instancetype)initInstance { +- (instancetype)initPrivate { if ((self = [super init])) { _channelPool = [NSMutableDictionary dictionary]; @@ -242,15 +245,15 @@ callOptions:(GRPCCallOptions *)callOptions { } - (void)disconnectAllChannels { - NSDictionary *copiedPooledChannels; + NSArray *copiedPooledChannels; @synchronized(self) { - copiedPooledChannels = [NSDictionary dictionaryWithDictionary:_channelPool]; + copiedPooledChannels = _channelPool.allValues; } // Disconnect pooled channels. - [copiedPooledChannels enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { - [obj disconnect]; - }]; + for (GRPCPooledChannel *pooledChannel in copiedPooledChannels) { + [pooledChannel disconnect]; + } } - (void)connectivityChange:(NSNotification *)note { @@ -262,7 +265,7 @@ callOptions:(GRPCCallOptions *)callOptions { @implementation GRPCChannelPool (Test) - (instancetype)initTestPool { - return [self initInstance]; + return [self initPrivate]; } @end diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 7e2d9d3c6d3..727c9e0a88e 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -237,7 +237,7 @@ #pragma mark GRPCWrappedCall @implementation GRPCWrappedCall { - __weak GRPCPooledChannel *_channel; + GRPCPooledChannel *_pooledChannel; grpc_call *_call; } @@ -251,7 +251,7 @@ if ((self = [super init])) { _call = unmanagedCall; - _channel = pooledChannel; + _pooledChannel = pooledChannel; } return self; } @@ -324,10 +324,8 @@ _call = NULL; } } - __strong GRPCPooledChannel *channel = _channel; - if (channel != nil) { - [channel notifyWrappedCallDealloc:self]; - } + __strong GRPCPooledChannel *channel = _pooledChannel; + [channel notifyWrappedCallDealloc:self]; } @end From 0a3a99d84e2a12a68568ee45cf4496a2d9ef5bf7 Mon Sep 17 00:00:00 2001 From: Srini Polavarapu Date: Thu, 6 Dec 2018 09:33:53 -0800 Subject: [PATCH 210/375] Bump version to v1.17.1-pre1 --- BUILD | 2 +- build.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILD b/BUILD index eeb1a2fa620..fb87e824bec 100644 --- a/BUILD +++ b/BUILD @@ -68,7 +68,7 @@ g_stands_for = "gizmo" core_version = "7.0.0" -version = "1.17.0" +version = "1.17.1-pre1" GPR_PUBLIC_HDRS = [ "include/grpc/support/alloc.h", diff --git a/build.yaml b/build.yaml index 62e07f64e42..df1fd85e050 100644 --- a/build.yaml +++ b/build.yaml @@ -14,7 +14,7 @@ settings: '#10': See the expand_version.py for all the quirks here core_version: 7.0.0 g_stands_for: gizmo - version: 1.17.0 + version: 1.17.1-pre1 filegroups: - name: alts_proto headers: From 9eaebf116d0651b314e186c454b26565347e5ede Mon Sep 17 00:00:00 2001 From: Srini Polavarapu Date: Thu, 6 Dec 2018 09:38:39 -0800 Subject: [PATCH 211/375] Regenerate projects --- CMakeLists.txt | 2 +- Makefile | 4 ++-- gRPC-C++.podspec | 6 +++--- gRPC-Core.podspec | 2 +- gRPC-ProtoRPC.podspec | 2 +- gRPC-RxLibrary.podspec | 2 +- gRPC.podspec | 2 +- package.xml | 8 ++++---- src/cpp/common/version_cc.cc | 2 +- src/csharp/Grpc.Core/Version.csproj.include | 2 +- src/csharp/Grpc.Core/VersionInfo.cs | 4 ++-- src/csharp/build_packages_dotnetcli.bat | 2 +- src/csharp/build_unitypackage.bat | 2 +- src/objective-c/!ProtoCompiler-gRPCPlugin.podspec | 2 +- src/objective-c/GRPCClient/private/version.h | 2 +- src/objective-c/tests/version.h | 2 +- src/php/composer.json | 2 +- src/php/ext/grpc/version.h | 2 +- src/python/grpcio/grpc/_grpcio_metadata.py | 2 +- src/python/grpcio/grpc_version.py | 2 +- src/python/grpcio_health_checking/grpc_version.py | 2 +- src/python/grpcio_reflection/grpc_version.py | 2 +- src/python/grpcio_testing/grpc_version.py | 2 +- src/python/grpcio_tests/grpc_version.py | 2 +- src/ruby/lib/grpc/version.rb | 2 +- src/ruby/tools/version.rb | 2 +- tools/distrib/python/grpcio_tools/grpc_version.py | 2 +- tools/doxygen/Doxyfile.c++ | 2 +- tools/doxygen/Doxyfile.c++.internal | 2 +- 29 files changed, 36 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58525d6c6f1..8c199696a9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ cmake_minimum_required(VERSION 2.8) set(PACKAGE_NAME "grpc") -set(PACKAGE_VERSION "1.17.0") +set(PACKAGE_VERSION "1.17.1-pre1") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/") diff --git a/Makefile b/Makefile index 02273df21d1..18f49301d76 100644 --- a/Makefile +++ b/Makefile @@ -438,8 +438,8 @@ Q = @ endif CORE_VERSION = 7.0.0 -CPP_VERSION = 1.17.0 -CSHARP_VERSION = 1.17.0 +CPP_VERSION = 1.17.1-pre1 +CSHARP_VERSION = 1.17.1-pre1 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 73c87942430..ba26e3979d6 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -23,15 +23,15 @@ Pod::Spec.new do |s| s.name = 'gRPC-C++' # TODO (mxyan): use version that match gRPC version when pod is stabilized - # version = '1.17.0' - version = '0.0.6' + # version = '1.17.1-pre1' + version = '0.0.6-pre1' s.version = version s.summary = 'gRPC C++ library' s.homepage = 'https://grpc.io' s.license = 'Apache License, Version 2.0' s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } - grpc_version = '1.17.0' + grpc_version = '1.17.1-pre1' s.source = { :git => 'https://github.com/grpc/grpc.git', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index ff4d79426fe..4b499208f5c 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -22,7 +22,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-Core' - version = '1.17.0' + version = '1.17.1-pre1' s.version = version s.summary = 'Core cross-platform gRPC library, written in C' s.homepage = 'https://grpc.io' diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index d7050906e43..5d5bd6c47f5 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-ProtoRPC' - version = '1.17.0' + version = '1.17.1-pre1' s.version = version s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.homepage = 'https://grpc.io' diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec index 955f3682f67..9c453f0b192 100644 --- a/gRPC-RxLibrary.podspec +++ b/gRPC-RxLibrary.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-RxLibrary' - version = '1.17.0' + version = '1.17.1-pre1' s.version = version s.summary = 'Reactive Extensions library for iOS/OSX.' s.homepage = 'https://grpc.io' diff --git a/gRPC.podspec b/gRPC.podspec index fb46ab46704..83c7fceef1a 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.name = 'gRPC' - version = '1.17.0' + version = '1.17.1-pre1' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'https://grpc.io' diff --git a/package.xml b/package.xml index bd2fffcc555..3e3d0c354c3 100644 --- a/package.xml +++ b/package.xml @@ -13,12 +13,12 @@ 2018-01-19 - 1.17.0 - 1.17.0 + 1.17.1RC1 + 1.17.1RC1 - stable - stable + beta + beta Apache 2.0 diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc index 0a3fd804fe5..af717f9934f 100644 --- a/src/cpp/common/version_cc.cc +++ b/src/cpp/common/version_cc.cc @@ -22,5 +22,5 @@ #include namespace grpc { -grpc::string Version() { return "1.17.0"; } +grpc::string Version() { return "1.17.1-pre1"; } } // namespace grpc diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include index 4741e08cf53..1935ab77e4f 100755 --- a/src/csharp/Grpc.Core/Version.csproj.include +++ b/src/csharp/Grpc.Core/Version.csproj.include @@ -1,7 +1,7 @@ - 1.17.0 + 1.17.1-pre1 3.6.1 diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index aa881867ec5..1209c509d03 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -33,11 +33,11 @@ namespace Grpc.Core /// /// Current AssemblyFileVersion of gRPC C# assemblies /// - public const string CurrentAssemblyFileVersion = "1.17.0.0"; + public const string CurrentAssemblyFileVersion = "1.17.1.0"; /// /// Current version of gRPC C# /// - public const string CurrentVersion = "1.17.0"; + public const string CurrentVersion = "1.17.1-pre1"; } } diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index 1b860c95380..996700b3e1e 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -13,7 +13,7 @@ @rem limitations under the License. @rem Current package versions -set VERSION=1.17.0 +set VERSION=1.17.1-pre1 @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/csharp/build_unitypackage.bat b/src/csharp/build_unitypackage.bat index b9f9cf4dbb8..2fec12ddf89 100644 --- a/src/csharp/build_unitypackage.bat +++ b/src/csharp/build_unitypackage.bat @@ -13,7 +13,7 @@ @rem limitations under the License. @rem Current package versions -set VERSION=1.17.0 +set VERSION=1.17.1-pre1 @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index c72751d1c6f..65524edad29 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' - v = '1.17.0' + v = '1.17.1-pre1' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h index fa5b04612ce..02d2c58a7d0 100644 --- a/src/objective-c/GRPCClient/private/version.h +++ b/src/objective-c/GRPCClient/private/version.h @@ -22,4 +22,4 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.17.0" +#define GRPC_OBJC_VERSION_STRING @"1.17.1-pre1" diff --git a/src/objective-c/tests/version.h b/src/objective-c/tests/version.h index 1cfbf6f705d..8c3e0da603f 100644 --- a/src/objective-c/tests/version.h +++ b/src/objective-c/tests/version.h @@ -22,5 +22,5 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.17.0" +#define GRPC_OBJC_VERSION_STRING @"1.17.1-pre1" #define GRPC_C_VERSION_STRING @"7.0.0" diff --git a/src/php/composer.json b/src/php/composer.json index d54db91b5fb..be72fc059e9 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc-dev", "description": "gRPC library for PHP - for Developement use only", "license": "Apache-2.0", - "version": "1.17.0", + "version": "1.17.1", "require": { "php": ">=5.5.0", "google/protobuf": "^v3.3.0" diff --git a/src/php/ext/grpc/version.h b/src/php/ext/grpc/version.h index e529c749dbd..9e79442157f 100644 --- a/src/php/ext/grpc/version.h +++ b/src/php/ext/grpc/version.h @@ -20,6 +20,6 @@ #ifndef VERSION_H #define VERSION_H -#define PHP_GRPC_VERSION "1.17.0" +#define PHP_GRPC_VERSION "1.17.1RC1" #endif /* VERSION_H */ diff --git a/src/python/grpcio/grpc/_grpcio_metadata.py b/src/python/grpcio/grpc/_grpcio_metadata.py index 0677d1b9cf5..63e56efa6b1 100644 --- a/src/python/grpcio/grpc/_grpcio_metadata.py +++ b/src/python/grpcio/grpc/_grpcio_metadata.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!! -__version__ = """1.17.0""" +__version__ = """1.17.1rc1""" diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index 8cbd5b24f25..03f7db3b2fe 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION = '1.17.0' +VERSION = '1.17.1rc1' diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py index 222d77aab18..c0817d51dce 100644 --- a/src/python/grpcio_health_checking/grpc_version.py +++ b/src/python/grpcio_health_checking/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! -VERSION = '1.17.0' +VERSION = '1.17.1rc1' diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py index daa8a84edb3..445513c6045 100644 --- a/src/python/grpcio_reflection/grpc_version.py +++ b/src/python/grpcio_reflection/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!! -VERSION = '1.17.0' +VERSION = '1.17.1rc1' diff --git a/src/python/grpcio_testing/grpc_version.py b/src/python/grpcio_testing/grpc_version.py index af9ab31aa13..0c89e08dfbf 100644 --- a/src/python/grpcio_testing/grpc_version.py +++ b/src/python/grpcio_testing/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!! -VERSION = '1.17.0' +VERSION = '1.17.1rc1' diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py index 887f8c105bc..5b861bc0c83 100644 --- a/src/python/grpcio_tests/grpc_version.py +++ b/src/python/grpcio_tests/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!! -VERSION = '1.17.0' +VERSION = '1.17.1rc1' diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index 6b09d61c0b4..3af5e94a7d0 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -14,5 +14,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '1.17.0' + VERSION = '1.17.1.pre1' end diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index 9ae2162335d..e27237158e0 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -14,6 +14,6 @@ module GRPC module Tools - VERSION = '1.17.0' + VERSION = '1.17.1.pre1' end end diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py index 4070200384b..628315ad26e 100644 --- a/tools/distrib/python/grpcio_tools/grpc_version.py +++ b/tools/distrib/python/grpcio_tools/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! -VERSION = '1.17.0' +VERSION = '1.17.1rc1' diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 88bfada6917..c32e6b34519 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.17.0 +PROJECT_NUMBER = 1.17.1-pre1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 31f90cf1b66..d62f540ce84 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.17.0 +PROJECT_NUMBER = 1.17.1-pre1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a From 70f34521deaeaf0d783f30d121fd26787135ac04 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 6 Dec 2018 12:08:43 -0800 Subject: [PATCH 212/375] isolate start: function from proto calls --- src/objective-c/ProtoRPC/ProtoRPC.h | 10 ++++++ src/objective-c/ProtoRPC/ProtoRPC.m | 19 ++++++---- src/objective-c/tests/InteropTests.m | 53 ++++++++++++++++++++++++---- 3 files changed, 70 insertions(+), 12 deletions(-) diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 2623aecb82f..949f52d1b53 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -76,6 +76,11 @@ NS_ASSUME_NONNULL_BEGIN callOptions:(nullable GRPCCallOptions *)callOptions responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; +/** + * Start the call. This function must only be called once for each instance. + */ +- (void)start; + /** * Cancel the request of this call at best effort. It attempts to notify the server that the RPC * should be cancelled, and issue closedWithTrailingMetadata:error: callback with error code @@ -101,6 +106,11 @@ NS_ASSUME_NONNULL_BEGIN callOptions:(nullable GRPCCallOptions *)callOptions responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; +/** + * Start the call. This function must only be called once for each instance. + */ +- (void)start; + /** * Cancel the request of this call at best effort. It attempts to notify the server that the RPC * should be cancelled, and issue closedWithTrailingMetadata:error: callback with error code diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 1db04894d5e..09f8d03af6f 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -47,6 +47,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing @implementation GRPCUnaryProtoCall { GRPCStreamingProtoCall *_call; + GPBMessage *_message; } - (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions @@ -54,17 +55,24 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing responseHandler:(id)handler callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass { + NSAssert(message != nil, @"message cannot be empty."); + NSAssert(responseClass != nil, @"responseClass cannot be empty."); if ((self = [super init])) { _call = [[GRPCStreamingProtoCall alloc] initWithRequestOptions:requestOptions responseHandler:handler callOptions:callOptions responseClass:responseClass]; - [_call writeMessage:message]; - [_call finish]; + _message = [message copy]; } return self; } +- (void)start { + [_call start]; + [_call writeMessage:_message]; + [_call finish]; +} + - (void)cancel { [_call cancel]; _call = nil; @@ -120,15 +128,14 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } dispatch_set_target_queue(_dispatchQueue, handler.dispatchQueue); - [self start]; + _call = [[GRPCCall2 alloc] initWithRequestOptions:_requestOptions + responseHandler:self + callOptions:_callOptions]; } return self; } - (void)start { - _call = [[GRPCCall2 alloc] initWithRequestOptions:_requestOptions - responseHandler:self - callOptions:_callOptions]; [_call start]; } diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 2492718046f..e94fd1493a0 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -197,7 +197,7 @@ BOOL isRemoteInteropTest(NSString *host) { - (void)testEmptyUnaryRPCWithV2API { XCTAssertNotNil([[self class] host]); - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnary"]; + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnaryWithV2API"]; GPBEmpty *request = [GPBEmpty message]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; @@ -205,7 +205,7 @@ BOOL isRemoteInteropTest(NSString *host) { options.PEMRootCertificates = [[self class] PEMRootCertificates]; options.hostNameOverride = [[self class] hostNameOverride]; - [_service + GRPCUnaryProtoCall *call = [_service emptyCallWithMessage:request responseHandler:[[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil messageCallback:^(id message) { @@ -219,6 +219,7 @@ BOOL isRemoteInteropTest(NSString *host) { XCTAssertNil(error, @"Unexpected error: %@", error); }] callOptions:options]; + [call start]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } @@ -246,6 +247,44 @@ BOOL isRemoteInteropTest(NSString *host) { [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } +- (void)testLargeUnaryRPCWithV2API { + XCTAssertNotNil([[self class] host]); + __weak XCTestExpectation *expectRecvMessage = [self expectationWithDescription:@"LargeUnaryWithV2API received message"]; + __weak XCTestExpectation *expectRecvComplete = [self expectationWithDescription:@"LargeUnaryWithV2API received complete"]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + request.responseType = RMTPayloadType_Compressable; + request.responseSize = 314159; + request.payload.body = [NSMutableData dataWithLength:271828]; + + GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; + options.transportType = [[self class] transportType]; + options.PEMRootCertificates = [[self class] PEMRootCertificates]; + options.hostNameOverride = [[self class] hostNameOverride]; + + GRPCUnaryProtoCall *call = [_service + unaryCallWithMessage:request + responseHandler:[[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + messageCallback:^(id message) { + XCTAssertNotNil(message); + if (message) { + RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; + expectedResponse.payload.type = RMTPayloadType_Compressable; + expectedResponse.payload.body = [NSMutableData dataWithLength:314159]; + XCTAssertEqualObjects(message, expectedResponse); + + [expectRecvMessage fulfill]; + } + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + XCTAssertNil(error, @"Unexpected error: %@", error); + [expectRecvComplete fulfill]; + }] + callOptions:options]; + [call start]; + [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; +} + - (void)testPacketCoalescing { XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectation = [self expectationWithDescription:@"LargeUnary"]; @@ -473,7 +512,7 @@ BOOL isRemoteInteropTest(NSString *host) { - (void)testPingPongRPCWithV2API { XCTAssertNotNil([[self class] host]); - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPong"]; + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPongWithV2API"]; NSArray *requests = @[ @27182, @8, @1828, @45904 ]; NSArray *responses = @[ @31415, @9, @2653, @58979 ]; @@ -517,6 +556,7 @@ BOOL isRemoteInteropTest(NSString *host) { [expectation fulfill]; }] callOptions:options]; + [call start]; [call writeMessage:request]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; @@ -562,7 +602,7 @@ BOOL isRemoteInteropTest(NSString *host) { - (void)testCancelAfterBeginRPCWithV2API { XCTAssertNotNil([[self class] host]); - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBegin"]; + __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBeginWithV2API"]; // A buffered pipe to which we never write any value acts as a writer that just hangs. __block GRPCStreamingProtoCall *call = [_service @@ -577,6 +617,7 @@ BOOL isRemoteInteropTest(NSString *host) { [expectation fulfill]; }] callOptions:nil]; + [call start]; [call cancel]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; @@ -650,7 +691,7 @@ BOOL isRemoteInteropTest(NSString *host) { [completionExpectation fulfill]; }] callOptions:options]; - + [call start]; [call writeMessage:request]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } @@ -680,7 +721,7 @@ BOOL isRemoteInteropTest(NSString *host) { [completionExpectation fulfill]; }] callOptions:options]; - + [call start]; [call writeMessage:request]; [call cancel]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; From 76f1ec16e1880605215beb60a204b0cab7c36b2d Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 6 Dec 2018 12:42:27 -0800 Subject: [PATCH 213/375] sensible nullability annotation for old API --- src/objective-c/GRPCClient/GRPCCall.h | 22 ++++++++++--------- src/objective-c/GRPCClient/GRPCCall.m | 7 +++--- src/objective-c/ProtoRPC/ProtoRPC.h | 10 ++++----- .../examples/SwiftSample/ViewController.swift | 10 ++++----- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 214969af230..51a82263bff 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -282,6 +282,8 @@ NS_ASSUME_NONNULL_END */ @interface GRPCCall : GRXWriter +- (instancetype)init NS_UNAVAILABLE; + /** * 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. @@ -306,7 +308,7 @@ NS_ASSUME_NONNULL_END * * The property is initialized to an empty NSMutableDictionary. */ -@property(nullable, atomic, readonly) NSMutableDictionary *requestHeaders; +@property(nonnull, atomic, readonly) NSMutableDictionary *requestHeaders; /** * This dictionary is populated with the HTTP headers received from the server. This happens before @@ -339,9 +341,9 @@ NS_ASSUME_NONNULL_END * host parameter should not contain the scheme (http:// or https://), only the name or IP addr * and the port number, for example @"localhost:5050". */ -- (nullable instancetype)initWithHost:(nullable NSString *)host - path:(nullable NSString *)path - requestsWriter:(nullable GRXWriter *)requestWriter; +- (nullable instancetype)initWithHost:(nonnull NSString *)host + path:(nonnull NSString *)path + requestsWriter:(nonnull GRXWriter *)requestWriter; /** * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and @@ -353,11 +355,11 @@ NS_ASSUME_NONNULL_END * The following methods are deprecated. */ + (void)setCallSafety:(GRPCCallSafety)callSafety - host:(nullable NSString *)host - path:(nullable NSString *)path; + host:(nonnull NSString *)host + path:(nonnull NSString *)path; @property(nullable, atomic, copy, readwrite) NSString *serverName; @property NSTimeInterval timeout; -- (void)setResponseDispatchQueue:(nullable dispatch_queue_t)queue; +- (void)setResponseDispatchQueue:(nonnull dispatch_queue_t)queue; @end @@ -368,11 +370,11 @@ DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.") @protocol GRPCRequestHeaders @property(nonatomic, readonly) NSUInteger count; -- (nullable id)objectForKeyedSubscript:(nullable id)key; -- (void)setObject:(nullable id)obj forKeyedSubscript:(nullable id)key; +- (nullable id)objectForKeyedSubscript:(nonnull id)key; +- (void)setObject:(nullable id)obj forKeyedSubscript:(nonnull id)key; - (void)removeAllObjects; -- (void)removeObjectForKey:(nullable id)key; +- (void)removeObjectForKey:(nonnull id)key; @end #pragma clang diagnostic push diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index dad8594a264..9b3bcd385e7 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -445,6 +445,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; } + (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString *)host path:(NSString *)path { + if (host.length == 0 || path.length == 0) { + return; + } NSString *hostAndPath = [NSString stringWithFormat:@"%@/%@", host, path]; switch (callSafety) { case GRPCCallSafetyDefault: @@ -466,10 +469,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; return [callFlags[hostAndPath] intValue]; } -- (instancetype)init { - return [self initWithHost:nil path:nil requestsWriter:nil]; -} - // Designated initializer - (instancetype)initWithHost:(NSString *)host path:(NSString *)path diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 949f52d1b53..1819fa93796 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -142,11 +142,11 @@ __attribute__((deprecated("Please use GRPCProtoCall."))) @interface ProtoRPC * addr and the port number, for example @"localhost:5050". */ - - (nullable instancetype)initWithHost : (nullable NSString *)host method - : (nullable GRPCProtoMethod *)method requestsWriter - : (nullable GRXWriter *)requestsWriter responseClass - : (nullable Class)responseClass responsesWriteable - : (nullable id)responsesWriteable NS_DESIGNATED_INITIALIZER; + (nullable instancetype)initWithHost : (nonnull NSString *)host method + : (nonnull GRPCProtoMethod *)method requestsWriter + : (nonnull GRXWriter *)requestsWriter responseClass + : (nonnull Class)responseClass responsesWriteable + : (nonnull id)responsesWriteable NS_DESIGNATED_INITIALIZER; - (void)start; @end diff --git a/src/objective-c/examples/SwiftSample/ViewController.swift b/src/objective-c/examples/SwiftSample/ViewController.swift index 0ba6e21f02a..4ed10266a4d 100644 --- a/src/objective-c/examples/SwiftSample/ViewController.swift +++ b/src/objective-c/examples/SwiftSample/ViewController.swift @@ -54,8 +54,8 @@ class ViewController: UIViewController { } else { NSLog("2. Finished with error: \(error!)") } - NSLog("2. Response headers: \(RPC.responseHeaders)") - NSLog("2. Response trailers: \(RPC.responseTrailers)") + NSLog("2. Response headers: \(String(describing: RPC.responseHeaders))") + NSLog("2. Response trailers: \(String(describing: RPC.responseTrailers))") } // TODO(jcanizales): Revert to using subscript syntax once XCode 8 is released. @@ -68,7 +68,7 @@ class ViewController: UIViewController { let method = GRPCProtoMethod(package: "grpc.testing", service: "TestService", method: "UnaryCall")! - let requestsWriter = GRXWriter(value: request.data()) + let requestsWriter = GRXWriter(value: request.data())! let call = GRPCCall(host: RemoteHost, path: method.httpPath, requestsWriter: requestsWriter)! @@ -80,8 +80,8 @@ class ViewController: UIViewController { } else { NSLog("3. Finished with error: \(error!)") } - NSLog("3. Response headers: \(call.responseHeaders)") - NSLog("3. Response trailers: \(call.responseTrailers)") + NSLog("3. Response headers: \(String(describing: call.responseHeaders))") + NSLog("3. Response trailers: \(String(describing: call.responseTrailers))") }) } } From eeced98fc556c6a5bc3a5dedc171c98747217078 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 6 Dec 2018 13:08:34 -0800 Subject: [PATCH 214/375] Rename handlers to didXxx --- src/objective-c/GRPCClient/GRPCCall.h | 8 +++---- src/objective-c/GRPCClient/GRPCCall.m | 16 ++++++------- src/objective-c/ProtoRPC/ProtoRPC.h | 12 +++++----- src/objective-c/ProtoRPC/ProtoRPC.m | 24 +++++++++---------- src/objective-c/tests/APIv2Tests/APIv2Tests.m | 6 ++--- src/objective-c/tests/InteropTests.m | 6 ++--- 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 51a82263bff..985743433cf 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -158,13 +158,13 @@ extern NSString *const kGRPCTrailersKey; /** * Issued when initial metadata is received from the server. */ -- (void)receivedInitialMetadata:(nullable NSDictionary *)initialMetadata; +- (void)didReceiveInitialMetadata:(nullable NSDictionary *)initialMetadata; /** * Issued when a message is received from the server. The message is the raw data received from the * server, with decompression and without proto deserialization. */ -- (void)receivedRawMessage:(nullable NSData *)message; +- (void)didReceiveRawMessage:(nullable NSData *)message; /** * Issued when a call finished. If the call finished successfully, \a error is nil and \a @@ -172,7 +172,7 @@ extern NSString *const kGRPCTrailersKey; * is non-nil and contains the corresponding error information, including gRPC error codes and * error descriptions. */ -- (void)closedWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata +- (void)didCloseWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata error:(nullable NSError *)error; @required @@ -247,7 +247,7 @@ extern NSString *const kGRPCTrailersKey; /** * Cancel the request of this call at best effort. It attempts to notify the server that the RPC - * should be cancelled, and issue closedWithTrailingMetadata:error: callback with error code + * should be cancelled, and issue didCloseWithTrailingMetadata:error: callback with error code * CANCELED if no other error code has already been issued. */ - (void)cancel; diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 9b3bcd385e7..48253677bd3 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -250,7 +250,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; _call = nil; _pipe = nil; - if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + if ([_handler respondsToSelector:@selector(didCloseWithTrailingMetadata:error:)]) { dispatch_async(_dispatchQueue, ^{ // Copy to local so that block is freed after cancellation completes. id copiedHandler = nil; @@ -259,7 +259,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; self->_handler = nil; } - [copiedHandler closedWithTrailingMetadata:nil + [copiedHandler didCloseWithTrailingMetadata:nil error:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeCancelled userInfo:@{ @@ -321,13 +321,13 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)issueInitialMetadata:(NSDictionary *)initialMetadata { @synchronized(self) { if (initialMetadata != nil && - [_handler respondsToSelector:@selector(receivedInitialMetadata:)]) { + [_handler respondsToSelector:@selector(didReceiveInitialMetadata:)]) { dispatch_async(_dispatchQueue, ^{ id copiedHandler = nil; @synchronized(self) { copiedHandler = self->_handler; } - [copiedHandler receivedInitialMetadata:initialMetadata]; + [copiedHandler didReceiveInitialMetadata:initialMetadata]; }); } } @@ -335,13 +335,13 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)issueMessage:(id)message { @synchronized(self) { - if (message != nil && [_handler respondsToSelector:@selector(receivedRawMessage:)]) { + if (message != nil && [_handler respondsToSelector:@selector(didReceiveRawMessage:)]) { dispatch_async(_dispatchQueue, ^{ id copiedHandler = nil; @synchronized(self) { copiedHandler = self->_handler; } - [copiedHandler receivedRawMessage:message]; + [copiedHandler didReceiveRawMessage:message]; }); } } @@ -349,7 +349,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)issueClosedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { @synchronized(self) { - if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + if ([_handler respondsToSelector:@selector(didCloseWithTrailingMetadata:error:)]) { dispatch_async(_dispatchQueue, ^{ id copiedHandler = nil; @synchronized(self) { @@ -357,7 +357,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Clean up _handler so that no more responses are reported to the handler. self->_handler = nil; } - [copiedHandler closedWithTrailingMetadata:trailingMetadata error:error]; + [copiedHandler didCloseWithTrailingMetadata:trailingMetadata error:error]; }); } else { _handler = nil; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 1819fa93796..287aa0369b1 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -33,12 +33,12 @@ NS_ASSUME_NONNULL_BEGIN /** * Issued when initial metadata is received from the server. */ -- (void)receivedInitialMetadata:(nullable NSDictionary *)initialMetadata; +- (void)didReceiveInitialMetadata:(nullable NSDictionary *)initialMetadata; /** * Issued when a message is received from the server. The message is the deserialized proto object. */ -- (void)receivedProtoMessage:(nullable GPBMessage *)message; +- (void)didReceiveProtoMessage:(nullable GPBMessage *)message; /** * Issued when a call finished. If the call finished successfully, \a error is nil and \a @@ -46,8 +46,8 @@ NS_ASSUME_NONNULL_BEGIN * is non-nil and contains the corresponding error information, including gRPC error codes and * error descriptions. */ -- (void)closedWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata - error:(nullable NSError *)error; +- (void)didCloseWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata + error:(nullable NSError *)error; @required @@ -83,7 +83,7 @@ NS_ASSUME_NONNULL_BEGIN /** * Cancel the request of this call at best effort. It attempts to notify the server that the RPC - * should be cancelled, and issue closedWithTrailingMetadata:error: callback with error code + * should be cancelled, and issue didCloseWithTrailingMetadata:error: callback with error code * CANCELED if no other error code has already been issued. */ - (void)cancel; @@ -113,7 +113,7 @@ NS_ASSUME_NONNULL_BEGIN /** * Cancel the request of this call at best effort. It attempts to notify the server that the RPC - * should be cancelled, and issue closedWithTrailingMetadata:error: callback with error code + * should be cancelled, and issue didCloseWithTrailingMetadata:error: callback with error code * CANCELED if no other error code has already been issued. */ - (void)cancel; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 09f8d03af6f..886e31ce58a 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -144,14 +144,14 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing @synchronized(self) { copiedCall = _call; _call = nil; - if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + if ([_handler respondsToSelector:@selector(didCloseWithTrailingMetadata:error:)]) { dispatch_async(_handler.dispatchQueue, ^{ id copiedHandler = nil; @synchronized(self) { copiedHandler = self->_handler; self->_handler = nil; } - [copiedHandler closedWithTrailingMetadata:nil + [copiedHandler didCloseWithTrailingMetadata:nil error:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeCancelled userInfo:@{ @@ -187,7 +187,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing [call finish]; } -- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { +- (void)didReceiveInitialMetadata:(NSDictionary *)initialMetadata { @synchronized(self) { if (initialMetadata != nil && [_handler respondsToSelector:@selector(initialMetadata:)]) { dispatch_async(_dispatchQueue, ^{ @@ -195,35 +195,35 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing @synchronized(self) { copiedHandler = self->_handler; } - [copiedHandler receivedInitialMetadata:initialMetadata]; + [copiedHandler didReceiveInitialMetadata:initialMetadata]; }); } } } -- (void)receivedRawMessage:(NSData *)message { +- (void)didReceiveRawMessage:(NSData *)message { if (message == nil) return; NSError *error = nil; GPBMessage *parsed = [_responseClass parseFromData:message error:&error]; @synchronized(self) { - if (parsed && [_handler respondsToSelector:@selector(receivedProtoMessage:)]) { + if (parsed && [_handler respondsToSelector:@selector(didReceiveProtoMessage:)]) { dispatch_async(_dispatchQueue, ^{ id copiedHandler = nil; @synchronized(self) { copiedHandler = self->_handler; } - [copiedHandler receivedProtoMessage:parsed]; + [copiedHandler didReceiveProtoMessage:parsed]; }); } else if (!parsed && - [_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + [_handler respondsToSelector:@selector(didCloseWithTrailingMetadata:error:)]) { dispatch_async(_dispatchQueue, ^{ id copiedHandler = nil; @synchronized(self) { copiedHandler = self->_handler; self->_handler = nil; } - [copiedHandler closedWithTrailingMetadata:nil + [copiedHandler didCloseWithTrailingMetadata:nil error:ErrorForBadProto(message, _responseClass, error)]; }); [_call cancel]; @@ -232,16 +232,16 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } } -- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { +- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { @synchronized(self) { - if ([_handler respondsToSelector:@selector(closedWithTrailingMetadata:error:)]) { + if ([_handler respondsToSelector:@selector(didCloseWithTrailingMetadata:error:)]) { dispatch_async(_dispatchQueue, ^{ id copiedHandler = nil; @synchronized(self) { copiedHandler = self->_handler; self->_handler = nil; } - [copiedHandler closedWithTrailingMetadata:trailingMetadata error:error]; + [copiedHandler didCloseWithTrailingMetadata:trailingMetadata error:error]; }); } _call = nil; diff --git a/src/objective-c/tests/APIv2Tests/APIv2Tests.m b/src/objective-c/tests/APIv2Tests/APIv2Tests.m index 32f2122f79b..ca7bf472830 100644 --- a/src/objective-c/tests/APIv2Tests/APIv2Tests.m +++ b/src/objective-c/tests/APIv2Tests/APIv2Tests.m @@ -81,19 +81,19 @@ static const NSTimeInterval kTestTimeout = 16; return self; } -- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { +- (void)didReceiveInitialMetadata:(NSDictionary *)initialMetadata { if (self->_initialMetadataCallback) { self->_initialMetadataCallback(initialMetadata); } } -- (void)receivedRawMessage:(GPBMessage *)message { +- (void)didReceiveRawMessage:(GPBMessage *)message { if (self->_messageCallback) { self->_messageCallback(message); } } -- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { +- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { if (self->_closeCallback) { self->_closeCallback(trailingMetadata, error); } diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index e94fd1493a0..d17a07f929a 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -102,19 +102,19 @@ BOOL isRemoteInteropTest(NSString *host) { return self; } -- (void)receivedInitialMetadata:(NSDictionary *)initialMetadata { +- (void)didReceiveInitialMetadata:(NSDictionary *)initialMetadata { if (_initialMetadataCallback) { _initialMetadataCallback(initialMetadata); } } -- (void)receivedProtoMessage:(GPBMessage *)message { +- (void)didReceiveProtoMessage:(GPBMessage *)message { if (_messageCallback) { _messageCallback(message); } } -- (void)closedWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { +- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error { if (_closeCallback) { _closeCallback(trailingMetadata, error); } From f9e50322bf1d6be736b415831eea44130b9dedfe Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 6 Dec 2018 15:58:53 -0800 Subject: [PATCH 215/375] batch fix --- src/objective-c/GRPCClient/GRPCCall.h | 16 +++--- src/objective-c/GRPCClient/GRPCCall.m | 4 +- .../GRPCClient/private/GRPCChannelPool+Test.h | 49 +++++++++++++++++++ .../GRPCClient/private/GRPCChannelPool.h | 28 ----------- .../GRPCClient/private/GRPCChannelPool.m | 7 ++- src/objective-c/ProtoRPC/ProtoRPC.h | 16 +++--- src/objective-c/ProtoRPC/ProtoRPC.m | 5 +- .../tests/ChannelTests/ChannelPoolTest.m | 2 +- .../tests/ChannelTests/ChannelTests.m | 1 + 9 files changed, 73 insertions(+), 55 deletions(-) create mode 100644 src/objective-c/GRPCClient/private/GRPCChannelPool+Test.h diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 985743433cf..6d8b9c1b127 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -153,6 +153,14 @@ extern NSString *const kGRPCTrailersKey; /** An object can implement this protocol to receive responses from server from a call. */ @protocol GRPCResponseHandler +@required + +/** + * All the responses must be issued to a user-provided dispatch queue. This property specifies the + * dispatch queue to be used for issuing the notifications. + */ +@property(atomic, readonly) dispatch_queue_t dispatchQueue; + @optional /** @@ -175,14 +183,6 @@ extern NSString *const kGRPCTrailersKey; - (void)didCloseWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata error:(nullable NSError *)error; -@required - -/** - * All the responses must be issued to a user-provided dispatch queue. This property specifies the - * dispatch queue to be used for issuing the notifications. - */ -@property(atomic, readonly) dispatch_queue_t dispatchQueue; - @end /** diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 48253677bd3..e75ca7193a7 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -856,9 +856,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; _retainSelf = self; if (_callOptions == nil) { - GRPCMutableCallOptions *callOptions; - - callOptions = [[GRPCHost callOptionsForHost:_host] mutableCopy]; + GRPCMutableCallOptions *callOptions = [[GRPCHost callOptionsForHost:_host] mutableCopy]; if (_serverName.length != 0) { callOptions.serverAuthority = _serverName; } diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool+Test.h b/src/objective-c/GRPCClient/private/GRPCChannelPool+Test.h new file mode 100644 index 00000000000..4e7c988585d --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool+Test.h @@ -0,0 +1,49 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#import "GRPCChannelPool.h" + +/** Test-only interface for \a GRPCPooledChannel. */ +@interface GRPCPooledChannel (Test) + +/** + * Initialize a pooled channel with non-default destroy delay for testing purpose. + */ +- (nullable instancetype)initWithChannelConfiguration: +(GRPCChannelConfiguration *)channelConfiguration + destroyDelay:(NSTimeInterval)destroyDelay; + +/** + * Return the pointer to the raw channel wrapped. + */ +@property(atomic, readonly) GRPCChannel *wrappedChannel; + +@end + +/** Test-only interface for \a GRPCChannelPool. */ +@interface GRPCChannelPool (Test) + +/** + * Get an instance of pool isolated from the global shared pool with channels' destroy delay being + * \a destroyDelay. + */ +- (nullable instancetype)initTestPool; + +@end + + diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 7c6f2b3bbfa..d1f28ec9bfa 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -75,23 +75,6 @@ NS_ASSUME_NONNULL_BEGIN @end -/** Test-only interface for \a GRPCPooledChannel. */ -@interface GRPCPooledChannel (Test) - -/** - * Initialize a pooled channel with non-default destroy delay for testing purpose. - */ -- (nullable instancetype)initWithChannelConfiguration: -(GRPCChannelConfiguration *)channelConfiguration - destroyDelay:(NSTimeInterval)destroyDelay; - -/** - * Return the pointer to the raw channel wrapped. - */ -@property(atomic, readonly) GRPCChannel *wrappedChannel; - -@end - /** * Manage the pool of connected channels. When a channel is no longer referenced by any call, * destroy the channel after a certain period of time elapsed. @@ -119,15 +102,4 @@ NS_ASSUME_NONNULL_BEGIN @end -/** Test-only interface for \a GRPCChannelPool. */ -@interface GRPCChannelPool (Test) - -/** - * Get an instance of pool isolated from the global shared pool with channels' destroy delay being - * \a destroyDelay. - */ -- (nullable instancetype)initTestPool; - -@end - NS_ASSUME_NONNULL_END diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 391022efd19..349bdd44a65 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -22,6 +22,7 @@ #import "GRPCChannel.h" #import "GRPCChannelFactory.h" #import "GRPCChannelPool.h" +#import "GRPCChannelPool+Test.h" #import "GRPCConnectivityMonitor.h" #import "GRPCCronetChannelFactory.h" #import "GRPCInsecureChannelFactory.h" @@ -59,9 +60,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; - (void)dealloc { // Disconnect GRPCWrappedCall objects created but not yet removed if (_wrappedCalls.allObjects.count != 0) { - NSEnumerator *enumerator = [_wrappedCalls objectEnumerator]; - GRPCWrappedCall *wrappedCall; - while ((wrappedCall = [enumerator nextObject])) { + for (GRPCWrappedCall *wrappedCall in _wrappedCalls.allObjects) { [wrappedCall channelDisconnected]; }; } @@ -73,7 +72,7 @@ callOptions:(GRPCCallOptions *)callOptions { NSAssert(path.length > 0, @"path must not be empty."); NSAssert(queue != nil, @"completionQueue must not be empty."); NSAssert(callOptions, @"callOptions must not be empty."); - if (path.length == 0 || queue == nil || callOptions == nil) return NULL; + if (path.length == 0 || queue == nil || callOptions == nil) return nil; GRPCWrappedCall *call = nil; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 287aa0369b1..2e0400a323f 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -28,6 +28,14 @@ NS_ASSUME_NONNULL_BEGIN /** An object can implement this protocol to receive responses from server from a call. */ @protocol GRPCProtoResponseHandler +@required + +/** + * All the responses must be issued to a user-provided dispatch queue. This property specifies the + * dispatch queue to be used for issuing the notifications. + */ +@property(atomic, readonly) dispatch_queue_t dispatchQueue; + @optional /** @@ -49,14 +57,6 @@ NS_ASSUME_NONNULL_BEGIN - (void)didCloseWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata error:(nullable NSError *)error; -@required - -/** - * All the responses must be issued to a user-provided dispatch queue. This property specifies the - * dispatch queue to be used for issuing the notifications. - */ -@property(atomic, readonly) dispatch_queue_t dispatchQueue; - @end /** A unary-request RPC call with Protobuf. */ diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 886e31ce58a..0f63f72f536 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -75,7 +75,6 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing - (void)cancel { [_call cancel]; - _call = nil; } @end @@ -124,7 +123,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing #else { #endif - _dispatchQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL); + _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); } dispatch_set_target_queue(_dispatchQueue, handler.dispatchQueue); @@ -145,7 +144,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing copiedCall = _call; _call = nil; if ([_handler respondsToSelector:@selector(didCloseWithTrailingMetadata:error:)]) { - dispatch_async(_handler.dispatchQueue, ^{ + dispatch_async(_dispatchQueue, ^{ id copiedHandler = nil; @synchronized(self) { copiedHandler = self->_handler; diff --git a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m index dc42d7c341d..eab8c5193fb 100644 --- a/src/objective-c/tests/ChannelTests/ChannelPoolTest.m +++ b/src/objective-c/tests/ChannelTests/ChannelPoolTest.m @@ -19,7 +19,7 @@ #import #import "../../GRPCClient/private/GRPCChannel.h" -#import "../../GRPCClient/private/GRPCChannelPool.h" +#import "../../GRPCClient/private/GRPCChannelPool+Test.h" #import "../../GRPCClient/private/GRPCCompletionQueue.h" #define TEST_TIMEOUT 32 diff --git a/src/objective-c/tests/ChannelTests/ChannelTests.m b/src/objective-c/tests/ChannelTests/ChannelTests.m index ee7f8b6fddb..7c80868c2c9 100644 --- a/src/objective-c/tests/ChannelTests/ChannelTests.m +++ b/src/objective-c/tests/ChannelTests/ChannelTests.m @@ -21,6 +21,7 @@ #import "../../GRPCClient/GRPCCallOptions.h" #import "../../GRPCClient/private/GRPCChannel.h" #import "../../GRPCClient/private/GRPCChannelPool.h" +#import "../../GRPCClient/private/GRPCChannelPool+Test.h" #import "../../GRPCClient/private/GRPCCompletionQueue.h" #import "../../GRPCClient/private/GRPCWrappedCall.h" From da759f1fc63ceb0c893bb6027bacfadfda5ab111 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 6 Dec 2018 18:26:51 -0800 Subject: [PATCH 216/375] batch fixes --- src/objective-c/GRPCClient/GRPCCall.h | 2 +- src/objective-c/GRPCClient/GRPCCall.m | 5 +- src/objective-c/GRPCClient/GRPCCallOptions.h | 4 +- src/objective-c/GRPCClient/GRPCCallOptions.m | 32 ++++---- .../GRPCClient/private/GRPCChannel.h | 5 +- .../GRPCClient/private/GRPCChannel.m | 8 +- .../GRPCClient/private/GRPCChannelPool.h | 13 +-- .../GRPCClient/private/GRPCChannelPool.m | 82 ++++++++++--------- .../private/GRPCCronetChannelFactory.m | 8 +- src/objective-c/GRPCClient/private/GRPCHost.m | 7 +- .../private/GRPCSecureChannelFactory.m | 5 +- .../GRPCClient/private/GRPCWrappedCall.m | 11 +-- .../GRPCClient/private/utilities.h | 22 ----- 13 files changed, 89 insertions(+), 115 deletions(-) delete mode 100644 src/objective-c/GRPCClient/private/utilities.h diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 6d8b9c1b127..be63de1af9b 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -206,7 +206,7 @@ extern NSString *const kGRPCTrailersKey; @property(copy, readonly) NSString *path; /** * Specify whether the call is idempotent or cachable. gRPC may select different HTTP verbs for the - * call based on this information. + * call based on this information. The default verb used by gRPC is POST. */ @property(readonly) GRPCCallSafety safety; diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index e75ca7193a7..e56cc72149c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -35,7 +35,6 @@ #import "private/NSData+GRPC.h" #import "private/NSDictionary+GRPC.h" #import "private/NSError+GRPC.h" -#import "private/utilities.h" #import "private/GRPCChannelPool.h" #import "private/GRPCCompletionQueue.h" @@ -277,7 +276,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)writeData:(NSData *)data { GRXBufferedPipe *copiedPipe = nil; @synchronized(self) { - NSAssert(!_canceled, @"Call arleady canceled."); + NSAssert(!_canceled, @"Call already canceled."); NSAssert(!_finished, @"Call is half-closed before sending data."); if (_canceled) { return; @@ -297,7 +296,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; GRXBufferedPipe *copiedPipe = nil; @synchronized(self) { NSAssert(_started, @"Call not started."); - NSAssert(!_canceled, @"Call arleady canceled."); + NSAssert(!_canceled, @"Call already canceled."); NSAssert(!_finished, @"Call already half-closed."); if (!_started) { return; diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 158a4745d23..85786c74174 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -170,7 +170,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { /** * PEM format certificate chain for client authentication, if required by the server. */ -@property(copy, readonly, nullable) NSString *PEMCertChain; +@property(copy, readonly, nullable) NSString *PEMCertificateChain; /** * Select the transport type to be used for this call. @@ -314,7 +314,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { /** * PEM format certificate chain for client authentication, if required by the server. */ -@property(copy, readwrite, nullable) NSString *PEMCertChain; +@property(copy, readwrite, nullable) NSString *PEMCertificateChain; /** * Select the transport type to be used for this call. diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 9a36ee547cd..1962ad8956d 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -35,7 +35,7 @@ static const NSTimeInterval kDefaultConnectMaxBackoff = 0; static NSDictionary *const kDefaultAdditionalChannelArgs = nil; static NSString *const kDefaultPEMRootCertificates = nil; static NSString *const kDefaultPEMPrivateKey = nil; -static NSString *const kDefaultPEMCertChain = nil; +static NSString *const kDefaultPEMCertificateChain = nil; static NSString *const kDefaultOauth2AccessToken = nil; static const id kDefaultAuthTokenProvider = nil; static const GRPCTransportType kDefaultTransportType = GRPCTransportTypeChttp2BoringSSL; @@ -74,7 +74,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { NSDictionary *_additionalChannelArgs; NSString *_PEMRootCertificates; NSString *_PEMPrivateKey; - NSString *_PEMCertChain; + NSString *_PEMCertificateChain; GRPCTransportType _transportType; NSString *_hostNameOverride; id _logContext; @@ -99,7 +99,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { @synthesize additionalChannelArgs = _additionalChannelArgs; @synthesize PEMRootCertificates = _PEMRootCertificates; @synthesize PEMPrivateKey = _PEMPrivateKey; -@synthesize PEMCertChain = _PEMCertChain; +@synthesize PEMCertificateChain = _PEMCertificateChain; @synthesize transportType = _transportType; @synthesize hostNameOverride = _hostNameOverride; @synthesize logContext = _logContext; @@ -124,7 +124,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { additionalChannelArgs:kDefaultAdditionalChannelArgs PEMRootCertificates:kDefaultPEMRootCertificates PEMPrivateKey:kDefaultPEMPrivateKey - PEMCertChain:kDefaultPEMCertChain + PEMCertificateChain:kDefaultPEMCertificateChain transportType:kDefaultTransportType hostNameOverride:kDefaultHostNameOverride logContext:kDefaultLogContext @@ -149,7 +149,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { additionalChannelArgs:(NSDictionary *)additionalChannelArgs PEMRootCertificates:(NSString *)PEMRootCertificates PEMPrivateKey:(NSString *)PEMPrivateKey - PEMCertChain:(NSString *)PEMCertChain + PEMCertificateChain:(NSString *)PEMCertificateChain transportType:(GRPCTransportType)transportType hostNameOverride:(NSString *)hostNameOverride logContext:(id)logContext @@ -174,7 +174,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { [[NSDictionary alloc] initWithDictionary:additionalChannelArgs copyItems:YES]; _PEMRootCertificates = [PEMRootCertificates copy]; _PEMPrivateKey = [PEMPrivateKey copy]; - _PEMCertChain = [PEMCertChain copy]; + _PEMCertificateChain = [PEMCertificateChain copy]; _transportType = transportType; _hostNameOverride = [hostNameOverride copy]; _logContext = logContext; @@ -203,7 +203,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { additionalChannelArgs:_additionalChannelArgs PEMRootCertificates:_PEMRootCertificates PEMPrivateKey:_PEMPrivateKey - PEMCertChain:_PEMCertChain + PEMCertificateChain:_PEMCertificateChain transportType:_transportType hostNameOverride:_hostNameOverride logContext:_logContext @@ -233,7 +233,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { copyItems:YES] PEMRootCertificates:[_PEMRootCertificates copy] PEMPrivateKey:[_PEMPrivateKey copy] - PEMCertChain:[_PEMCertChain copy] + PEMCertificateChain:[_PEMCertificateChain copy] transportType:_transportType hostNameOverride:[_hostNameOverride copy] logContext:_logContext @@ -256,7 +256,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { if (!areObjectsEqual(callOptions.additionalChannelArgs, _additionalChannelArgs)) return NO; if (!areObjectsEqual(callOptions.PEMRootCertificates, _PEMRootCertificates)) return NO; if (!areObjectsEqual(callOptions.PEMPrivateKey, _PEMPrivateKey)) return NO; - if (!areObjectsEqual(callOptions.PEMCertChain, _PEMCertChain)) return NO; + if (!areObjectsEqual(callOptions.PEMCertificateChain, _PEMCertificateChain)) return NO; if (!areObjectsEqual(callOptions.hostNameOverride, _hostNameOverride)) return NO; if (!(callOptions.transportType == _transportType)) return NO; if (!areObjectsEqual(callOptions.logContext, _logContext)) return NO; @@ -280,7 +280,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { result ^= _additionalChannelArgs.hash; result ^= _PEMRootCertificates.hash; result ^= _PEMPrivateKey.hash; - result ^= _PEMCertChain.hash; + result ^= _PEMCertificateChain.hash; result ^= _hostNameOverride.hash; result ^= _transportType; result ^= _logContext.hash; @@ -311,7 +311,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { @dynamic additionalChannelArgs; @dynamic PEMRootCertificates; @dynamic PEMPrivateKey; -@dynamic PEMCertChain; +@dynamic PEMCertificateChain; @dynamic transportType; @dynamic hostNameOverride; @dynamic logContext; @@ -336,7 +336,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { additionalChannelArgs:kDefaultAdditionalChannelArgs PEMRootCertificates:kDefaultPEMRootCertificates PEMPrivateKey:kDefaultPEMPrivateKey - PEMCertChain:kDefaultPEMCertChain + PEMCertificateChain:kDefaultPEMCertificateChain transportType:kDefaultTransportType hostNameOverride:kDefaultHostNameOverride logContext:kDefaultLogContext @@ -363,7 +363,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { additionalChannelArgs:_additionalChannelArgs PEMRootCertificates:_PEMRootCertificates PEMPrivateKey:_PEMPrivateKey - PEMCertChain:_PEMCertChain + PEMCertificateChain:_PEMCertificateChain transportType:_transportType hostNameOverride:_hostNameOverride logContext:_logContext @@ -391,7 +391,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { additionalChannelArgs:[_additionalChannelArgs copy] PEMRootCertificates:_PEMRootCertificates PEMPrivateKey:_PEMPrivateKey - PEMCertChain:_PEMCertChain + PEMCertificateChain:_PEMCertificateChain transportType:_transportType hostNameOverride:_hostNameOverride logContext:_logContext @@ -493,8 +493,8 @@ static BOOL areObjectsEqual(id obj1, id obj2) { _PEMPrivateKey = [PEMPrivateKey copy]; } -- (void)setPEMCertChain:(NSString *)PEMCertChain { - _PEMCertChain = [PEMCertChain copy]; +- (void)setPEMCertificateChain:(NSString *)PEMCertificateChain { + _PEMCertificateChain = [PEMCertificateChain copy]; } - (void)setTransportType:(GRPCTransportType)transportType { diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h index c01aeccf81f..bbada0d8cb3 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.h +++ b/src/objective-c/GRPCClient/private/GRPCChannel.h @@ -29,7 +29,10 @@ struct grpc_channel_credentials; NS_ASSUME_NONNULL_BEGIN -/** Caching signature of a channel. */ +/** + * Signature for the channel. If two channel's signatures are the same and connect to the same + * remote, they share the same underlying \a GRPCChannel object. + */ @interface GRPCChannelConfiguration : NSObject - (instancetype)init NS_UNAVAILABLE; diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 9432e7ab397..edcedf6e24f 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -28,7 +28,6 @@ #import "GRPCCronetChannelFactory.h" #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" -#import "utilities.h" #import "version.h" #import @@ -63,8 +62,9 @@ factory = [GRPCSecureChannelFactory factoryWithPEMRootCertificates:_callOptions.PEMRootCertificates privateKey:_callOptions.PEMPrivateKey - certChain:_callOptions.PEMCertChain + certChain:_callOptions.PEMCertificateChain error:&error]; + NSAssert(factory != nil, @"Failed to create secure channel factory"); if (factory == nil) { NSLog(@"Error creating secure channel factory: %@", error); } @@ -114,8 +114,8 @@ [NSNumber numberWithUnsignedInteger:(NSUInteger)(_callOptions.keepaliveTimeout * 1000)]; } - if (_callOptions.retryEnabled == NO) { - args[@GRPC_ARG_ENABLE_RETRIES] = [NSNumber numberWithInt:_callOptions.retryEnabled]; + if (!_callOptions.retryEnabled) { + args[@GRPC_ARG_ENABLE_RETRIES] = [NSNumber numberWithInt:_callOptions.retryEnabled ? 1 : 0]; } if (_callOptions.connectMinTimeout > 0) { diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index d1f28ec9bfa..19ef4c93ac6 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -16,11 +16,6 @@ * */ -/** - * Signature for the channel. If two channel's signatures are the same, they share the same - * underlying \a GRPCChannel object. - */ - #import #import "GRPCChannelFactory.h" @@ -35,10 +30,10 @@ NS_ASSUME_NONNULL_BEGIN @class GRPCWrappedCall; /** - * A proxied channel object that can be retained and creates GRPCWrappedCall object from. If a - * raw channel is not present (i.e. no tcp connection to the server) when a GRPCWrappedCall object - * is requested, it issues a connection/reconnection. The behavior of this object is to mimic that - * of gRPC core's channel object. + * A proxied channel object that can be retained and used to create GRPCWrappedCall object + * regardless of the current connection status. If a connection is not established when a + * GRPCWrappedCall object is requested, it issues a connection/reconnection. This behavior is to + * follow that of gRPC core's channel object. */ @interface GRPCPooledChannel : NSObject diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 349bdd44a65..17c74e558b4 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -27,7 +27,6 @@ #import "GRPCCronetChannelFactory.h" #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" -#import "utilities.h" #import "version.h" #import "GRPCWrappedCall.h" #import "GRPCCompletionQueue.h" @@ -57,6 +56,34 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; return [self initWithChannelConfiguration:channelConfiguration destroyDelay:kDefaultChannelDestroyDelay]; } +- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration + destroyDelay:(NSTimeInterval)destroyDelay { + NSAssert(channelConfiguration != nil, @"channelConfiguration cannot be empty."); + if (channelConfiguration == nil) { + return nil; + } + + if ((self = [super init])) { + _channelConfiguration = [channelConfiguration copy]; + _destroyDelay = destroyDelay; + _wrappedCalls = [NSHashTable weakObjectsHashTable]; + _wrappedChannel = nil; + _lastTimedDestroy = nil; +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + if (@available(iOS 8.0, macOS 10.10, *)) { + _timerQueue = dispatch_queue_create(NULL, + dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); + } else { +#else + { +#endif + _timerQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + } + } + + return self; +} + - (void)dealloc { // Disconnect GRPCWrappedCall objects created but not yet removed if (_wrappedCalls.allObjects.count != 0) { @@ -67,12 +94,14 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } - (GRPCWrappedCall *)wrappedCallWithPath:(NSString *)path -completionQueue:(GRPCCompletionQueue *)queue -callOptions:(GRPCCallOptions *)callOptions { + completionQueue:(GRPCCompletionQueue *)queue + callOptions:(GRPCCallOptions *)callOptions { NSAssert(path.length > 0, @"path must not be empty."); NSAssert(queue != nil, @"completionQueue must not be empty."); NSAssert(callOptions, @"callOptions must not be empty."); - if (path.length == 0 || queue == nil || callOptions == nil) return nil; + if (path.length == 0 || queue == nil || callOptions == nil) { + return nil; + } GRPCWrappedCall *call = nil; @@ -97,6 +126,7 @@ callOptions:(GRPCCallOptions *)callOptions { call = [[GRPCWrappedCall alloc] initWithUnmanagedCall:unmanagedCall pooledChannel:self]; if (call == nil) { NSAssert(call != nil, @"Unable to create GRPCWrappedCall object"); + grpc_call_unref(unmanagedCall); return nil; } @@ -111,16 +141,22 @@ callOptions:(GRPCCallOptions *)callOptions { return; } @synchronized(self) { - // Detect if all objects weakly referenced in _wrappedCalls are (implicitly) removed. In such - // case the channel is no longer referenced by a grpc_call object and can be destroyed after - // a certain delay. + // Detect if all objects weakly referenced in _wrappedCalls are (implicitly) removed. + // _wrappedCalls.count does not work here since the hash table may include deallocated weak + // references. _wrappedCalls.allObjects forces removal of those objects. if (_wrappedCalls.allObjects.count == 0) { + // No more call has reference to this channel. We may start the timer for destroying the + // channel now. NSDate *now = [NSDate date]; NSAssert(now != nil, @"Unable to create NSDate object 'now'."); _lastTimedDestroy = now; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)_destroyDelay * NSEC_PER_SEC), _timerQueue, ^{ @synchronized(self) { + // Check _lastTimedDestroy against now in case more calls are created (and + // maybe destroyed) after this dispatch_async. In that case the current + // dispatch_after block should be discarded; the channel should be + // destroyed in a later dispatch_after block. if (now != nil && self->_lastTimedDestroy == now) { self->_wrappedChannel = nil; self->_lastTimedDestroy = nil; @@ -145,38 +181,6 @@ callOptions:(GRPCCallOptions *)callOptions { } } -@end - -@implementation GRPCPooledChannel (Test) - -- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration - destroyDelay:(NSTimeInterval)destroyDelay { - NSAssert(channelConfiguration != nil, @"channelConfiguration cannot be empty."); - if (channelConfiguration == nil) { - return nil; - } - - if ((self = [super init])) { - _channelConfiguration = [channelConfiguration copy]; - _destroyDelay = destroyDelay; - _wrappedCalls = [NSHashTable weakObjectsHashTable]; - _wrappedChannel = nil; - _lastTimedDestroy = nil; -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 - if (@available(iOS 8.0, macOS 10.10, *)) { - _timerQueue = dispatch_queue_create(NULL, - dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); - } else { -#else - { -#endif - _timerQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); - } - } - - return self; -} - - (GRPCChannel *)wrappedChannel { GRPCChannel *channel = nil; @synchronized(self) { diff --git a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m index 0aeb67b1426..5bcb021dc4b 100644 --- a/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCCronetChannelFactory.m @@ -40,8 +40,8 @@ } - (instancetype)initWithEngine:(stream_engine *)engine { + NSAssert(engine != NULL, @"Cronet engine cannot be empty."); if (!engine) { - [NSException raise:NSInvalidArgumentException format:@"Cronet engine is NULL. Set it first."]; return nil; } if ((self = [super init])) { @@ -65,14 +65,12 @@ @implementation GRPCCronetChannelFactory + (instancetype)sharedInstance { - [NSException raise:NSInvalidArgumentException - format:@"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."]; + NSAssert(NO, @"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."); return nil; } - (grpc_channel *)createChannelWithHost:(NSString *)host channelArgs:(NSDictionary *)args { - [NSException raise:NSInvalidArgumentException - format:@"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."]; + NSAssert(NO, @"Must enable macro GRPC_COMPILE_WITH_CRONET to build Cronet channel."); return NULL; } diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index 0f2281ede85..e7a7460221f 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -32,7 +32,6 @@ #import "GRPCCronetChannelFactory.h" #import "GRPCSecureChannelFactory.h" #import "NSDictionary+GRPC.h" -#import "utilities.h" #import "version.h" NS_ASSUME_NONNULL_BEGIN @@ -42,7 +41,7 @@ static NSMutableDictionary *gHostCache; @implementation GRPCHost { NSString *_PEMRootCertificates; NSString *_PEMPrivateKey; - NSString *_pemCertChain; + NSString *_PEMCertificateChain; } + (nullable instancetype)hostWithAddress:(NSString *)address { @@ -96,7 +95,7 @@ static NSMutableDictionary *gHostCache; error:(NSError **)errorPtr { _PEMRootCertificates = [pemRootCerts copy]; _PEMPrivateKey = [pemPrivateKey copy]; - _pemCertChain = [pemCertChain copy]; + _PEMCertificateChain = [pemCertChain copy]; return YES; } @@ -113,7 +112,7 @@ static NSMutableDictionary *gHostCache; options.connectMaxBackoff = (NSTimeInterval)_maxConnectBackoff / 1000; options.PEMRootCertificates = _PEMRootCertificates; options.PEMPrivateKey = _PEMPrivateKey; - options.PEMCertChain = _pemCertChain; + options.PEMCertificateChain = _PEMCertificateChain; options.hostNameOverride = _hostNameOverride; #ifdef GRPC_COMPILE_WITH_CRONET // By old API logic, insecure channel precedes Cronet channel; Cronet channel preceeds default diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 69f70de17d1..3ccc70a7448 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -22,7 +22,6 @@ #import "ChannelArgsUtil.h" #import "GRPCChannel.h" -#import "utilities.h" @implementation GRPCSecureChannelFactory { grpc_channel_credentials *_channelCreds; @@ -116,6 +115,10 @@ } - (grpc_channel *)createChannelWithHost:(NSString *)host channelArgs:(NSDictionary *)args { + NSAssert(host.length != 0, @"host cannot be empty"); + if (host.length == 0) { + return NULL; + } grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs([args copy]); grpc_channel *unmanagedChannel = grpc_secure_channel_create(_channelCreds, host.UTF8String, coreChannelArgs, NULL); diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 727c9e0a88e..82149e3dba5 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -30,7 +30,6 @@ #import "NSData+GRPC.h" #import "NSDictionary+GRPC.h" #import "NSError+GRPC.h" -#import "utilities.h" #import "GRPCOpBatchLog.h" @@ -237,6 +236,7 @@ #pragma mark GRPCWrappedCall @implementation GRPCWrappedCall { + // pooledChannel holds weak reference to this object so this is ok GRPCPooledChannel *_pooledChannel; grpc_call *_call; } @@ -275,8 +275,7 @@ for (GRPCOperation *operation in operations) { ops_array[i++] = operation.op; } - grpc_call_error error; - error = grpc_call_start_batch(_call, ops_array, nops, (__bridge_retained void *)(^(bool success) { + grpc_call_error error = grpc_call_start_batch(_call, ops_array, nops, (__bridge_retained void *)(^(bool success) { if (!success) { if (errorHandler) { errorHandler(); @@ -291,11 +290,7 @@ 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]; - } + NSAssert(error == GRPC_CALL_OK, @"Error starting a batch of operations: %i", error); } } } diff --git a/src/objective-c/GRPCClient/private/utilities.h b/src/objective-c/GRPCClient/private/utilities.h deleted file mode 100644 index 8e3dd793586..00000000000 --- a/src/objective-c/GRPCClient/private/utilities.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#import - -/** Raise exception when condition not met. */ -#define GRPCAssert(condition, errorString) NSAssert(condition, errorString) From 1a9404876ce0315fc05fe82465dc389600db0965 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 6 Dec 2018 19:07:25 -0800 Subject: [PATCH 217/375] batch fixes --- src/objective-c/GRPCClient/private/GRPCChannel.m | 16 ++++++---------- src/objective-c/GRPCClient/private/GRPCHost.m | 2 +- src/objective-c/ProtoRPC/ProtoRPC.m | 15 ++++++++------- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index edcedf6e24f..12acfa14295 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -50,16 +50,17 @@ } - (id)channelFactory { - NSError *error; - id factory; GRPCTransportType type = _callOptions.transportType; switch (type) { case GRPCTransportTypeChttp2BoringSSL: // TODO (mxyan): Remove when the API is deprecated #ifdef GRPC_COMPILE_WITH_CRONET if (![GRPCCall isUsingCronet]) { +#else + { #endif - factory = [GRPCSecureChannelFactory + NSError *error; + id factory = [GRPCSecureChannelFactory factoryWithPEMRootCertificates:_callOptions.PEMRootCertificates privateKey:_callOptions.PEMPrivateKey certChain:_callOptions.PEMCertificateChain @@ -69,9 +70,7 @@ NSLog(@"Error creating secure channel factory: %@", error); } return factory; -#ifdef GRPC_COMPILE_WITH_CRONET } -#endif // fallthrough case GRPCTransportTypeCronet: return [GRPCCronetChannelFactory sharedInstance]; @@ -164,7 +163,7 @@ } - (NSUInteger)hash { - NSUInteger result = 0; + NSUInteger result = 31; result ^= _host.hash; result ^= _callOptions.channelOptionsHash; @@ -230,10 +229,7 @@ NSTimeInterval timeout = callOptions.timeout; NSAssert(timeout >= 0, @"Invalid timeout"); if (timeout < 0) return NULL; - grpc_slice host_slice = grpc_empty_slice(); - if (serverAuthority) { - host_slice = grpc_slice_from_copied_string(serverAuthority.UTF8String); - } + grpc_slice host_slice = serverAuthority ? grpc_slice_from_copied_string(serverAuthority.UTF8String) : grpc_empty_slice(); grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); gpr_timespec deadline_ms = timeout == 0 ? gpr_inf_future(GPR_CLOCK_REALTIME) diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index e7a7460221f..24348c3aed7 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -75,7 +75,7 @@ static NSMutableDictionary *gHostCache; } if ((self = [super init])) { - _address = address; + _address = [address copy]; _retryEnabled = YES; gHostCache[address] = self; } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 0f63f72f536..89f0b3f3473 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -97,14 +97,13 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing responseHandler:(id)handler callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass { - if (requestOptions.host.length == 0 || requestOptions.path.length == 0) { - [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; - } - if (requestOptions.safety > GRPCCallSafetyCacheableRequest) { - [NSException raise:NSInvalidArgumentException format:@"Invalid call safety value."]; + NSAssert(requestOptions.host.length != 0 && requestOptions.path.length != 0 && requestOptions.safety <= GRPCCallSafetyCacheableRequest, @"Invalid callOptions."); + NSAssert(handler != nil, @"handler cannot be empty."); + if (requestOptions.host.length == 0 || requestOptions.path.length == 0 || requestOptions.safety > GRPCCallSafetyCacheableRequest) { + return nil; } if (handler == nil) { - [NSException raise:NSInvalidArgumentException format:@"Response handler required."]; + return nil; } if ((self = [super init])) { @@ -166,8 +165,10 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } - (void)writeMessage:(GPBMessage *)message { + NSAssert([message isKindOfClass:[GPBMessage class]]); if (![message isKindOfClass:[GPBMessage class]]) { - [NSException raise:NSInvalidArgumentException format:@"Data must be a valid protobuf type."]; + NSLog(@"Failed to send a message that is non-proto."); + return; } GRPCCall2 *call; From f0f6e03212837c67d7e078e6f33074e80aa4bcc0 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 6 Dec 2018 22:41:03 -0800 Subject: [PATCH 218/375] clang-format --- src/objective-c/GRPCClient/GRPCCall.h | 2 +- src/objective-c/GRPCClient/GRPCCall.m | 19 ++--- src/objective-c/GRPCClient/GRPCCallOptions.m | 8 +- .../GRPCClient/private/GRPCChannel.m | 6 +- .../GRPCClient/private/GRPCChannelPool+Test.h | 4 +- .../GRPCClient/private/GRPCChannelPool.h | 2 +- .../GRPCClient/private/GRPCChannelPool.m | 26 ++++--- .../GRPCClient/private/GRPCWrappedCall.h | 2 +- .../GRPCClient/private/GRPCWrappedCall.m | 35 ++++----- src/objective-c/ProtoRPC/ProtoRPC.m | 24 +++--- .../tests/ChannelTests/ChannelTests.m | 49 +++++-------- src/objective-c/tests/InteropTests.m | 73 ++++++++++--------- 12 files changed, 127 insertions(+), 123 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index be63de1af9b..b549f5d2bf3 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -181,7 +181,7 @@ extern NSString *const kGRPCTrailersKey; * error descriptions. */ - (void)didCloseWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata - error:(nullable NSError *)error; + error:(nullable NSError *)error; @end diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index e56cc72149c..589b52031a7 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -28,6 +28,8 @@ #include #import "GRPCCallOptions.h" +#import "private/GRPCChannelPool.h" +#import "private/GRPCCompletionQueue.h" #import "private/GRPCConnectivityMonitor.h" #import "private/GRPCHost.h" #import "private/GRPCRequestHeaders.h" @@ -35,8 +37,6 @@ #import "private/NSData+GRPC.h" #import "private/NSDictionary+GRPC.h" #import "private/NSError+GRPC.h" -#import "private/GRPCChannelPool.h" -#import "private/GRPCCompletionQueue.h" // At most 6 ops can be in an op batch for a client: SEND_INITIAL_METADATA, // SEND_MESSAGE, SEND_CLOSE_FROM_CLIENT, RECV_INITIAL_METADATA, RECV_MESSAGE, @@ -259,12 +259,12 @@ const char *kCFStreamVarName = "grpc_cfstream"; } [copiedHandler didCloseWithTrailingMetadata:nil - error:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeCancelled - userInfo:@{ - NSLocalizedDescriptionKey : - @"Canceled by app" - }]]; + error:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeCancelled + userInfo:@{ + NSLocalizedDescriptionKey : + @"Canceled by app" + }]]; }); } else { _handler = nil; @@ -819,7 +819,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; _responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable dispatchQueue:_responseQueue]; - GRPCPooledChannel *channel = [[GRPCChannelPool sharedInstance] channelWithHost:_host callOptions:_callOptions]; + GRPCPooledChannel *channel = + [[GRPCChannelPool sharedInstance] channelWithHost:_host callOptions:_callOptions]; GRPCWrappedCall *wrappedCall = [channel wrappedCallWithPath:_path completionQueue:[GRPCCompletionQueue completionQueue] callOptions:_callOptions]; diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index 1962ad8956d..d3440ee6c07 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -233,7 +233,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { copyItems:YES] PEMRootCertificates:[_PEMRootCertificates copy] PEMPrivateKey:[_PEMPrivateKey copy] - PEMCertificateChain:[_PEMCertificateChain copy] + PEMCertificateChain:[_PEMCertificateChain copy] transportType:_transportType hostNameOverride:[_hostNameOverride copy] logContext:_logContext @@ -336,7 +336,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { additionalChannelArgs:kDefaultAdditionalChannelArgs PEMRootCertificates:kDefaultPEMRootCertificates PEMPrivateKey:kDefaultPEMPrivateKey - PEMCertificateChain:kDefaultPEMCertificateChain + PEMCertificateChain:kDefaultPEMCertificateChain transportType:kDefaultTransportType hostNameOverride:kDefaultHostNameOverride logContext:kDefaultLogContext @@ -363,7 +363,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { additionalChannelArgs:_additionalChannelArgs PEMRootCertificates:_PEMRootCertificates PEMPrivateKey:_PEMPrivateKey - PEMCertificateChain:_PEMCertificateChain + PEMCertificateChain:_PEMCertificateChain transportType:_transportType hostNameOverride:_hostNameOverride logContext:_logContext @@ -391,7 +391,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { additionalChannelArgs:[_additionalChannelArgs copy] PEMRootCertificates:_PEMRootCertificates PEMPrivateKey:_PEMPrivateKey - PEMCertificateChain:_PEMCertificateChain + PEMCertificateChain:_PEMCertificateChain transportType:_transportType hostNameOverride:_hostNameOverride logContext:_logContext diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index 12acfa14295..1a79fb04a0d 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -57,7 +57,7 @@ #ifdef GRPC_COMPILE_WITH_CRONET if (![GRPCCall isUsingCronet]) { #else - { + { #endif NSError *error; id factory = [GRPCSecureChannelFactory @@ -229,7 +229,9 @@ NSTimeInterval timeout = callOptions.timeout; NSAssert(timeout >= 0, @"Invalid timeout"); if (timeout < 0) return NULL; - grpc_slice host_slice = serverAuthority ? grpc_slice_from_copied_string(serverAuthority.UTF8String) : grpc_empty_slice(); + grpc_slice host_slice = serverAuthority + ? grpc_slice_from_copied_string(serverAuthority.UTF8String) + : grpc_empty_slice(); grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String); gpr_timespec deadline_ms = timeout == 0 ? gpr_inf_future(GPR_CLOCK_REALTIME) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool+Test.h b/src/objective-c/GRPCClient/private/GRPCChannelPool+Test.h index 4e7c988585d..ca0cc51a52c 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool+Test.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool+Test.h @@ -25,7 +25,7 @@ * Initialize a pooled channel with non-default destroy delay for testing purpose. */ - (nullable instancetype)initWithChannelConfiguration: -(GRPCChannelConfiguration *)channelConfiguration + (GRPCChannelConfiguration *)channelConfiguration destroyDelay:(NSTimeInterval)destroyDelay; /** @@ -45,5 +45,3 @@ - (nullable instancetype)initTestPool; @end - - diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index 19ef4c93ac6..d3a99ca8263 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -45,7 +45,7 @@ NS_ASSUME_NONNULL_BEGIN * Initialize with an actual channel object \a channel and a reference to the channel pool. */ - (nullable instancetype)initWithChannelConfiguration: - (GRPCChannelConfiguration *)channelConfiguration; + (GRPCChannelConfiguration *)channelConfiguration; /** * Create a GRPCWrappedCall object (grpc_call) from this channel. If channel is disconnected, get a diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index 17c74e558b4..a323f0490c8 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -21,15 +21,15 @@ #import "../internal/GRPCCallOptions+Internal.h" #import "GRPCChannel.h" #import "GRPCChannelFactory.h" -#import "GRPCChannelPool.h" #import "GRPCChannelPool+Test.h" +#import "GRPCChannelPool.h" +#import "GRPCCompletionQueue.h" #import "GRPCConnectivityMonitor.h" #import "GRPCCronetChannelFactory.h" #import "GRPCInsecureChannelFactory.h" #import "GRPCSecureChannelFactory.h" -#import "version.h" #import "GRPCWrappedCall.h" -#import "GRPCCompletionQueue.h" +#import "version.h" #import #include @@ -53,10 +53,12 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } - (instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration { - return [self initWithChannelConfiguration:channelConfiguration destroyDelay:kDefaultChannelDestroyDelay]; + return [self initWithChannelConfiguration:channelConfiguration + destroyDelay:kDefaultChannelDestroyDelay]; } -- (nullable instancetype)initWithChannelConfiguration:(GRPCChannelConfiguration *)channelConfiguration +- (nullable instancetype)initWithChannelConfiguration: + (GRPCChannelConfiguration *)channelConfiguration destroyDelay:(NSTimeInterval)destroyDelay { NSAssert(channelConfiguration != nil, @"channelConfiguration cannot be empty."); if (channelConfiguration == nil) { @@ -71,8 +73,8 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; _lastTimedDestroy = nil; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 if (@available(iOS 8.0, macOS 10.10, *)) { - _timerQueue = dispatch_queue_create(NULL, - dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); + _timerQueue = dispatch_queue_create(NULL, dispatch_queue_attr_make_with_qos_class( + DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0)); } else { #else { @@ -115,9 +117,10 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; } _lastTimedDestroy = nil; - grpc_call *unmanagedCall = [_wrappedChannel unmanagedCallWithPath:path - completionQueue:[GRPCCompletionQueue completionQueue] - callOptions:callOptions]; + grpc_call *unmanagedCall = + [_wrappedChannel unmanagedCallWithPath:path + completionQueue:[GRPCCompletionQueue completionQueue] + callOptions:callOptions]; if (unmanagedCall == NULL) { NSAssert(unmanagedCall != NULL, @"Unable to create grpc_call object"); return nil; @@ -203,8 +206,7 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; + (instancetype)sharedInstance { dispatch_once(&gInitChannelPool, ^{ - gChannelPool = - [[GRPCChannelPool alloc] initPrivate]; + gChannelPool = [[GRPCChannelPool alloc] initPrivate]; NSAssert(gChannelPool != nil, @"Cannot initialize global channel pool."); }); return gChannelPool; diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h index 0432190528f..92bd1be2570 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h @@ -77,7 +77,7 @@ - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)new NS_UNAVAILABLE; ++ (instancetype) new NS_UNAVAILABLE; - (instancetype)initWithUnmanagedCall:(grpc_call *)unmanagedCall pooledChannel:(GRPCPooledChannel *)pooledChannel NS_DESIGNATED_INITIALIZER; diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 82149e3dba5..9066cb950f4 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -267,7 +267,7 @@ [GRPCOpBatchLog addOpBatchToLog:operations]; #endif - @synchronized (self) { + @synchronized(self) { if (_call != NULL) { size_t nops = operations.count; grpc_op *ops_array = gpr_malloc(nops * sizeof(grpc_op)); @@ -275,19 +275,20 @@ 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); NSAssert(error == GRPC_CALL_OK, @"Error starting a batch of operations: %i", error); @@ -296,7 +297,7 @@ } - (void)cancel { - @synchronized (self) { + @synchronized(self) { if (_call != NULL) { grpc_call_cancel(_call, NULL); } @@ -304,7 +305,7 @@ } - (void)channelDisconnected { - @synchronized (self) { + @synchronized(self) { if (_call != NULL) { grpc_call_unref(_call); _call = NULL; @@ -313,7 +314,7 @@ } - (void)dealloc { - @synchronized (self) { + @synchronized(self) { if (_call != NULL) { grpc_call_unref(_call); _call = NULL; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 89f0b3f3473..da534351780 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -97,9 +97,12 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing responseHandler:(id)handler callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass { - NSAssert(requestOptions.host.length != 0 && requestOptions.path.length != 0 && requestOptions.safety <= GRPCCallSafetyCacheableRequest, @"Invalid callOptions."); + NSAssert(requestOptions.host.length != 0 && requestOptions.path.length != 0 && + requestOptions.safety <= GRPCCallSafetyCacheableRequest, + @"Invalid callOptions."); NSAssert(handler != nil, @"handler cannot be empty."); - if (requestOptions.host.length == 0 || requestOptions.path.length == 0 || requestOptions.safety > GRPCCallSafetyCacheableRequest) { + if (requestOptions.host.length == 0 || requestOptions.path.length == 0 || + requestOptions.safety > GRPCCallSafetyCacheableRequest) { return nil; } if (handler == nil) { @@ -150,12 +153,12 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing self->_handler = nil; } [copiedHandler didCloseWithTrailingMetadata:nil - error:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeCancelled - userInfo:@{ - NSLocalizedDescriptionKey : - @"Canceled by app" - }]]; + error:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeCancelled + userInfo:@{ + NSLocalizedDescriptionKey : + @"Canceled by app" + }]]; }); } else { _handler = nil; @@ -223,8 +226,9 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing copiedHandler = self->_handler; self->_handler = nil; } - [copiedHandler didCloseWithTrailingMetadata:nil - error:ErrorForBadProto(message, _responseClass, error)]; + [copiedHandler + didCloseWithTrailingMetadata:nil + error:ErrorForBadProto(message, _responseClass, error)]; }); [_call cancel]; _call = nil; diff --git a/src/objective-c/tests/ChannelTests/ChannelTests.m b/src/objective-c/tests/ChannelTests/ChannelTests.m index 7c80868c2c9..df78e8b1162 100644 --- a/src/objective-c/tests/ChannelTests/ChannelTests.m +++ b/src/objective-c/tests/ChannelTests/ChannelTests.m @@ -20,8 +20,8 @@ #import "../../GRPCClient/GRPCCallOptions.h" #import "../../GRPCClient/private/GRPCChannel.h" -#import "../../GRPCClient/private/GRPCChannelPool.h" #import "../../GRPCClient/private/GRPCChannelPool+Test.h" +#import "../../GRPCClient/private/GRPCChannelPool.h" #import "../../GRPCClient/private/GRPCCompletionQueue.h" #import "../../GRPCClient/private/GRPCWrappedCall.h" @@ -40,13 +40,12 @@ static NSString *kDummyPath = @"/dummy/path"; - (void)testPooledChannelCreatingChannel { GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCChannelConfiguration *config = [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost - callOptions:options]; + GRPCChannelConfiguration *config = + [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options]; GRPCPooledChannel *channel = [[GRPCPooledChannel alloc] initWithChannelConfiguration:config]; GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; - GRPCWrappedCall *wrappedCall = [channel wrappedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + GRPCWrappedCall *wrappedCall = + [channel wrappedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertNotNil(channel.wrappedChannel); (void)wrappedCall; } @@ -54,26 +53,22 @@ static NSString *kDummyPath = @"/dummy/path"; - (void)testTimedDestroyChannel { const NSTimeInterval kDestroyDelay = 1.0; GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCChannelConfiguration *config = [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost - callOptions:options]; - GRPCPooledChannel *channel = [[GRPCPooledChannel alloc] initWithChannelConfiguration:config - destroyDelay:kDestroyDelay]; + GRPCChannelConfiguration *config = + [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options]; + GRPCPooledChannel *channel = + [[GRPCPooledChannel alloc] initWithChannelConfiguration:config destroyDelay:kDestroyDelay]; GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; GRPCWrappedCall *wrappedCall; GRPCChannel *wrappedChannel; @autoreleasepool { - wrappedCall = [channel wrappedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + wrappedCall = [channel wrappedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertNotNil(channel.wrappedChannel); // Unref and ref channel immediately; expect using the same raw channel. wrappedChannel = channel.wrappedChannel; wrappedCall = nil; - wrappedCall = [channel wrappedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + wrappedCall = [channel wrappedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertEqual(channel.wrappedChannel, wrappedChannel); // Unref and ref channel after destroy delay; expect a new raw channel. @@ -81,23 +76,20 @@ static NSString *kDummyPath = @"/dummy/path"; } sleep(kDestroyDelay + 1); XCTAssertNil(channel.wrappedChannel); - wrappedCall = [channel wrappedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + wrappedCall = [channel wrappedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertNotEqual(channel.wrappedChannel, wrappedChannel); } - (void)testDisconnect { const NSTimeInterval kDestroyDelay = 1.0; GRPCCallOptions *options = [[GRPCCallOptions alloc] init]; - GRPCChannelConfiguration *config = [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost - callOptions:options]; - GRPCPooledChannel *channel = [[GRPCPooledChannel alloc] initWithChannelConfiguration:config - destroyDelay:kDestroyDelay]; + GRPCChannelConfiguration *config = + [[GRPCChannelConfiguration alloc] initWithHost:kDummyHost callOptions:options]; + GRPCPooledChannel *channel = + [[GRPCPooledChannel alloc] initWithChannelConfiguration:config destroyDelay:kDestroyDelay]; GRPCCompletionQueue *cq = [GRPCCompletionQueue completionQueue]; - GRPCWrappedCall *wrappedCall = [channel wrappedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + GRPCWrappedCall *wrappedCall = + [channel wrappedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertNotNil(channel.wrappedChannel); // Disconnect; expect wrapped channel to be dropped @@ -106,9 +98,8 @@ static NSString *kDummyPath = @"/dummy/path"; // Create a new call and unref the old call; confirm that destroy of the old call does not make // the channel disconnect, even after the destroy delay. - GRPCWrappedCall *wrappedCall2 = [channel wrappedCallWithPath:kDummyPath - completionQueue:cq - callOptions:options]; + GRPCWrappedCall *wrappedCall2 = + [channel wrappedCallWithPath:kDummyPath completionQueue:cq callOptions:options]; XCTAssertNotNil(channel.wrappedChannel); GRPCChannel *wrappedChannel = channel.wrappedChannel; wrappedCall = nil; diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index d17a07f929a..3665e9705d8 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -249,8 +249,10 @@ BOOL isRemoteInteropTest(NSString *host) { - (void)testLargeUnaryRPCWithV2API { XCTAssertNotNil([[self class] host]); - __weak XCTestExpectation *expectRecvMessage = [self expectationWithDescription:@"LargeUnaryWithV2API received message"]; - __weak XCTestExpectation *expectRecvComplete = [self expectationWithDescription:@"LargeUnaryWithV2API received complete"]; + __weak XCTestExpectation *expectRecvMessage = + [self expectationWithDescription:@"LargeUnaryWithV2API received message"]; + __weak XCTestExpectation *expectRecvComplete = + [self expectationWithDescription:@"LargeUnaryWithV2API received complete"]; RMTSimpleRequest *request = [RMTSimpleRequest message]; request.responseType = RMTPayloadType_Compressable; @@ -263,24 +265,26 @@ BOOL isRemoteInteropTest(NSString *host) { options.hostNameOverride = [[self class] hostNameOverride]; GRPCUnaryProtoCall *call = [_service - unaryCallWithMessage:request - responseHandler:[[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil - messageCallback:^(id message) { - XCTAssertNotNil(message); - if (message) { - RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message]; - expectedResponse.payload.type = RMTPayloadType_Compressable; - expectedResponse.payload.body = [NSMutableData dataWithLength:314159]; - XCTAssertEqualObjects(message, expectedResponse); - - [expectRecvMessage fulfill]; - } - } - closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { - XCTAssertNil(error, @"Unexpected error: %@", error); - [expectRecvComplete fulfill]; - }] - callOptions:options]; + unaryCallWithMessage:request + responseHandler:[[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil + messageCallback:^(id message) { + XCTAssertNotNil(message); + if (message) { + RMTSimpleResponse *expectedResponse = + [RMTSimpleResponse message]; + expectedResponse.payload.type = RMTPayloadType_Compressable; + expectedResponse.payload.body = + [NSMutableData dataWithLength:314159]; + XCTAssertEqualObjects(message, expectedResponse); + + [expectRecvMessage fulfill]; + } + } + closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { + XCTAssertNil(error, @"Unexpected error: %@", error); + [expectRecvComplete fulfill]; + }] + callOptions:options]; [call start]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; } @@ -602,7 +606,8 @@ BOOL isRemoteInteropTest(NSString *host) { - (void)testCancelAfterBeginRPCWithV2API { XCTAssertNotNil([[self class] host]); - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterBeginWithV2API"]; + __weak XCTestExpectation *expectation = + [self expectationWithDescription:@"CancelAfterBeginWithV2API"]; // A buffered pipe to which we never write any value acts as a writer that just hangs. __block GRPCStreamingProtoCall *call = [_service @@ -699,7 +704,7 @@ BOOL isRemoteInteropTest(NSString *host) { - (void)testCancelAfterFirstRequestWithV2API { XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *completionExpectation = - [self expectationWithDescription:@"Call completed."]; + [self expectationWithDescription:@"Call completed."]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; options.transportType = self.class.transportType; @@ -707,20 +712,20 @@ BOOL isRemoteInteropTest(NSString *host) { options.hostNameOverride = [[self class] hostNameOverride]; id request = - [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 requestedResponseSize:@31415]; + [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 requestedResponseSize:@31415]; __block GRPCStreamingProtoCall *call = [_service - fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] - initWithInitialMetadataCallback:nil - messageCallback:^(id message) { - XCTFail(@"Received unexpected response."); - } - closeCallback:^(NSDictionary *trailingMetadata, - NSError *error) { - XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); - [completionExpectation fulfill]; - }] - callOptions:options]; + fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] + initWithInitialMetadataCallback:nil + messageCallback:^(id message) { + XCTFail(@"Received unexpected response."); + } + closeCallback:^(NSDictionary *trailingMetadata, + NSError *error) { + XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); + [completionExpectation fulfill]; + }] + callOptions:options]; [call start]; [call writeMessage:request]; [call cancel]; From 92db5fc72488f9d62b81ee311a79832df787f3ef Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 7 Dec 2018 10:29:24 -0800 Subject: [PATCH 219/375] Rename getTokenWithHandler --- src/objective-c/GRPCClient/GRPCCall.m | 14 ++++++++++++-- src/objective-c/GRPCClient/GRPCCallOptions.h | 13 ++++++++++++- src/objective-c/ProtoRPC/ProtoRPC.m | 2 +- src/objective-c/tests/APIv2Tests/APIv2Tests.m | 2 +- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 589b52031a7..18f79311a69 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -885,7 +885,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; @synchronized(self) { self.isWaitingForToken = YES; } - [_callOptions.authTokenProvider getTokenWithHandler:^(NSString *token) { + void (^tokenHandler)(NSString *token) = ^(NSString *token) { @synchronized(self) { if (self.isWaitingForToken) { if (token) { @@ -895,7 +895,17 @@ const char *kCFStreamVarName = "grpc_cfstream"; self.isWaitingForToken = NO; } } - }]; + }; + id authTokenProvider = _callOptions.authTokenProvider; + if ([authTokenProvider respondsToSelector:@selector(provideTokenToHandler:)]) { + [_callOptions.authTokenProvider provideTokenToHandler:tokenHandler]; + } else { + NSAssert([authTokenProvider respondsToSelector:@selector(getTokenWithHandler:)], + @"authTokenProvider has no usable method"); + if ([authTokenProvider respondsToSelector:@selector(getTokenWithHandler:)]) { + [_callOptions.authTokenProvider getTokenWithHandler:tokenHandler]; + } + } } else { [self startCallWithWriteable:writeable]; } diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index 85786c74174..b7f08480dc0 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -58,13 +58,24 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { /** * Implement this protocol to provide a token to gRPC when a call is initiated. */ -@protocol GRPCAuthorizationProtocol +@protocol GRPCAuthorizationProtocol + +@optional + +/** + * This method is called when gRPC is about to start the call. When OAuth token is acquired, + * \a handler is expected to be called with \a token being the new token to be used for this call. + */ +- (void)provideTokenToHandler:(void (^_Nullable)(NSString *_Nullable token))handler; /** + * This method is deprecated. Please use \a provideTokenToHandler. + * * This method is called when gRPC is about to start the call. When OAuth token is acquired, * \a handler is expected to be called with \a token being the new token to be used for this call. */ - (void)getTokenWithHandler:(void (^_Nullable)(NSString *_Nullable token))handler; + @end @interface GRPCCallOptions : NSObject diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index da534351780..92d7fce33cc 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -168,7 +168,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } - (void)writeMessage:(GPBMessage *)message { - NSAssert([message isKindOfClass:[GPBMessage class]]); + NSAssert([message isKindOfClass:[GPBMessage class]], @"Parameter message must be a GPBMessage"); if (![message isKindOfClass:[GPBMessage class]]) { NSLog(@"Failed to send a message that is non-proto."); return; diff --git a/src/objective-c/tests/APIv2Tests/APIv2Tests.m b/src/objective-c/tests/APIv2Tests/APIv2Tests.m index ca7bf472830..fd472aafebd 100644 --- a/src/objective-c/tests/APIv2Tests/APIv2Tests.m +++ b/src/objective-c/tests/APIv2Tests/APIv2Tests.m @@ -241,7 +241,7 @@ static const NSTimeInterval kTestTimeout = 16; [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; } -- (void)getTokenWithHandler:(void (^)(NSString *token))handler { +- (void)provideTokenToHandler:(void (^)(NSString *token))handler { dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); dispatch_sync(queue, ^{ handler(@"test-access-token"); From 2e139e35fcaaabff7a21f85fc8e424ae39d0c586 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Fri, 30 Nov 2018 23:24:59 +0100 Subject: [PATCH 220/375] Bazel 0.20.0 workspace fixes. --- WORKSPACE | 2 ++ bazel/grpc_deps.bzl | 35 +++++++++++++++++++---------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index a547c24cbe2..c1e63d86e50 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,6 +1,8 @@ workspace(name="com_github_grpc_grpc") load("//bazel:grpc_deps.bzl", "grpc_deps", "grpc_test_only_deps") +load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") + grpc_deps() grpc_test_only_deps() diff --git a/bazel/grpc_deps.bzl b/bazel/grpc_deps.bzl index 86268178554..82aada24629 100644 --- a/bazel/grpc_deps.bzl +++ b/bazel/grpc_deps.bzl @@ -1,5 +1,8 @@ """Load dependencies needed to compile and test the grpc library as a 3rd-party consumer.""" +load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + def grpc_deps(): """Loads dependencies need to compile and test the grpc library.""" @@ -99,14 +102,14 @@ def grpc_deps(): ) if "boringssl" not in native.existing_rules(): - native.http_archive( + http_archive( name = "boringssl", # on the chromium-stable-with-bazel branch url = "https://boringssl.googlesource.com/boringssl/+archive/afc30d43eef92979b05776ec0963c9cede5fb80f.tar.gz", ) if "com_github_madler_zlib" not in native.existing_rules(): - native.new_http_archive( + http_archive( name = "com_github_madler_zlib", build_file = "@com_github_grpc_grpc//third_party:zlib.BUILD", strip_prefix = "zlib-cacf7f1d4e3d44d871b605da3b647f07d718623f", @@ -114,14 +117,14 @@ def grpc_deps(): ) if "com_google_protobuf" not in native.existing_rules(): - native.http_archive( + http_archive( name = "com_google_protobuf", strip_prefix = "protobuf-48cb18e5c419ddd23d9badcfe4e9df7bde1979b2", url = "https://github.com/google/protobuf/archive/48cb18e5c419ddd23d9badcfe4e9df7bde1979b2.tar.gz", ) if "com_github_nanopb_nanopb" not in native.existing_rules(): - native.new_http_archive( + http_archive( name = "com_github_nanopb_nanopb", build_file = "@com_github_grpc_grpc//third_party:nanopb.BUILD", strip_prefix = "nanopb-f8ac463766281625ad710900479130c7fcb4d63b", @@ -129,7 +132,7 @@ def grpc_deps(): ) if "com_github_google_googletest" not in native.existing_rules(): - native.new_http_archive( + http_archive( name = "com_github_google_googletest", build_file = "@com_github_grpc_grpc//third_party:gtest.BUILD", strip_prefix = "googletest-ec44c6c1675c25b9827aacd08c02433cccde7780", @@ -137,14 +140,14 @@ def grpc_deps(): ) if "com_github_gflags_gflags" not in native.existing_rules(): - native.http_archive( + http_archive( name = "com_github_gflags_gflags", strip_prefix = "gflags-30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e", url = "https://github.com/gflags/gflags/archive/30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e.tar.gz", ) if "com_github_google_benchmark" not in native.existing_rules(): - native.new_http_archive( + http_archive( name = "com_github_google_benchmark", build_file = "@com_github_grpc_grpc//third_party:benchmark.BUILD", strip_prefix = "benchmark-9913418d323e64a0111ca0da81388260c2bbe1e9", @@ -152,7 +155,7 @@ def grpc_deps(): ) if "com_github_cares_cares" not in native.existing_rules(): - native.new_http_archive( + http_archive( name = "com_github_cares_cares", build_file = "@com_github_grpc_grpc//third_party:cares/cares.BUILD", strip_prefix = "c-ares-3be1924221e1326df520f8498d704a5c4c8d0cce", @@ -160,14 +163,14 @@ def grpc_deps(): ) if "com_google_absl" not in native.existing_rules(): - native.http_archive( + http_archive( name = "com_google_absl", strip_prefix = "abseil-cpp-cd95e71df6eaf8f2a282b1da556c2cf1c9b09207", url = "https://github.com/abseil/abseil-cpp/archive/cd95e71df6eaf8f2a282b1da556c2cf1c9b09207.tar.gz", ) if "com_github_bazelbuild_bazeltoolchains" not in native.existing_rules(): - native.http_archive( + http_archive( name = "com_github_bazelbuild_bazeltoolchains", strip_prefix = "bazel-toolchains-280edaa6f93623074513d2b426068de42e62ea4d", urls = [ @@ -178,7 +181,7 @@ def grpc_deps(): ) if "io_opencensus_cpp" not in native.existing_rules(): - native.http_archive( + http_archive( name = "io_opencensus_cpp", strip_prefix = "opencensus-cpp-fdf0f308b1631bb4a942e32ba5d22536a6170274", url = "https://github.com/census-instrumentation/opencensus-cpp/archive/fdf0f308b1631bb4a942e32ba5d22536a6170274.tar.gz", @@ -200,7 +203,7 @@ def grpc_test_only_deps(): ) if "com_github_twisted_twisted" not in native.existing_rules(): - native.new_http_archive( + http_archive( name = "com_github_twisted_twisted", strip_prefix = "twisted-twisted-17.5.0", url = "https://github.com/twisted/twisted/archive/twisted-17.5.0.zip", @@ -208,7 +211,7 @@ def grpc_test_only_deps(): ) if "com_github_yaml_pyyaml" not in native.existing_rules(): - native.new_http_archive( + http_archive( name = "com_github_yaml_pyyaml", strip_prefix = "pyyaml-3.12", url = "https://github.com/yaml/pyyaml/archive/3.12.zip", @@ -216,7 +219,7 @@ def grpc_test_only_deps(): ) if "com_github_twisted_incremental" not in native.existing_rules(): - native.new_http_archive( + http_archive( name = "com_github_twisted_incremental", strip_prefix = "incremental-incremental-17.5.0", url = "https://github.com/twisted/incremental/archive/incremental-17.5.0.zip", @@ -224,7 +227,7 @@ def grpc_test_only_deps(): ) if "com_github_zopefoundation_zope_interface" not in native.existing_rules(): - native.new_http_archive( + http_archive( name = "com_github_zopefoundation_zope_interface", strip_prefix = "zope.interface-4.4.3", url = "https://github.com/zopefoundation/zope.interface/archive/4.4.3.zip", @@ -232,7 +235,7 @@ def grpc_test_only_deps(): ) if "com_github_twisted_constantly" not in native.existing_rules(): - native.new_http_archive( + http_archive( name = "com_github_twisted_constantly", strip_prefix = "constantly-15.1.0", url = "https://github.com/twisted/constantly/archive/15.1.0.zip", From d3d8a37a6bdfab94690b75af21c4a4c580c25716 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Sat, 1 Dec 2018 00:42:34 +0100 Subject: [PATCH 221/375] Fix sanity checker. --- tools/run_tests/sanity/check_bazel_workspace.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/run_tests/sanity/check_bazel_workspace.py b/tools/run_tests/sanity/check_bazel_workspace.py index d562fffc8a9..a34f61208e6 100755 --- a/tools/run_tests/sanity/check_bazel_workspace.py +++ b/tools/run_tests/sanity/check_bazel_workspace.py @@ -110,6 +110,8 @@ bazel_file += '\ngrpc_deps()\n' bazel_file += '\ngrpc_test_only_deps()\n' build_rules = { 'native': eval_state, + 'http_archive': lambda **args: eval_state.http_archive(**args), + 'load': lambda a, b: None, } exec bazel_file in build_rules for name in _GRPC_DEP_NAMES: @@ -149,6 +151,8 @@ for name in _GRPC_DEP_NAMES: names_and_urls_with_overridden_name, overridden_name=name) rules = { 'native': state, + 'http_archive': lambda **args: state.http_archive(**args), + 'load': lambda a, b: None, } exec bazel_file in rules assert name not in names_and_urls_with_overridden_name.keys() From df21aab3a6af360cff29a5164f9728ba646d35ab Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 7 Dec 2018 16:01:23 -0800 Subject: [PATCH 222/375] nullability annotation --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- src/objective-c/ProtoRPC/ProtoRPC.h | 18 ++++++------- src/objective-c/ProtoRPC/ProtoRPC.m | 3 +++ src/objective-c/ProtoRPC/ProtoService.h | 34 ++++++++++++++----------- src/objective-c/ProtoRPC/ProtoService.m | 7 ++--- src/objective-c/tests/GRPCClientTests.m | 3 ++- 6 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 18f79311a69..cfd0de1a8a2 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -485,7 +485,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; requestsWriter:(GRXWriter *)requestWriter callOptions:(GRPCCallOptions *)callOptions { // Purposely using pointer rather than length ([host length] == 0) for backwards compatibility. - NSAssert(host != nil && path != nil, @"Neither host nor path can be nil."); + NSAssert(host.length != 0 && path.length != 0, @"Neither host nor path can be nil."); NSAssert(safety <= GRPCCallSafetyCacheableRequest, @"Invalid call safety value."); NSAssert(requestWriter.state == GRXWriterStateNotStarted, @"The requests writer can't be already started."); diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 2e0400a323f..e6ba1f66ca5 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -70,11 +70,11 @@ NS_ASSUME_NONNULL_BEGIN * Users should not use this initializer directly. Call objects will be created, initialized, and * returned to users by methods of the generated service. */ -- (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions - message:(GPBMessage *)message - responseHandler:(id)handler - callOptions:(nullable GRPCCallOptions *)callOptions - responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions + message:(GPBMessage *)message + responseHandler:(id)handler + callOptions:(nullable GRPCCallOptions *)callOptions + responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; /** * Start the call. This function must only be called once for each instance. @@ -101,10 +101,10 @@ NS_ASSUME_NONNULL_BEGIN * Users should not use this initializer directly. Call objects will be created, initialized, and * returned to users by methods of the generated service. */ -- (instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions - responseHandler:(id)handler - callOptions:(nullable GRPCCallOptions *)callOptions - responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithRequestOptions:(GRPCRequestOptions *)requestOptions + responseHandler:(id)handler + callOptions:(nullable GRPCCallOptions *)callOptions + responseClass:(Class)responseClass NS_DESIGNATED_INITIALIZER; /** * Start the call. This function must only be called once for each instance. diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 92d7fce33cc..15b0f681ce3 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -57,6 +57,9 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing responseClass:(Class)responseClass { NSAssert(message != nil, @"message cannot be empty."); NSAssert(responseClass != nil, @"responseClass cannot be empty."); + if (message == nil || responseClass == nil) { + return nil; + } if ((self = [super init])) { _call = [[GRPCStreamingProtoCall alloc] initWithRequestOptions:requestOptions responseHandler:handler diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h index 2105de78a38..70423ee9def 100644 --- a/src/objective-c/ProtoRPC/ProtoService.h +++ b/src/objective-c/ProtoRPC/ProtoService.h @@ -27,33 +27,35 @@ @class GRPCStreamingProtoCall; @protocol GRPCProtoResponseCallbacks; +NS_ASSUME_NONNULL_BEGIN + __attribute__((deprecated("Please use GRPCProtoService."))) @interface ProtoService : NSObject - - (instancetype)initWithHost : (NSString *)host packageName + (nullable instancetype)initWithHost : (NSString *)host packageName : (NSString *)packageName serviceName : (NSString *)serviceName callOptions - : (GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; + : (nullable GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; - (instancetype)initWithHost:(NSString *)host packageName:(NSString *)packageName serviceName:(NSString *)serviceName; -- (GRPCProtoCall *)RPCToMethod:(NSString *)method - requestsWriter:(GRXWriter *)requestsWriter - responseClass:(Class)responseClass - responsesWriteable:(id)responsesWriteable; +- (nullable GRPCProtoCall *)RPCToMethod:(NSString *)method + requestsWriter:(GRXWriter *)requestsWriter + responseClass:(Class)responseClass + responsesWriteable:(id)responsesWriteable; -- (GRPCUnaryProtoCall *)RPCToMethod:(NSString *)method - message:(id)message - responseHandler:(id)handler - callOptions:(GRPCCallOptions *)callOptions - responseClass:(Class)responseClass; +- (nullable GRPCUnaryProtoCall *)RPCToMethod:(NSString *)method + message:(id)message + responseHandler:(id)handler + callOptions:(nullable GRPCCallOptions *)callOptions + responseClass:(Class)responseClass; -- (GRPCStreamingProtoCall *)RPCToMethod:(NSString *)method - responseHandler:(id)handler - callOptions:(GRPCCallOptions *)callOptions - responseClass:(Class)responseClass; +- (nullable GRPCStreamingProtoCall *)RPCToMethod:(NSString *)method + responseHandler:(id)handler + callOptions:(nullable GRPCCallOptions *)callOptions + responseClass:(Class)responseClass; @end @@ -67,3 +69,5 @@ __attribute__((deprecated("Please use GRPCProtoService."))) @interface ProtoServ #pragma clang diagnostic pop @end + + NS_ASSUME_NONNULL_END diff --git a/src/objective-c/ProtoRPC/ProtoService.m b/src/objective-c/ProtoRPC/ProtoService.m index 6df502fb0c0..3d998bfaeb8 100644 --- a/src/objective-c/ProtoRPC/ProtoService.m +++ b/src/objective-c/ProtoRPC/ProtoService.m @@ -44,9 +44,10 @@ packageName:(NSString *)packageName serviceName:(NSString *)serviceName callOptions:(GRPCCallOptions *)callOptions { - if (!host || !serviceName) { - [NSException raise:NSInvalidArgumentException - format:@"Neither host nor serviceName can be nil."]; + NSAssert(host.length != 0 && packageName.length != 0 && serviceName.length != 0, + @"Invalid parameter."); + if (host.length == 0 || packageName.length == 0 || serviceName.length == 0) { + return nil; } if ((self = [super init])) { _host = [host copy]; diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 2cfdd1a003b..b16720557f7 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -362,9 +362,10 @@ static GRPCProtoMethod *kFullDuplexCallMethod; // TODO(makarandd): Move to a different file that contains only unit tests - (void)testExceptions { + GRXWriter *writer = [GRXWriter writerWithValue:[NSData data]]; // Try to set parameters to nil for GRPCCall. This should cause an exception @try { - (void)[[GRPCCall alloc] initWithHost:nil path:nil requestsWriter:nil]; + (void)[[GRPCCall alloc] initWithHost:@"" path:@"" requestsWriter:writer]; XCTFail(@"Did not receive an exception when parameters are nil"); } @catch (NSException *theException) { NSLog(@"Received exception as expected: %@", theException.name); From 3f00d61b04874cc5f0159c16f2c598a8f2fb93a7 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 7 Dec 2018 16:12:00 -0800 Subject: [PATCH 223/375] batch fix --- .../GRPCClient/private/GRPCWrappedCall.m | 1 + src/objective-c/ProtoRPC/ProtoRPC.m | 18 +++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 9066cb950f4..4edd9d3e378 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -320,6 +320,7 @@ _call = NULL; } } + // Explicitly converting weak reference _pooledChannel to strong. __strong GRPCPooledChannel *channel = _pooledChannel; [channel notifyWrappedCallDealloc:self]; } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 15b0f681ce3..abf224c3cfd 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -140,7 +140,11 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } - (void)start { - [_call start]; + GRPCCall2 *copiedCall; + @synchronized(self) { + copiedCall = _call; + } + [copiedCall start]; } - (void)cancel { @@ -177,20 +181,20 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing return; } - GRPCCall2 *call; + GRPCCall2 *copiedCall; @synchronized(self) { - call = _call; + copiedCall = _call; } - [call writeData:[message data]]; + [copiedCall writeData:[message data]]; } - (void)finish { - GRPCCall2 *call; + GRPCCall2 *copiedCall; @synchronized(self) { - call = _call; + copiedCall = _call; _call = nil; } - [call finish]; + [copiedCall finish]; } - (void)didReceiveInitialMetadata:(NSDictionary *)initialMetadata { From eea5f1ad3dee4d96c9b86efe89f75c973cc57eed Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 10 Dec 2018 12:38:05 -0800 Subject: [PATCH 224/375] Missing nullable --- src/objective-c/GRPCClient/GRPCCall.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index b549f5d2bf3..4ef8cee36de 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -282,7 +282,7 @@ NS_ASSUME_NONNULL_END */ @interface GRPCCall : GRXWriter -- (instancetype)init NS_UNAVAILABLE; +- (nullable instancetype)init NS_UNAVAILABLE; /** * The container of the request headers of an RPC conforms to this protocol, which is a subset of From 20c8cc72920b14520160c4e2001caec2b8acddc0 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 10 Dec 2018 18:06:34 -0800 Subject: [PATCH 225/375] nullability failing --- src/objective-c/GRPCClient/private/GRPCChannelPool+Test.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool+Test.h b/src/objective-c/GRPCClient/private/GRPCChannelPool+Test.h index ca0cc51a52c..e2c3aee3d92 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool+Test.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool+Test.h @@ -18,6 +18,8 @@ #import "GRPCChannelPool.h" +NS_ASSUME_NONNULL_BEGIN + /** Test-only interface for \a GRPCPooledChannel. */ @interface GRPCPooledChannel (Test) @@ -31,7 +33,7 @@ /** * Return the pointer to the raw channel wrapped. */ -@property(atomic, readonly) GRPCChannel *wrappedChannel; +@property(atomic, readonly, nullable) GRPCChannel *wrappedChannel; @end @@ -45,3 +47,5 @@ - (nullable instancetype)initTestPool; @end + +NS_ASSUME_NONNULL_END From 3d7dce518dc048670cc22b5c19a0aaca69b479d7 Mon Sep 17 00:00:00 2001 From: Richard Belleville Date: Wed, 12 Dec 2018 09:38:44 -0800 Subject: [PATCH 226/375] Update urllib3 to avoid security vulnerability --- requirements.bazel.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.bazel.txt b/requirements.bazel.txt index 61e529a6ec8..7794aec752e 100644 --- a/requirements.bazel.txt +++ b/requirements.bazel.txt @@ -9,7 +9,7 @@ futures>=2.2.0 google-auth>=1.0.0 oauth2client==4.1.0 requests>=2.14.2 -urllib3==1.22 +urllib3>=1.23 chardet==3.0.4 certifi==2017.4.17 idna==2.7 From 031dfd970384245209b9e6a3b526806f04fa9a59 Mon Sep 17 00:00:00 2001 From: Srini Polavarapu Date: Wed, 12 Dec 2018 11:29:51 -0800 Subject: [PATCH 227/375] Bump version to 1.17.1 --- BUILD | 2 +- build.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILD b/BUILD index fb87e824bec..eafa89bbaac 100644 --- a/BUILD +++ b/BUILD @@ -68,7 +68,7 @@ g_stands_for = "gizmo" core_version = "7.0.0" -version = "1.17.1-pre1" +version = "1.17.1" GPR_PUBLIC_HDRS = [ "include/grpc/support/alloc.h", diff --git a/build.yaml b/build.yaml index df1fd85e050..946ffb34ecc 100644 --- a/build.yaml +++ b/build.yaml @@ -14,7 +14,7 @@ settings: '#10': See the expand_version.py for all the quirks here core_version: 7.0.0 g_stands_for: gizmo - version: 1.17.1-pre1 + version: 1.17.1 filegroups: - name: alts_proto headers: From a31ccd49e685b26514514f282798a9464433650b Mon Sep 17 00:00:00 2001 From: Srini Polavarapu Date: Wed, 12 Dec 2018 12:45:00 -0800 Subject: [PATCH 228/375] Regenerate projects --- CMakeLists.txt | 2 +- Makefile | 4 ++-- gRPC-C++.podspec | 6 +++--- gRPC-Core.podspec | 2 +- gRPC-ProtoRPC.podspec | 2 +- gRPC-RxLibrary.podspec | 2 +- gRPC.podspec | 2 +- package.xml | 8 ++++---- src/cpp/common/version_cc.cc | 2 +- src/csharp/Grpc.Core/Version.csproj.include | 2 +- src/csharp/Grpc.Core/VersionInfo.cs | 2 +- src/csharp/build_packages_dotnetcli.bat | 2 +- src/csharp/build_unitypackage.bat | 2 +- src/objective-c/!ProtoCompiler-gRPCPlugin.podspec | 2 +- src/objective-c/GRPCClient/private/version.h | 2 +- src/objective-c/tests/version.h | 2 +- src/php/ext/grpc/version.h | 2 +- src/python/grpcio/grpc/_grpcio_metadata.py | 2 +- src/python/grpcio/grpc_version.py | 2 +- src/python/grpcio_health_checking/grpc_version.py | 2 +- src/python/grpcio_reflection/grpc_version.py | 2 +- src/python/grpcio_testing/grpc_version.py | 2 +- src/python/grpcio_tests/grpc_version.py | 2 +- src/ruby/lib/grpc/version.rb | 2 +- src/ruby/tools/version.rb | 2 +- tools/distrib/python/grpcio_tools/grpc_version.py | 2 +- tools/doxygen/Doxyfile.c++ | 2 +- tools/doxygen/Doxyfile.c++.internal | 2 +- 28 files changed, 34 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c199696a9b..b39e6f8e885 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ cmake_minimum_required(VERSION 2.8) set(PACKAGE_NAME "grpc") -set(PACKAGE_VERSION "1.17.1-pre1") +set(PACKAGE_VERSION "1.17.1") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/") diff --git a/Makefile b/Makefile index 18f49301d76..736583fd936 100644 --- a/Makefile +++ b/Makefile @@ -438,8 +438,8 @@ Q = @ endif CORE_VERSION = 7.0.0 -CPP_VERSION = 1.17.1-pre1 -CSHARP_VERSION = 1.17.1-pre1 +CPP_VERSION = 1.17.1 +CSHARP_VERSION = 1.17.1 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index ba26e3979d6..65a3f5584d1 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -23,15 +23,15 @@ Pod::Spec.new do |s| s.name = 'gRPC-C++' # TODO (mxyan): use version that match gRPC version when pod is stabilized - # version = '1.17.1-pre1' - version = '0.0.6-pre1' + # version = '1.17.1' + version = '0.0.6' s.version = version s.summary = 'gRPC C++ library' s.homepage = 'https://grpc.io' s.license = 'Apache License, Version 2.0' s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } - grpc_version = '1.17.1-pre1' + grpc_version = '1.17.1' s.source = { :git => 'https://github.com/grpc/grpc.git', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 4b499208f5c..bf0d33ca3cc 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -22,7 +22,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-Core' - version = '1.17.1-pre1' + version = '1.17.1' s.version = version s.summary = 'Core cross-platform gRPC library, written in C' s.homepage = 'https://grpc.io' diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index 5d5bd6c47f5..c781ac12117 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-ProtoRPC' - version = '1.17.1-pre1' + version = '1.17.1' s.version = version s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.homepage = 'https://grpc.io' diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec index 9c453f0b192..e9a07fe0c0b 100644 --- a/gRPC-RxLibrary.podspec +++ b/gRPC-RxLibrary.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-RxLibrary' - version = '1.17.1-pre1' + version = '1.17.1' s.version = version s.summary = 'Reactive Extensions library for iOS/OSX.' s.homepage = 'https://grpc.io' diff --git a/gRPC.podspec b/gRPC.podspec index 83c7fceef1a..54420ae5cc8 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.name = 'gRPC' - version = '1.17.1-pre1' + version = '1.17.1' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'https://grpc.io' diff --git a/package.xml b/package.xml index 3e3d0c354c3..f1cfe0f6231 100644 --- a/package.xml +++ b/package.xml @@ -13,12 +13,12 @@ 2018-01-19 - 1.17.1RC1 - 1.17.1RC1 + 1.17.1 + 1.17.1 - beta - beta + stable + stable Apache 2.0 diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc index af717f9934f..94d10196ebb 100644 --- a/src/cpp/common/version_cc.cc +++ b/src/cpp/common/version_cc.cc @@ -22,5 +22,5 @@ #include namespace grpc { -grpc::string Version() { return "1.17.1-pre1"; } +grpc::string Version() { return "1.17.1"; } } // namespace grpc diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include index 1935ab77e4f..64a38f3f2d3 100755 --- a/src/csharp/Grpc.Core/Version.csproj.include +++ b/src/csharp/Grpc.Core/Version.csproj.include @@ -1,7 +1,7 @@ - 1.17.1-pre1 + 1.17.1 3.6.1 diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index 1209c509d03..3b7a76557da 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -38,6 +38,6 @@ namespace Grpc.Core /// /// Current version of gRPC C# /// - public const string CurrentVersion = "1.17.1-pre1"; + public const string CurrentVersion = "1.17.1"; } } diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index 996700b3e1e..42ed94f20a2 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -13,7 +13,7 @@ @rem limitations under the License. @rem Current package versions -set VERSION=1.17.1-pre1 +set VERSION=1.17.1 @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/csharp/build_unitypackage.bat b/src/csharp/build_unitypackage.bat index 2fec12ddf89..a3a096588ad 100644 --- a/src/csharp/build_unitypackage.bat +++ b/src/csharp/build_unitypackage.bat @@ -13,7 +13,7 @@ @rem limitations under the License. @rem Current package versions -set VERSION=1.17.1-pre1 +set VERSION=1.17.1 @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index 65524edad29..b68dde831bb 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' - v = '1.17.1-pre1' + v = '1.17.1' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h index 02d2c58a7d0..8da4d65a838 100644 --- a/src/objective-c/GRPCClient/private/version.h +++ b/src/objective-c/GRPCClient/private/version.h @@ -22,4 +22,4 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.17.1-pre1" +#define GRPC_OBJC_VERSION_STRING @"1.17.1" diff --git a/src/objective-c/tests/version.h b/src/objective-c/tests/version.h index 8c3e0da603f..65f9ad4912a 100644 --- a/src/objective-c/tests/version.h +++ b/src/objective-c/tests/version.h @@ -22,5 +22,5 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.17.1-pre1" +#define GRPC_OBJC_VERSION_STRING @"1.17.1" #define GRPC_C_VERSION_STRING @"7.0.0" diff --git a/src/php/ext/grpc/version.h b/src/php/ext/grpc/version.h index 9e79442157f..3ae5450748a 100644 --- a/src/php/ext/grpc/version.h +++ b/src/php/ext/grpc/version.h @@ -20,6 +20,6 @@ #ifndef VERSION_H #define VERSION_H -#define PHP_GRPC_VERSION "1.17.1RC1" +#define PHP_GRPC_VERSION "1.17.1" #endif /* VERSION_H */ diff --git a/src/python/grpcio/grpc/_grpcio_metadata.py b/src/python/grpcio/grpc/_grpcio_metadata.py index 63e56efa6b1..effc73ed79f 100644 --- a/src/python/grpcio/grpc/_grpcio_metadata.py +++ b/src/python/grpcio/grpc/_grpcio_metadata.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!! -__version__ = """1.17.1rc1""" +__version__ = """1.17.1""" diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index 03f7db3b2fe..382ed461715 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION = '1.17.1rc1' +VERSION = '1.17.1' diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py index c0817d51dce..62f4f394fce 100644 --- a/src/python/grpcio_health_checking/grpc_version.py +++ b/src/python/grpcio_health_checking/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! -VERSION = '1.17.1rc1' +VERSION = '1.17.1' diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py index 445513c6045..ab82077c478 100644 --- a/src/python/grpcio_reflection/grpc_version.py +++ b/src/python/grpcio_reflection/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!! -VERSION = '1.17.1rc1' +VERSION = '1.17.1' diff --git a/src/python/grpcio_testing/grpc_version.py b/src/python/grpcio_testing/grpc_version.py index 0c89e08dfbf..096f1d30fd3 100644 --- a/src/python/grpcio_testing/grpc_version.py +++ b/src/python/grpcio_testing/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!! -VERSION = '1.17.1rc1' +VERSION = '1.17.1' diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py index 5b861bc0c83..b3ec30934ab 100644 --- a/src/python/grpcio_tests/grpc_version.py +++ b/src/python/grpcio_tests/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!! -VERSION = '1.17.1rc1' +VERSION = '1.17.1' diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index 3af5e94a7d0..2d7b867937a 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -14,5 +14,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '1.17.1.pre1' + VERSION = '1.17.1' end diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index e27237158e0..68fba45b9b4 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -14,6 +14,6 @@ module GRPC module Tools - VERSION = '1.17.1.pre1' + VERSION = '1.17.1' end end diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py index 628315ad26e..a43a6ace9ee 100644 --- a/tools/distrib/python/grpcio_tools/grpc_version.py +++ b/tools/distrib/python/grpcio_tools/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! -VERSION = '1.17.1rc1' +VERSION = '1.17.1' diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index c32e6b34519..73658d16b7b 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.17.1-pre1 +PROJECT_NUMBER = 1.17.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index d62f540ce84..02c9e75e819 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.17.1-pre1 +PROJECT_NUMBER = 1.17.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a From 3fc5ca0c75aae97e9201df000a5afd5f628403b8 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 12 Dec 2018 14:30:12 -0800 Subject: [PATCH 229/375] batch fix --- .../GRPCClient/private/GRPCInsecureChannelFactory.m | 2 +- src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m | 2 +- src/objective-c/GRPCClient/private/GRPCWrappedCall.m | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m index b802137c13a..8ad1e848f55 100644 --- a/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCInsecureChannelFactory.m @@ -33,7 +33,7 @@ } - (grpc_channel *)createChannelWithHost:(NSString *)host channelArgs:(NSDictionary *)args { - grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs([args copy]); + grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs(args); grpc_channel *unmanagedChannel = grpc_insecure_channel_create(host.UTF8String, coreChannelArgs, NULL); GRPCFreeChannelArgs(coreChannelArgs); diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index 3ccc70a7448..96998895364 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -119,7 +119,7 @@ if (host.length == 0) { return NULL; } - grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs([args copy]); + grpc_channel_args *coreChannelArgs = GRPCBuildChannelArgs(args); grpc_channel *unmanagedChannel = grpc_secure_channel_create(_channelCreds, host.UTF8String, coreChannelArgs, NULL); GRPCFreeChannelArgs(coreChannelArgs); diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 4edd9d3e378..1a848a4b7c3 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -307,6 +307,10 @@ - (void)channelDisconnected { @synchronized(self) { if (_call != NULL) { + // Unreference the call will lead to its cancellation in the core. Note that since + // this function is only called with a network state change, any existing GRPCCall object will + // also receive the same notification and cancel themselves with GRPCErrorCodeUnavailable, so + // the user gets GRPCErrorCodeUnavailable in this case. grpc_call_unref(_call); _call = NULL; } From 0f4d465452552cfaf16367241c8894034d1f575a Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 12 Dec 2018 15:52:54 -0800 Subject: [PATCH 230/375] nit fix --- src/objective-c/GRPCClient/private/GRPCHost.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/private/GRPCHost.h b/src/objective-c/GRPCClient/private/GRPCHost.h index f1d57196424..ca3c52ea177 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.h +++ b/src/objective-c/GRPCClient/private/GRPCHost.h @@ -64,7 +64,7 @@ struct grpc_channel_credentials; withCertChain:(nullable NSString *)pemCertChain error:(NSError **)errorPtr; -@property(atomic, readwrite) GRPCTransportType transportType; +@property(atomic) GRPCTransportType transportType; + (GRPCCallOptions *)callOptionsForHost:(NSString *)host; From 827e84d0a4165e3e64d9ae0a1b8fbbaecdde0fa6 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 12 Dec 2018 17:21:30 -0800 Subject: [PATCH 231/375] Fix unused variable error --- src/objective-c/tests/Podfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile index 12112f95e14..8e5f588906b 100644 --- a/src/objective-c/tests/Podfile +++ b/src/objective-c/tests/Podfile @@ -150,7 +150,9 @@ post_install do |installer| end # Enable NSAssert on gRPC - if target.name == 'gRPC' || target.name == 'ProtoRPC' || target.name == 'RxLibrary' + if target.name == 'gRPC' || target.name.start_with?('gRPC.') || + target.name == 'ProtoRPC' || target.name.start_with?('ProtoRPC.') || + target.name == 'RxLibrary' || target.name.start_with?('RxLibrary.') target.build_configurations.each do |config| if config.name != 'Release' config.build_settings['ENABLE_NS_ASSERTIONS'] = 'YES' From 6f083e112c509e4ef964b90eb1c3654033123878 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 12 Dec 2018 17:43:52 -0800 Subject: [PATCH 232/375] revert pb files --- .../lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c | 4 ++-- src/core/tsi/alts/handshaker/altscontext.pb.c | 4 ++-- src/core/tsi/alts/handshaker/handshaker.pb.c | 4 ++-- src/core/tsi/alts/handshaker/transport_security_common.pb.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c index a7b072420ec..f6538e1349f 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c @@ -75,14 +75,14 @@ PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) #endif #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) -/* If you get an error here, it means that you need to define PB_FIELD_32BIT +/* If you get an error here, it means that you need to define PB_FIELD_16BIT * compile-time option. You can do that in pb.h or on compiler command line. * * The reason you need to do this is that some of your messages contain tag * numbers or field sizes that are larger than what can fit in the default * 8 bit descriptors. */ -PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 256 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v1_ServerList, servers) < 256), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) +PB_STATIC_ASSERT((pb_membersize(grpc_lb_v1_LoadBalanceRequest, initial_request) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceRequest, client_stats) < 256 && pb_membersize(grpc_lb_v1_ClientStats, timestamp) < 256 && pb_membersize(grpc_lb_v1_ClientStats, calls_finished_with_drop) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, initial_response) < 256 && pb_membersize(grpc_lb_v1_LoadBalanceResponse, server_list) < 256 && pb_membersize(grpc_lb_v1_InitialLoadBalanceResponse, client_stats_report_interval) < 256 && pb_membersize(grpc_lb_v1_ServerList, servers) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v1_LoadBalanceRequest_grpc_lb_v1_InitialLoadBalanceRequest_grpc_lb_v1_ClientStatsPerToken_grpc_lb_v1_ClientStats_grpc_lb_v1_LoadBalanceResponse_grpc_lb_v1_InitialLoadBalanceResponse_grpc_lb_v1_ServerList_grpc_lb_v1_Server) #endif diff --git a/src/core/tsi/alts/handshaker/altscontext.pb.c b/src/core/tsi/alts/handshaker/altscontext.pb.c index 2320edb1eff..5fb152a558e 100644 --- a/src/core/tsi/alts/handshaker/altscontext.pb.c +++ b/src/core/tsi/alts/handshaker/altscontext.pb.c @@ -33,14 +33,14 @@ PB_STATIC_ASSERT((pb_membersize(grpc_gcp_AltsContext, peer_rpc_versions) < 65536 #endif #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) -/* If you get an error here, it means that you need to define PB_FIELD_32BIT +/* If you get an error here, it means that you need to define PB_FIELD_16BIT * compile-time option. You can do that in pb.h or on compiler command line. * * The reason you need to do this is that some of your messages contain tag * numbers or field sizes that are larger than what can fit in the default * 8 bit descriptors. */ -PB_STATIC_ASSERT((pb_membersize(grpc_gcp_AltsContext, peer_rpc_versions) < 256), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_gcp_AltsContext) +PB_STATIC_ASSERT((pb_membersize(grpc_gcp_AltsContext, peer_rpc_versions) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_gcp_AltsContext) #endif diff --git a/src/core/tsi/alts/handshaker/handshaker.pb.c b/src/core/tsi/alts/handshaker/handshaker.pb.c index 8eda290e123..5450b1602d4 100644 --- a/src/core/tsi/alts/handshaker/handshaker.pb.c +++ b/src/core/tsi/alts/handshaker/handshaker.pb.c @@ -108,14 +108,14 @@ PB_STATIC_ASSERT((pb_membersize(grpc_gcp_StartClientHandshakeReq, target_identit #endif #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) -/* If you get an error here, it means that you need to define PB_FIELD_32BIT +/* If you get an error here, it means that you need to define PB_FIELD_16BIT * compile-time option. You can do that in pb.h or on compiler command line. * * The reason you need to do this is that some of your messages contain tag * numbers or field sizes that are larger than what can fit in the default * 8 bit descriptors. */ -PB_STATIC_ASSERT((pb_membersize(grpc_gcp_StartClientHandshakeReq, target_identities) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, local_identity) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, local_endpoint) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, remote_endpoint) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, rpc_versions) < 256 && pb_membersize(grpc_gcp_ServerHandshakeParameters, local_identities) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, handshake_parameters[0]) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, local_endpoint) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, remote_endpoint) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, rpc_versions) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry, value) < 256 && pb_membersize(grpc_gcp_HandshakerReq, client_start) < 256 && pb_membersize(grpc_gcp_HandshakerReq, server_start) < 256 && pb_membersize(grpc_gcp_HandshakerReq, next) < 256 && pb_membersize(grpc_gcp_HandshakerResult, peer_identity) < 256 && pb_membersize(grpc_gcp_HandshakerResult, local_identity) < 256 && pb_membersize(grpc_gcp_HandshakerResult, peer_rpc_versions) < 256 && pb_membersize(grpc_gcp_HandshakerResp, result) < 256 && pb_membersize(grpc_gcp_HandshakerResp, status) < 256), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_gcp_Endpoint_grpc_gcp_Identity_grpc_gcp_StartClientHandshakeReq_grpc_gcp_ServerHandshakeParameters_grpc_gcp_StartServerHandshakeReq_grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_grpc_gcp_NextHandshakeMessageReq_grpc_gcp_HandshakerReq_grpc_gcp_HandshakerResult_grpc_gcp_HandshakerStatus_grpc_gcp_HandshakerResp) +PB_STATIC_ASSERT((pb_membersize(grpc_gcp_StartClientHandshakeReq, target_identities) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, local_identity) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, local_endpoint) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, remote_endpoint) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, rpc_versions) < 256 && pb_membersize(grpc_gcp_ServerHandshakeParameters, local_identities) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, handshake_parameters[0]) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, local_endpoint) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, remote_endpoint) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, rpc_versions) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry, value) < 256 && pb_membersize(grpc_gcp_HandshakerReq, client_start) < 256 && pb_membersize(grpc_gcp_HandshakerReq, server_start) < 256 && pb_membersize(grpc_gcp_HandshakerReq, next) < 256 && pb_membersize(grpc_gcp_HandshakerResult, peer_identity) < 256 && pb_membersize(grpc_gcp_HandshakerResult, local_identity) < 256 && pb_membersize(grpc_gcp_HandshakerResult, peer_rpc_versions) < 256 && pb_membersize(grpc_gcp_HandshakerResp, result) < 256 && pb_membersize(grpc_gcp_HandshakerResp, status) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_gcp_Endpoint_grpc_gcp_Identity_grpc_gcp_StartClientHandshakeReq_grpc_gcp_ServerHandshakeParameters_grpc_gcp_StartServerHandshakeReq_grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_grpc_gcp_NextHandshakeMessageReq_grpc_gcp_HandshakerReq_grpc_gcp_HandshakerResult_grpc_gcp_HandshakerStatus_grpc_gcp_HandshakerResp) #endif diff --git a/src/core/tsi/alts/handshaker/transport_security_common.pb.c b/src/core/tsi/alts/handshaker/transport_security_common.pb.c index aac699314e7..326b1b10ab7 100644 --- a/src/core/tsi/alts/handshaker/transport_security_common.pb.c +++ b/src/core/tsi/alts/handshaker/transport_security_common.pb.c @@ -35,14 +35,14 @@ PB_STATIC_ASSERT((pb_membersize(grpc_gcp_RpcProtocolVersions, max_rpc_version) < #endif #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) -/* If you get an error here, it means that you need to define PB_FIELD_32BIT +/* If you get an error here, it means that you need to define PB_FIELD_16BIT * compile-time option. You can do that in pb.h or on compiler command line. * * The reason you need to do this is that some of your messages contain tag * numbers or field sizes that are larger than what can fit in the default * 8 bit descriptors. */ -PB_STATIC_ASSERT((pb_membersize(grpc_gcp_RpcProtocolVersions, max_rpc_version) < 256 && pb_membersize(grpc_gcp_RpcProtocolVersions, min_rpc_version) < 256), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_gcp_RpcProtocolVersions_grpc_gcp_RpcProtocolVersions_Version) +PB_STATIC_ASSERT((pb_membersize(grpc_gcp_RpcProtocolVersions, max_rpc_version) < 256 && pb_membersize(grpc_gcp_RpcProtocolVersions, min_rpc_version) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_gcp_RpcProtocolVersions_grpc_gcp_RpcProtocolVersions_Version) #endif From e6e10814993b5e6af93675bd468755786de1e20d Mon Sep 17 00:00:00 2001 From: Moiz Haidry Date: Tue, 11 Dec 2018 10:29:08 -0800 Subject: [PATCH 233/375] Add support for Callback Client Streaming benchmarks --- test/cpp/qps/client.h | 28 ++--- test/cpp/qps/client_callback.cc | 176 ++++++++++++++++++++++++++++---- 2 files changed, 174 insertions(+), 30 deletions(-) diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index 668d9419169..0b9837660be 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -236,6 +236,21 @@ class Client { return 0; } + bool IsClosedLoop() { return closed_loop_; } + + gpr_timespec NextIssueTime(int thread_idx) { + const gpr_timespec result = next_time_[thread_idx]; + next_time_[thread_idx] = + gpr_time_add(next_time_[thread_idx], + gpr_time_from_nanos(interarrival_timer_.next(thread_idx), + GPR_TIMESPAN)); + return result; + } + + bool ThreadCompleted() { + return static_cast(gpr_atm_acq_load(&thread_pool_done_)); + } + protected: bool closed_loop_; gpr_atm thread_pool_done_; @@ -289,14 +304,6 @@ class Client { } } - gpr_timespec NextIssueTime(int thread_idx) { - const gpr_timespec result = next_time_[thread_idx]; - next_time_[thread_idx] = - gpr_time_add(next_time_[thread_idx], - gpr_time_from_nanos(interarrival_timer_.next(thread_idx), - GPR_TIMESPAN)); - return result; - } std::function NextIssuer(int thread_idx) { return closed_loop_ ? std::function() : std::bind(&Client::NextIssueTime, this, thread_idx); @@ -380,10 +387,6 @@ class Client { double interval_start_time_; }; - bool ThreadCompleted() { - return static_cast(gpr_atm_acq_load(&thread_pool_done_)); - } - virtual void ThreadFunc(size_t thread_idx, Client::Thread* t) = 0; std::vector> threads_; @@ -442,6 +445,7 @@ class ClientImpl : public Client { config.payload_config()); } virtual ~ClientImpl() {} + const RequestType* request() { return &request_; } protected: const int cores_; diff --git a/test/cpp/qps/client_callback.cc b/test/cpp/qps/client_callback.cc index 87889e36dc5..00d5853a8e8 100644 --- a/test/cpp/qps/client_callback.cc +++ b/test/cpp/qps/client_callback.cc @@ -73,6 +73,20 @@ class CallbackClient virtual ~CallbackClient() {} + /** + * The main thread of the benchmark will be waiting on DestroyMultithreading. + * Increment the rpcs_done_ variable to signify that the Callback RPC + * after thread completion is done. When the last outstanding rpc increments + * the counter it should also signal the main thread's conditional variable. + */ + void NotifyMainThreadOfThreadCompletion() { + std::lock_guard l(shutdown_mu_); + rpcs_done_++; + if (rpcs_done_ == total_outstanding_rpcs_) { + shutdown_cv_.notify_one(); + } + } + protected: size_t num_threads_; size_t total_outstanding_rpcs_; @@ -93,23 +107,6 @@ class CallbackClient ThreadFuncImpl(t, thread_idx); } - virtual void ScheduleRpc(Thread* t, size_t thread_idx, - size_t ctx_vector_idx) = 0; - - /** - * The main thread of the benchmark will be waiting on DestroyMultithreading. - * Increment the rpcs_done_ variable to signify that the Callback RPC - * after thread completion is done. When the last outstanding rpc increments - * the counter it should also signal the main thread's conditional variable. - */ - void NotifyMainThreadOfThreadCompletion() { - std::lock_guard l(shutdown_mu_); - rpcs_done_++; - if (rpcs_done_ == total_outstanding_rpcs_) { - shutdown_cv_.notify_one(); - } - } - private: int NumThreads(const ClientConfig& config) { int num_threads = config.async_client_threads(); @@ -157,7 +154,7 @@ class CallbackUnaryClient final : public CallbackClient { void InitThreadFuncImpl(size_t thread_idx) override { return; } private: - void ScheduleRpc(Thread* t, size_t thread_idx, size_t vector_idx) override { + void ScheduleRpc(Thread* t, size_t thread_idx, size_t vector_idx) { if (!closed_loop_) { gpr_timespec next_issue_time = NextIssueTime(thread_idx); // Start an alarm callback to run the internal callback after @@ -199,11 +196,154 @@ class CallbackUnaryClient final : public CallbackClient { } }; +class CallbackStreamingClient : public CallbackClient { + public: + CallbackStreamingClient(const ClientConfig& config) + : CallbackClient(config), + messages_per_stream_(config.messages_per_stream()) { + for (int ch = 0; ch < config.client_channels(); ch++) { + for (int i = 0; i < config.outstanding_rpcs_per_channel(); i++) { + ctx_.emplace_back( + new CallbackClientRpcContext(channels_[ch].get_stub())); + } + } + StartThreads(num_threads_); + } + ~CallbackStreamingClient() {} + + void AddHistogramEntry(double start_, bool ok, void* thread_ptr) { + // Update Histogram with data from the callback run + HistogramEntry entry; + if (ok) { + entry.set_value((UsageTimer::Now() - start_) * 1e9); + } + ((Client::Thread*)thread_ptr)->UpdateHistogram(&entry); + } + + int messages_per_stream() { return messages_per_stream_; } + + protected: + const int messages_per_stream_; +}; + +class CallbackStreamingPingPongClient : public CallbackStreamingClient { + public: + CallbackStreamingPingPongClient(const ClientConfig& config) + : CallbackStreamingClient(config) {} + ~CallbackStreamingPingPongClient() {} +}; + +class CallbackStreamingPingPongReactor final + : public grpc::experimental::ClientBidiReactor { + public: + CallbackStreamingPingPongReactor( + CallbackStreamingPingPongClient* client, + std::unique_ptr ctx) + : client_(client), ctx_(std::move(ctx)), messages_issued_(0) {} + + void StartNewRpc() { + if (client_->ThreadCompleted()) return; + start_ = UsageTimer::Now(); + ctx_->stub_->experimental_async()->StreamingCall(&(ctx_->context_), this); + StartWrite(client_->request()); + StartCall(); + } + + void OnWriteDone(bool ok) override { + if (!ok || client_->ThreadCompleted()) { + if (!ok) gpr_log(GPR_ERROR, "Error writing RPC"); + StartWritesDone(); + return; + } + StartRead(&ctx_->response_); + } + + void OnReadDone(bool ok) override { + client_->AddHistogramEntry(start_, ok, thread_ptr_); + + if (client_->ThreadCompleted() || !ok || + (client_->messages_per_stream() != 0 && + ++messages_issued_ >= client_->messages_per_stream())) { + if (!ok) { + gpr_log(GPR_ERROR, "Error reading RPC"); + } + StartWritesDone(); + return; + } + StartWrite(client_->request()); + } + + void OnDone(const Status& s) override { + if (client_->ThreadCompleted() || !s.ok()) { + client_->NotifyMainThreadOfThreadCompletion(); + return; + } + ctx_.reset(new CallbackClientRpcContext(ctx_->stub_)); + ScheduleRpc(); + } + + void ScheduleRpc() { + if (client_->ThreadCompleted()) return; + + if (!client_->IsClosedLoop()) { + gpr_timespec next_issue_time = client_->NextIssueTime(thread_idx_); + // Start an alarm callback to run the internal callback after + // next_issue_time + ctx_->alarm_.experimental().Set(next_issue_time, + [this](bool ok) { StartNewRpc(); }); + } else { + StartNewRpc(); + } + } + + void set_thread_ptr(void* ptr) { thread_ptr_ = ptr; } + void set_thread_idx(int thread_idx) { thread_idx_ = thread_idx; } + + CallbackStreamingPingPongClient* client_; + std::unique_ptr ctx_; + int thread_idx_; // Needed to update histogram entries + void* thread_ptr_; // Needed to update histogram entries + double start_; // Track message start time + int messages_issued_; // Messages issued by this stream +}; + +class CallbackStreamingPingPongClientImpl final + : public CallbackStreamingPingPongClient { + public: + CallbackStreamingPingPongClientImpl(const ClientConfig& config) + : CallbackStreamingPingPongClient(config) { + for (size_t i = 0; i < total_outstanding_rpcs_; i++) + reactor_.emplace_back( + new CallbackStreamingPingPongReactor(this, std::move(ctx_[i]))); + } + ~CallbackStreamingPingPongClientImpl() {} + + bool ThreadFuncImpl(Client::Thread* t, size_t thread_idx) override { + for (size_t vector_idx = thread_idx; vector_idx < total_outstanding_rpcs_; + vector_idx += num_threads_) { + reactor_[vector_idx]->set_thread_ptr(t); + reactor_[vector_idx]->set_thread_idx(thread_idx); + reactor_[vector_idx]->ScheduleRpc(); + } + return true; + } + + void InitThreadFuncImpl(size_t thread_idx) override {} + + private: + std::vector> reactor_; +}; + +// TODO(mhaidry) : Implement Streaming from client, server and both ways + std::unique_ptr CreateCallbackClient(const ClientConfig& config) { switch (config.rpc_type()) { case UNARY: return std::unique_ptr(new CallbackUnaryClient(config)); case STREAMING: + return std::unique_ptr( + new CallbackStreamingPingPongClientImpl(config)); case STREAMING_FROM_CLIENT: case STREAMING_FROM_SERVER: case STREAMING_BOTH_WAYS: From 48ac4ee48a56582c86f2ada6d3281e37590c57c4 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 13 Dec 2018 11:21:45 -0800 Subject: [PATCH 234/375] Test assert failure --- src/objective-c/tests/InteropTests.m | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 3665e9705d8..656af188884 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -197,7 +197,8 @@ BOOL isRemoteInteropTest(NSString *host) { - (void)testEmptyUnaryRPCWithV2API { XCTAssertNotNil([[self class] host]); - __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyUnaryWithV2API"]; + __weak XCTestExpectation *expectReceive = [self expectationWithDescription:@"EmptyUnaryWithV2API received message"]; + __weak XCTestExpectation *expectComplete = [self expectationWithDescription:@"EmptyUnaryWithV2API completed"]; GPBEmpty *request = [GPBEmpty message]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; @@ -212,11 +213,12 @@ BOOL isRemoteInteropTest(NSString *host) { if (message) { id expectedResponse = [GPBEmpty message]; XCTAssertEqualObjects(message, expectedResponse); - [expectation fulfill]; + [expectReceive fulfill]; } } closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { XCTAssertNil(error, @"Unexpected error: %@", error); + [expectComplete fulfill]; }] callOptions:options]; [call start]; @@ -249,9 +251,9 @@ BOOL isRemoteInteropTest(NSString *host) { - (void)testLargeUnaryRPCWithV2API { XCTAssertNotNil([[self class] host]); - __weak XCTestExpectation *expectRecvMessage = + __weak XCTestExpectation *expectReceive = [self expectationWithDescription:@"LargeUnaryWithV2API received message"]; - __weak XCTestExpectation *expectRecvComplete = + __weak XCTestExpectation *expectComplete = [self expectationWithDescription:@"LargeUnaryWithV2API received complete"]; RMTSimpleRequest *request = [RMTSimpleRequest message]; @@ -277,12 +279,12 @@ BOOL isRemoteInteropTest(NSString *host) { [NSMutableData dataWithLength:314159]; XCTAssertEqualObjects(message, expectedResponse); - [expectRecvMessage fulfill]; + [expectReceive fulfill]; } } closeCallback:^(NSDictionary *trailingMetadata, NSError *error) { XCTAssertNil(error, @"Unexpected error: %@", error); - [expectRecvComplete fulfill]; + [expectComplete fulfill]; }] callOptions:options]; [call start]; From dc502a80988763abefb70938d020123ef0422e18 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 13 Dec 2018 11:27:26 -0800 Subject: [PATCH 235/375] clang-format --- src/objective-c/tests/InteropTests.m | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 656af188884..717dfd81f7d 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -197,8 +197,10 @@ BOOL isRemoteInteropTest(NSString *host) { - (void)testEmptyUnaryRPCWithV2API { XCTAssertNotNil([[self class] host]); - __weak XCTestExpectation *expectReceive = [self expectationWithDescription:@"EmptyUnaryWithV2API received message"]; - __weak XCTestExpectation *expectComplete = [self expectationWithDescription:@"EmptyUnaryWithV2API completed"]; + __weak XCTestExpectation *expectReceive = + [self expectationWithDescription:@"EmptyUnaryWithV2API received message"]; + __weak XCTestExpectation *expectComplete = + [self expectationWithDescription:@"EmptyUnaryWithV2API completed"]; GPBEmpty *request = [GPBEmpty message]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; From b4ccbdb124e11dd740cd042cfab88aa38e34398d Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 13 Dec 2018 16:48:28 -0800 Subject: [PATCH 236/375] Remove some annotations in GRPCRequestHeader --- src/objective-c/GRPCClient/GRPCCall.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 4ef8cee36de..f36b814cec3 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -370,11 +370,11 @@ DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.") @protocol GRPCRequestHeaders @property(nonatomic, readonly) NSUInteger count; -- (nullable id)objectForKeyedSubscript:(nonnull id)key; -- (void)setObject:(nullable id)obj forKeyedSubscript:(nonnull id)key; +- (id)objectForKeyedSubscript:(id)key; +- (void)setObject:(id)obj forKeyedSubscript:(id)key; - (void)removeAllObjects; -- (void)removeObjectForKey:(nonnull id)key; +- (void)removeObjectForKey:(id)key; @end #pragma clang diagnostic push From 5ec78a286d7be61aec929b133c031a7a1af262df Mon Sep 17 00:00:00 2001 From: Moiz Haidry Date: Fri, 14 Dec 2018 10:36:51 -0800 Subject: [PATCH 237/375] Added support for fixed load benchmarks, all the rpcs access one requestor to the get the next issue time for the RPC --- test/cpp/qps/client_callback.cc | 35 ++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/test/cpp/qps/client_callback.cc b/test/cpp/qps/client_callback.cc index 00d5853a8e8..1880f46d43d 100644 --- a/test/cpp/qps/client_callback.cc +++ b/test/cpp/qps/client_callback.cc @@ -66,7 +66,10 @@ class CallbackClient config, BenchmarkStubCreator) { num_threads_ = NumThreads(config); rpcs_done_ = 0; - SetupLoadTest(config, num_threads_); + + // Don't divide the fixed load among threads as the user threads + // only bootstrap the RPCs + SetupLoadTest(config, 1); total_outstanding_rpcs_ = config.client_channels() * config.outstanding_rpcs_per_channel(); } @@ -87,6 +90,11 @@ class CallbackClient } } + gpr_timespec NextIssueTime() { + std::lock_guard l(next_issue_time_mu_); + return Client::NextIssueTime(0); + } + protected: size_t num_threads_; size_t total_outstanding_rpcs_; @@ -108,6 +116,8 @@ class CallbackClient } private: + std::mutex next_issue_time_mu_; // Used by next issue time + int NumThreads(const ClientConfig& config) { int num_threads = config.async_client_threads(); if (num_threads <= 0) { // Use dynamic sizing @@ -146,7 +156,7 @@ class CallbackUnaryClient final : public CallbackClient { bool ThreadFuncImpl(Thread* t, size_t thread_idx) override { for (size_t vector_idx = thread_idx; vector_idx < total_outstanding_rpcs_; vector_idx += num_threads_) { - ScheduleRpc(t, thread_idx, vector_idx); + ScheduleRpc(t, vector_idx); } return true; } @@ -154,26 +164,26 @@ class CallbackUnaryClient final : public CallbackClient { void InitThreadFuncImpl(size_t thread_idx) override { return; } private: - void ScheduleRpc(Thread* t, size_t thread_idx, size_t vector_idx) { + void ScheduleRpc(Thread* t, size_t vector_idx) { if (!closed_loop_) { - gpr_timespec next_issue_time = NextIssueTime(thread_idx); + gpr_timespec next_issue_time = NextIssueTime(); // Start an alarm callback to run the internal callback after // next_issue_time ctx_[vector_idx]->alarm_.experimental().Set( - next_issue_time, [this, t, thread_idx, vector_idx](bool ok) { - IssueUnaryCallbackRpc(t, thread_idx, vector_idx); + next_issue_time, [this, t, vector_idx](bool ok) { + IssueUnaryCallbackRpc(t, vector_idx); }); } else { - IssueUnaryCallbackRpc(t, thread_idx, vector_idx); + IssueUnaryCallbackRpc(t, vector_idx); } } - void IssueUnaryCallbackRpc(Thread* t, size_t thread_idx, size_t vector_idx) { + void IssueUnaryCallbackRpc(Thread* t, size_t vector_idx) { GPR_TIMER_SCOPE("CallbackUnaryClient::ThreadFunc", 0); double start = UsageTimer::Now(); ctx_[vector_idx]->stub_->experimental_async()->UnaryCall( (&ctx_[vector_idx]->context_), &request_, &ctx_[vector_idx]->response_, - [this, t, thread_idx, start, vector_idx](grpc::Status s) { + [this, t, start, vector_idx](grpc::Status s) { // Update Histogram with data from the callback run HistogramEntry entry; if (s.ok()) { @@ -190,7 +200,7 @@ class CallbackUnaryClient final : public CallbackClient { ctx_[vector_idx].reset( new CallbackClientRpcContext(ctx_[vector_idx]->stub_)); // Schedule a new RPC - ScheduleRpc(t, thread_idx, vector_idx); + ScheduleRpc(t, vector_idx); } }); } @@ -287,7 +297,7 @@ class CallbackStreamingPingPongReactor final if (client_->ThreadCompleted()) return; if (!client_->IsClosedLoop()) { - gpr_timespec next_issue_time = client_->NextIssueTime(thread_idx_); + gpr_timespec next_issue_time = client_->NextIssueTime(); // Start an alarm callback to run the internal callback after // next_issue_time ctx_->alarm_.experimental().Set(next_issue_time, @@ -298,11 +308,9 @@ class CallbackStreamingPingPongReactor final } void set_thread_ptr(void* ptr) { thread_ptr_ = ptr; } - void set_thread_idx(int thread_idx) { thread_idx_ = thread_idx; } CallbackStreamingPingPongClient* client_; std::unique_ptr ctx_; - int thread_idx_; // Needed to update histogram entries void* thread_ptr_; // Needed to update histogram entries double start_; // Track message start time int messages_issued_; // Messages issued by this stream @@ -323,7 +331,6 @@ class CallbackStreamingPingPongClientImpl final for (size_t vector_idx = thread_idx; vector_idx < total_outstanding_rpcs_; vector_idx += num_threads_) { reactor_[vector_idx]->set_thread_ptr(t); - reactor_[vector_idx]->set_thread_idx(thread_idx); reactor_[vector_idx]->ScheduleRpc(); } return true; From 653160d8067e648c94c7ab095dc7fe4bbe1f3271 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 14 Dec 2018 13:47:33 -0800 Subject: [PATCH 238/375] Make NSMutableDictionary annotation right --- src/objective-c/GRPCClient/GRPCCall.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index f36b814cec3..d4d16024fa0 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -370,11 +370,11 @@ DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.") @protocol GRPCRequestHeaders @property(nonatomic, readonly) NSUInteger count; -- (id)objectForKeyedSubscript:(id)key; -- (void)setObject:(id)obj forKeyedSubscript:(id)key; +- (nullable id)objectForKeyedSubscript:(nonnull id)key; +- (void)setObject:(nonnull id)obj forKeyedSubscript:(nonnull id)key; - (void)removeAllObjects; -- (void)removeObjectForKey:(id)key; +- (void)removeObjectForKey:(nonnull id)key; @end #pragma clang diagnostic push From 4f91630d6b2ba9fbf0b75e2dbaa1932a739f2b17 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 14 Dec 2018 13:46:53 -0800 Subject: [PATCH 239/375] CFStream use serial dispatch queue --- src/core/lib/iomgr/cfstream_handle.cc | 98 ++++++++++++--------------- src/core/lib/iomgr/cfstream_handle.h | 2 + 2 files changed, 46 insertions(+), 54 deletions(-) diff --git a/src/core/lib/iomgr/cfstream_handle.cc b/src/core/lib/iomgr/cfstream_handle.cc index 827fd24831e..bb402f96cf5 100644 --- a/src/core/lib/iomgr/cfstream_handle.cc +++ b/src/core/lib/iomgr/cfstream_handle.cc @@ -52,62 +52,53 @@ CFStreamHandle* CFStreamHandle::CreateStreamHandle( void CFStreamHandle::ReadCallback(CFReadStreamRef stream, CFStreamEventType type, void* client_callback_info) { + grpc_core::ExecCtx exec_ctx; CFStreamHandle* handle = static_cast(client_callback_info); - CFSTREAM_HANDLE_REF(handle, "read callback"); - dispatch_async( - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - grpc_core::ExecCtx exec_ctx; - if (grpc_tcp_trace.enabled()) { - gpr_log(GPR_DEBUG, "CFStream ReadCallback (%p, %p, %lu, %p)", handle, - stream, type, client_callback_info); - } - switch (type) { - case kCFStreamEventOpenCompleted: - handle->open_event_.SetReady(); - break; - case kCFStreamEventHasBytesAvailable: - case kCFStreamEventEndEncountered: - handle->read_event_.SetReady(); - break; - case kCFStreamEventErrorOccurred: - handle->open_event_.SetReady(); - handle->read_event_.SetReady(); - break; - default: - GPR_UNREACHABLE_CODE(return ); - } - CFSTREAM_HANDLE_UNREF(handle, "read callback"); - }); + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_DEBUG, "CFStream ReadCallback (%p, %p, %lu, %p)", handle, + stream, type, client_callback_info); + } + switch (type) { + case kCFStreamEventOpenCompleted: + handle->open_event_.SetReady(); + break; + case kCFStreamEventHasBytesAvailable: + case kCFStreamEventEndEncountered: + handle->read_event_.SetReady(); + break; + case kCFStreamEventErrorOccurred: + handle->open_event_.SetReady(); + handle->read_event_.SetReady(); + break; + default: + GPR_UNREACHABLE_CODE(return ); + } } void CFStreamHandle::WriteCallback(CFWriteStreamRef stream, CFStreamEventType type, void* clientCallBackInfo) { + grpc_core::ExecCtx exec_ctx; CFStreamHandle* handle = static_cast(clientCallBackInfo); - CFSTREAM_HANDLE_REF(handle, "write callback"); - dispatch_async( - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - grpc_core::ExecCtx exec_ctx; - if (grpc_tcp_trace.enabled()) { - gpr_log(GPR_DEBUG, "CFStream WriteCallback (%p, %p, %lu, %p)", handle, - stream, type, clientCallBackInfo); - } - switch (type) { - case kCFStreamEventOpenCompleted: - handle->open_event_.SetReady(); - break; - case kCFStreamEventCanAcceptBytes: - case kCFStreamEventEndEncountered: - handle->write_event_.SetReady(); - break; - case kCFStreamEventErrorOccurred: - handle->open_event_.SetReady(); - handle->write_event_.SetReady(); - break; - default: - GPR_UNREACHABLE_CODE(return ); - } - CFSTREAM_HANDLE_UNREF(handle, "write callback"); - }); + printf("** CFStreamHandle::WriteCallback\n"); + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_DEBUG, "CFStream WriteCallback (%p, %p, %lu, %p)", handle, + stream, type, clientCallBackInfo); + } + switch (type) { + case kCFStreamEventOpenCompleted: + handle->open_event_.SetReady(); + break; + case kCFStreamEventCanAcceptBytes: + case kCFStreamEventEndEncountered: + handle->write_event_.SetReady(); + break; + case kCFStreamEventErrorOccurred: + handle->open_event_.SetReady(); + handle->write_event_.SetReady(); + break; + default: + GPR_UNREACHABLE_CODE(return ); + } } CFStreamHandle::CFStreamHandle(CFReadStreamRef read_stream, @@ -116,6 +107,7 @@ CFStreamHandle::CFStreamHandle(CFReadStreamRef read_stream, open_event_.InitEvent(); read_event_.InitEvent(); write_event_.InitEvent(); + dispatch_queue_ = dispatch_queue_create(nullptr, DISPATCH_QUEUE_SERIAL); CFStreamClientContext ctx = {0, static_cast(this), CFStreamHandle::Retain, CFStreamHandle::Release, nil}; @@ -129,10 +121,8 @@ CFStreamHandle::CFStreamHandle(CFReadStreamRef read_stream, kCFStreamEventOpenCompleted | kCFStreamEventCanAcceptBytes | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, CFStreamHandle::WriteCallback, &ctx); - CFReadStreamScheduleWithRunLoop(read_stream, CFRunLoopGetMain(), - kCFRunLoopCommonModes); - CFWriteStreamScheduleWithRunLoop(write_stream, CFRunLoopGetMain(), - kCFRunLoopCommonModes); + CFReadStreamSetDispatchQueue(read_stream, dispatch_queue_); + CFWriteStreamSetDispatchQueue(write_stream, dispatch_queue_); } CFStreamHandle::~CFStreamHandle() { diff --git a/src/core/lib/iomgr/cfstream_handle.h b/src/core/lib/iomgr/cfstream_handle.h index 4258e72431c..93ec5f044bb 100644 --- a/src/core/lib/iomgr/cfstream_handle.h +++ b/src/core/lib/iomgr/cfstream_handle.h @@ -62,6 +62,8 @@ class CFStreamHandle final { grpc_core::LockfreeEvent read_event_; grpc_core::LockfreeEvent write_event_; + dispatch_queue_t dispatch_queue_; + gpr_refcount refcount_; }; From 4196f59a445a53246f3835b52b49613c9ebd091e Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 14 Dec 2018 16:06:15 -0800 Subject: [PATCH 240/375] more nullability annotation --- src/objective-c/GRPCClient/GRPCCall.h | 2 +- src/objective-c/GRPCClient/GRPCCallOptions.h | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index d4d16024fa0..404d4b76568 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -282,7 +282,7 @@ NS_ASSUME_NONNULL_END */ @interface GRPCCall : GRXWriter -- (nullable instancetype)init NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; /** * The container of the request headers of an RPC conforms to this protocol, which is a subset of diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index b7f08480dc0..b866f268ee1 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -18,6 +18,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** * Safety remark of a gRPC method as defined in RFC 2616 Section 9.1 */ @@ -66,7 +68,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * This method is called when gRPC is about to start the call. When OAuth token is acquired, * \a handler is expected to be called with \a token being the new token to be used for this call. */ -- (void)provideTokenToHandler:(void (^_Nullable)(NSString *_Nullable token))handler; +- (void)provideTokenToHandler:(void (^)(NSString *_Nullable token))handler; /** * This method is deprecated. Please use \a provideTokenToHandler. @@ -74,7 +76,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { * This method is called when gRPC is about to start the call. When OAuth token is acquired, * \a handler is expected to be called with \a token being the new token to be used for this call. */ -- (void)getTokenWithHandler:(void (^_Nullable)(NSString *_Nullable token))handler; +- (void)getTokenWithHandler:(void (^)(NSString *_Nullable token))handler; @end @@ -210,7 +212,7 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { /** * Return if the channel options are equal to another object. */ -- (BOOL)hasChannelOptionsEqualTo:(nonnull GRPCCallOptions *)callOptions; +- (BOOL)hasChannelOptionsEqualTo:(GRPCCallOptions *)callOptions; /** * Hash for channel options. @@ -352,3 +354,5 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { @property(readwrite) NSUInteger channelID; @end + +NS_ASSUME_NONNULL_END From b90652ab0329e67697e71282b785187a4d1cb223 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 14 Dec 2018 16:07:20 -0800 Subject: [PATCH 241/375] remove debug information --- src/core/lib/iomgr/cfstream_handle.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/lib/iomgr/cfstream_handle.cc b/src/core/lib/iomgr/cfstream_handle.cc index bb402f96cf5..6cb9ca1a0d4 100644 --- a/src/core/lib/iomgr/cfstream_handle.cc +++ b/src/core/lib/iomgr/cfstream_handle.cc @@ -79,7 +79,6 @@ void CFStreamHandle::WriteCallback(CFWriteStreamRef stream, void* clientCallBackInfo) { grpc_core::ExecCtx exec_ctx; CFStreamHandle* handle = static_cast(clientCallBackInfo); - printf("** CFStreamHandle::WriteCallback\n"); if (grpc_tcp_trace.enabled()) { gpr_log(GPR_DEBUG, "CFStream WriteCallback (%p, %p, %lu, %p)", handle, stream, type, clientCallBackInfo); From c097e21259db28d8b80ed661c0c0e3d808466ed1 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 14 Dec 2018 17:55:11 -0800 Subject: [PATCH 242/375] Nullability annotation fix --- src/objective-c/GRPCClient/GRPCCall.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 404d4b76568..15b1c904498 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -282,7 +282,7 @@ NS_ASSUME_NONNULL_END */ @interface GRPCCall : GRXWriter -- (instancetype)init NS_UNAVAILABLE; +- (nonnull instancetype)init NS_UNAVAILABLE; /** * The container of the request headers of an RPC conforms to this protocol, which is a subset of From 240eb480864a0be9f9af5c452b290de3385f1211 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 17 Dec 2018 16:19:46 +0100 Subject: [PATCH 243/375] prevent setting wrong time on macos high sierra kokoro workers --- tools/internal_ci/helper_scripts/prepare_build_macos_rc | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tools/internal_ci/helper_scripts/prepare_build_macos_rc b/tools/internal_ci/helper_scripts/prepare_build_macos_rc index 0ef9735c1cd..067a60da822 100644 --- a/tools/internal_ci/helper_scripts/prepare_build_macos_rc +++ b/tools/internal_ci/helper_scripts/prepare_build_macos_rc @@ -19,14 +19,6 @@ launchctl limit maxfiles ulimit -a -# synchronize the clock -date -sudo systemsetup -setusingnetworktime off -sudo systemsetup -setnetworktimeserver "$( ipconfig getoption en0 server_identifier )" -sudo systemsetup -settimezone America/Los_Angeles -sudo systemsetup -setusingnetworktime on -date - # Add GCP credentials for BQ access # pin google-api-python-client to avoid https://github.com/grpc/grpc/issues/15600 pip install google-api-python-client==1.6.7 --user python From afc2fabe0c16efbf768c70f365688156b457619d Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 17 Dec 2018 16:10:06 -0800 Subject: [PATCH 244/375] Avoid taking refs on the stream by getting a copy of the context --- .../chttp2/transport/context_list.cc | 38 +++++++++++++------ .../transport/chttp2/transport/context_list.h | 35 ++++------------- 2 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/context_list.cc b/src/core/ext/transport/chttp2/transport/context_list.cc index f30d41c3326..df09809067d 100644 --- a/src/core/ext/transport/chttp2/transport/context_list.cc +++ b/src/core/ext/transport/chttp2/transport/context_list.cc @@ -21,31 +21,47 @@ #include "src/core/ext/transport/chttp2/transport/context_list.h" namespace { -void (*write_timestamps_callback_g)(void*, grpc_core::Timestamps*) = nullptr; -} +void (*write_timestamps_callback_g)(void*, grpc_core::Timestamps*, + grpc_error* error) = nullptr; +void* (*get_copied_context_fn_g)(void*) = nullptr; +} // namespace namespace grpc_core { +void ContextList::Append(ContextList** head, grpc_chttp2_stream* s) { + if (get_copied_context_fn_g == nullptr || + write_timestamps_callback_g == nullptr) { + return; + } + /* Create a new element in the list and add it at the front */ + ContextList* elem = grpc_core::New(); + elem->trace_context_ = get_copied_context_fn_g(s->context); + elem->byte_offset_ = s->byte_counter; + elem->next_ = *head; + *head = elem; +} + void ContextList::Execute(void* arg, grpc_core::Timestamps* ts, grpc_error* error) { ContextList* head = static_cast(arg); ContextList* to_be_freed; while (head != nullptr) { - if (error == GRPC_ERROR_NONE && ts != nullptr) { - if (write_timestamps_callback_g) { - ts->byte_offset = static_cast(head->byte_offset_); - write_timestamps_callback_g(head->s_->context, ts); - } + if (write_timestamps_callback_g) { + ts->byte_offset = static_cast(head->byte_offset_); + write_timestamps_callback_g(head->trace_context_, ts, error); } - GRPC_CHTTP2_STREAM_UNREF(static_cast(head->s_), - "timestamp"); to_be_freed = head; head = head->next_; grpc_core::Delete(to_be_freed); } } -void grpc_http2_set_write_timestamps_callback( - void (*fn)(void*, grpc_core::Timestamps*)) { +void grpc_http2_set_write_timestamps_callback(void (*fn)(void*, + grpc_core::Timestamps*, + grpc_error* error)) { write_timestamps_callback_g = fn; } + +void grpc_http2_set_fn_get_copied_context(void* (*fn)(void*)) { + get_copied_context_fn_g = fn; +} } /* namespace grpc_core */ diff --git a/src/core/ext/transport/chttp2/transport/context_list.h b/src/core/ext/transport/chttp2/transport/context_list.h index d8701077494..5b9d2ab3784 100644 --- a/src/core/ext/transport/chttp2/transport/context_list.h +++ b/src/core/ext/transport/chttp2/transport/context_list.h @@ -31,42 +31,23 @@ class ContextList { public: /* Creates a new element with \a context as the value and appends it to the * list. */ - static void Append(ContextList** head, grpc_chttp2_stream* s) { - /* Make sure context is not already present */ - GRPC_CHTTP2_STREAM_REF(s, "timestamp"); - -#ifndef NDEBUG - ContextList* ptr = *head; - while (ptr != nullptr) { - if (ptr->s_ == s) { - GPR_ASSERT( - false && - "Trying to append a stream that is already present in the list"); - } - ptr = ptr->next_; - } -#endif - - /* Create a new element in the list and add it at the front */ - ContextList* elem = grpc_core::New(); - elem->s_ = s; - elem->byte_offset_ = s->byte_counter; - elem->next_ = *head; - *head = elem; - } + static void Append(ContextList** head, grpc_chttp2_stream* s); /* Executes a function \a fn with each context in the list and \a ts. It also - * frees up the entire list after this operation. */ + * frees up the entire list after this operation. It is intended as a callback + * and hence does not take a ref on \a error */ static void Execute(void* arg, grpc_core::Timestamps* ts, grpc_error* error); private: - grpc_chttp2_stream* s_ = nullptr; + void* trace_context_ = nullptr; ContextList* next_ = nullptr; size_t byte_offset_ = 0; }; -void grpc_http2_set_write_timestamps_callback( - void (*fn)(void*, grpc_core::Timestamps*)); +void grpc_http2_set_write_timestamps_callback(void (*fn)(void*, + grpc_core::Timestamps*, + grpc_error* error)); +void grpc_http2_set_fn_get_copied_context(void* (*fn)(void*)); } /* namespace grpc_core */ #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CONTEXT_LIST_H */ From 906cf5b428f31513321c8d2e3530aa7a03cca400 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 17 Dec 2018 16:15:46 -0800 Subject: [PATCH 245/375] Add error details on context list clearing --- .../ext/transport/chttp2/transport/chttp2_transport.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 9b6574b612d..3b7c48a72ca 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -170,9 +170,6 @@ grpc_chttp2_transport::~grpc_chttp2_transport() { grpc_slice_buffer_destroy_internal(&outbuf); grpc_chttp2_hpack_compressor_destroy(&hpack_compressor); - grpc_core::ContextList::Execute(cl, nullptr, GRPC_ERROR_NONE); - cl = nullptr; - grpc_slice_buffer_destroy_internal(&read_buffer); grpc_chttp2_hpack_parser_destroy(&hpack_parser); grpc_chttp2_goaway_parser_destroy(&goaway_parser); @@ -569,6 +566,10 @@ static void close_transport_locked(grpc_chttp2_transport* t, grpc_error* error) { end_all_the_calls(t, GRPC_ERROR_REF(error)); cancel_pings(t, GRPC_ERROR_REF(error)); + // ContextList::Execute follows semantics of a callback function and does not + // need a ref on error + grpc_core::ContextList::Execute(cl, nullptr, error); + cl = nullptr; if (t->closed_with_error == GRPC_ERROR_NONE) { if (!grpc_error_has_clear_grpc_status(error)) { error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, From 915cd71b4a6aceb8003077e0e360ea7accbde38c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 17 Dec 2018 17:36:28 -0800 Subject: [PATCH 246/375] nullability revert --- src/objective-c/GRPCClient/GRPCCall.h | 32 +++++++++++++----------- src/objective-c/ProtoRPC/ProtoRPC.h | 9 +++---- src/objective-c/ProtoRPC/ProtoService.h | 33 +++++++++++++------------ 3 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 15b1c904498..6669067fbff 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -275,6 +275,9 @@ extern NSString *const kGRPCTrailersKey; NS_ASSUME_NONNULL_END +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnullability-completeness" + /** * This interface is deprecated. Please use \a GRPCcall2. * @@ -282,7 +285,7 @@ NS_ASSUME_NONNULL_END */ @interface GRPCCall : GRXWriter -- (nonnull instancetype)init NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; /** * The container of the request headers of an RPC conforms to this protocol, which is a subset of @@ -308,7 +311,7 @@ NS_ASSUME_NONNULL_END * * The property is initialized to an empty NSMutableDictionary. */ -@property(nonnull, atomic, readonly) NSMutableDictionary *requestHeaders; +@property(atomic, readonly) NSMutableDictionary *requestHeaders; /** * This dictionary is populated with the HTTP headers received from the server. This happens before @@ -319,7 +322,7 @@ NS_ASSUME_NONNULL_END * 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(nullable, atomic, readonly) NSDictionary *responseHeaders; +@property(atomic, readonly) NSDictionary *responseHeaders; /** * Same as responseHeaders, but populated with the HTTP trailers received from the server before the @@ -328,7 +331,7 @@ NS_ASSUME_NONNULL_END * The value of this property is nil until all response trailers are received, and will change * before -writesFinishedWithError: is sent to the writeable. */ -@property(nullable, atomic, readonly) NSDictionary *responseTrailers; +@property(atomic, readonly) NSDictionary *responseTrailers; /** * The request writer has to write NSData objects into the provided Writeable. The server will @@ -341,9 +344,9 @@ NS_ASSUME_NONNULL_END * host parameter should not contain the scheme (http:// or https://), only the name or IP addr * and the port number, for example @"localhost:5050". */ -- (nullable instancetype)initWithHost:(nonnull NSString *)host - path:(nonnull NSString *)path - requestsWriter:(nonnull GRXWriter *)requestWriter; +- (instancetype)initWithHost:(NSString *)host + path:(NSString *)path + requestsWriter:(GRXWriter *)requestWriter; /** * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and @@ -354,12 +357,10 @@ NS_ASSUME_NONNULL_END /** * The following methods are deprecated. */ -+ (void)setCallSafety:(GRPCCallSafety)callSafety - host:(nonnull NSString *)host - path:(nonnull NSString *)path; -@property(nullable, atomic, copy, readwrite) NSString *serverName; ++ (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString *)host path:(NSString *)path; +@property(atomic, copy, readwrite) NSString *serverName; @property NSTimeInterval timeout; -- (void)setResponseDispatchQueue:(nonnull dispatch_queue_t)queue; +- (void)setResponseDispatchQueue:(dispatch_queue_t)queue; @end @@ -370,11 +371,11 @@ DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.") @protocol GRPCRequestHeaders @property(nonatomic, readonly) NSUInteger count; -- (nullable id)objectForKeyedSubscript:(nonnull id)key; -- (void)setObject:(nonnull id)obj forKeyedSubscript:(nonnull id)key; +- (id)objectForKeyedSubscript:(id)key; +- (void)setObject:(id)obj forKeyedSubscript:(id)key; - (void)removeAllObjects; -- (void)removeObjectForKey:(nonnull id)key; +- (void)removeObjectForKey:(id)key; @end #pragma clang diagnostic push @@ -383,3 +384,4 @@ DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.") @interface NSMutableDictionary (GRPCRequestHeaders) @end #pragma clang diagnostic pop +#pragma clang diagnostic pop diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index e6ba1f66ca5..91a50d395af 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -142,11 +142,10 @@ __attribute__((deprecated("Please use GRPCProtoCall."))) @interface ProtoRPC * addr and the port number, for example @"localhost:5050". */ - - (nullable instancetype)initWithHost : (nonnull NSString *)host method - : (nonnull GRPCProtoMethod *)method requestsWriter - : (nonnull GRXWriter *)requestsWriter responseClass - : (nonnull Class)responseClass responsesWriteable - : (nonnull id)responsesWriteable NS_DESIGNATED_INITIALIZER; + (instancetype)initWithHost : (NSString *)host method + : (GRPCProtoMethod *)method requestsWriter : (GRXWriter *)requestsWriter responseClass + : (Class)responseClass responsesWriteable + : (id)responsesWriteable NS_DESIGNATED_INITIALIZER; - (void)start; @end diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h index 70423ee9def..d76e96ce2a6 100644 --- a/src/objective-c/ProtoRPC/ProtoService.h +++ b/src/objective-c/ProtoRPC/ProtoService.h @@ -27,38 +27,41 @@ @class GRPCStreamingProtoCall; @protocol GRPCProtoResponseCallbacks; -NS_ASSUME_NONNULL_BEGIN +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnullability-completeness" __attribute__((deprecated("Please use GRPCProtoService."))) @interface ProtoService : NSObject - - (nullable instancetype)initWithHost : (NSString *)host packageName - : (NSString *)packageName serviceName : (NSString *)serviceName callOptions + (nullable instancetype)initWithHost : (nonnull NSString *)host packageName + : (nonnull NSString *)packageName serviceName : (nonnull NSString *)serviceName callOptions : (nullable GRPCCallOptions *)callOptions NS_DESIGNATED_INITIALIZER; - (instancetype)initWithHost:(NSString *)host packageName:(NSString *)packageName serviceName:(NSString *)serviceName; -- (nullable GRPCProtoCall *)RPCToMethod:(NSString *)method - requestsWriter:(GRXWriter *)requestsWriter - responseClass:(Class)responseClass - responsesWriteable:(id)responsesWriteable; +- (GRPCProtoCall *)RPCToMethod:(NSString *)method + requestsWriter:(GRXWriter *)requestsWriter + responseClass:(Class)responseClass + responsesWriteable:(id)responsesWriteable; -- (nullable GRPCUnaryProtoCall *)RPCToMethod:(NSString *)method - message:(id)message - responseHandler:(id)handler +- (nullable GRPCUnaryProtoCall *)RPCToMethod:(nonnull NSString *)method + message:(nonnull id)message + responseHandler:(nonnull id)handler callOptions:(nullable GRPCCallOptions *)callOptions - responseClass:(Class)responseClass; + responseClass:(nonnull Class)responseClass; -- (nullable GRPCStreamingProtoCall *)RPCToMethod:(NSString *)method - responseHandler:(id)handler +- (nullable GRPCStreamingProtoCall *)RPCToMethod:(nonnull NSString *)method + responseHandler:(nonnull id)handler callOptions:(nullable GRPCCallOptions *)callOptions - responseClass:(Class)responseClass; + responseClass:(nonnull Class)responseClass; @end +#pragma clang diagnostic pop + /** * This subclass is empty now. Eventually we'll remove ProtoService class * to avoid potential naming conflict @@ -69,5 +72,3 @@ __attribute__((deprecated("Please use GRPCProtoService."))) @interface ProtoServ #pragma clang diagnostic pop @end - - NS_ASSUME_NONNULL_END From 8c3df503ad59a6c66e1b1ab6257b52c508ec37dc Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 17 Dec 2018 21:54:53 -0800 Subject: [PATCH 247/375] Fix compatibility test failures --- src/objective-c/GRPCClient/GRPCCall.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index cfd0de1a8a2..39e4967ec98 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -484,8 +484,8 @@ const char *kCFStreamVarName = "grpc_cfstream"; callSafety:(GRPCCallSafety)safety requestsWriter:(GRXWriter *)requestWriter callOptions:(GRPCCallOptions *)callOptions { - // Purposely using pointer rather than length ([host length] == 0) for backwards compatibility. - NSAssert(host.length != 0 && path.length != 0, @"Neither host nor path can be nil."); + // Purposely using pointer rather than length (host.length == 0) for backwards compatibility. + NSAssert(host != nil && path != nil, @"Neither host nor path can be nil."); NSAssert(safety <= GRPCCallSafetyCacheableRequest, @"Invalid call safety value."); NSAssert(requestWriter.state == GRXWriterStateNotStarted, @"The requests writer can't be already started."); From d36a13af3182495079bee65ff78e3e7e7f0d5901 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 17 Dec 2018 21:55:26 -0800 Subject: [PATCH 248/375] Try use alternative simulator for APIv2Tests --- src/objective-c/tests/run_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh index e8c3e6ec2a4..f075d9baadd 100755 --- a/src/objective-c/tests/run_tests.sh +++ b/src/objective-c/tests/run_tests.sh @@ -187,7 +187,7 @@ echo "TIME: $(date)" xcodebuild \ -workspace Tests.xcworkspace \ -scheme APIv2Tests \ - -destination name="iPhone 8" \ + -destination name="iPhone X" \ test \ | egrep -v "$XCODEBUILD_FILTER" \ | egrep -v '^$' \ From 8bc8ff3dce507f912b8985fefaa22da1e2d95b6d Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 18 Dec 2018 11:13:13 -0800 Subject: [PATCH 249/375] Fix nullability incompatibility --- src/compiler/objective_c_generator.cc | 11 +++++------ src/objective-c/ProtoRPC/ProtoRPC.h | 5 +++++ src/objective-c/ProtoRPC/ProtoService.m | 10 +++++++++- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc index 0a6b64f5952..af5398ec683 100644 --- a/src/compiler/objective_c_generator.cc +++ b/src/compiler/objective_c_generator.cc @@ -355,7 +355,7 @@ void PrintMethodImplementations(Printer* printer, "@implementation $service_class$\n\n" "// Designated initializer\n" "- (instancetype)initWithHost:(NSString *)host " - "callOptions:(GRPCCallOptions *_Nullable)callOptions{\n" + "callOptions:(GRPCCallOptions *_Nullable)callOptions {\n" " self = [super initWithHost:host\n" " packageName:@\"$package$\"\n" " serviceName:@\"$service_name$\"\n" @@ -363,10 +363,9 @@ void PrintMethodImplementations(Printer* printer, " return self;\n" "}\n\n" "- (instancetype)initWithHost:(NSString *)host {\n" - " return [self initWithHost:host\n" - " packageName:@\"$package$\"\n" - " serviceName:@\"$service_name$\"\n" - " callOptions:nil];\n" + " return [super initWithHost:host\n" + " packageName:@\"$package$\"\n" + " serviceName:@\"$service_name$\"];\n" "}\n\n"); printer.Print( @@ -381,7 +380,7 @@ void PrintMethodImplementations(Printer* printer, printer.Print( "#pragma mark - Class Methods\n\n" "+ (instancetype)serviceWithHost:(NSString *)host {\n" - " return [self serviceWithHost:host callOptions:nil];\n" + " return [[self alloc] initWithHost:host];\n" "}\n\n" "+ (instancetype)serviceWithHost:(NSString *)host " "callOptions:(GRPCCallOptions *_Nullable)callOptions {\n" diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 91a50d395af..8ce3421cc17 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -134,6 +134,9 @@ NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnullability-completeness" + __attribute__((deprecated("Please use GRPCProtoCall."))) @interface ProtoRPC : GRPCCall @@ -160,3 +163,5 @@ __attribute__((deprecated("Please use GRPCProtoCall."))) @interface ProtoRPC #pragma clang diagnostic pop @end + +#pragma clang diagnostic pop diff --git a/src/objective-c/ProtoRPC/ProtoService.m b/src/objective-c/ProtoRPC/ProtoService.m index 3d998bfaeb8..b7c7fadbcf0 100644 --- a/src/objective-c/ProtoRPC/ProtoService.m +++ b/src/objective-c/ProtoRPC/ProtoService.m @@ -61,7 +61,15 @@ - (instancetype)initWithHost:(NSString *)host packageName:(NSString *)packageName serviceName:(NSString *)serviceName { - return [self initWithHost:host packageName:packageName serviceName:serviceName callOptions:nil]; + // Do not call designated initializer here due to nullability incompatibility. This method is from + // old API and does not assert on nullability of the parameters. + if ((self = [super init])) { + _host = [host copy]; + _packageName = [packageName copy]; + _serviceName = [serviceName copy]; + _callOptions = nil; + } + return self; } - (GRPCProtoCall *)RPCToMethod:(NSString *)method From 31a775b425eac37bb43c301cfb25e1f6a4bde106 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 18 Dec 2018 12:52:14 -0800 Subject: [PATCH 250/375] Add missing argument --- include/grpcpp/impl/codegen/call_op_set.h | 3 +-- include/grpcpp/impl/codegen/interceptor_common.h | 1 + test/cpp/end2end/client_interceptors_end2end_test.cc | 8 +++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index 3db9f48bffe..1c0ccbab527 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -340,12 +340,11 @@ class CallOpSendMessage { if (send_buf_.Valid()) { interceptor_methods->AddInterceptionHookPoint( experimental::InterceptionHookPoints::POST_SEND_MESSAGE); - // We had already registered failed_send_ earlier. No need to do it again. } send_buf_.Clear(); // The contents of the SendMessage value that was previously set // has had its references stolen by core's operations - interceptor_methods->SetSendMessage(nullptr); + interceptor_methods->SetSendMessage(nullptr, &failed_send_); } void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) { diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index 321691236be..b01706af8d9 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -403,6 +403,7 @@ class CancelInterceptorBatchMethods false && "It is illegal to call GetSendMessageStatus on a method which " "has a Cancel notification"); + return false; } std::multimap* GetSendInitialMetadata() override { diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 33773e3b3b9..c55eaab4d6f 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -580,11 +580,9 @@ TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingTest) { TEST_F(ClientInterceptorsStreamingEnd2endTest, ClientStreamingHijackingTest) { ChannelArguments args; - auto creators = std::unique_ptr>>( - new std::vector< - std::unique_ptr>()); - creators->push_back( + std::vector> + creators; + creators.push_back( std::unique_ptr( new ClientStreamingRpcHijackingInterceptorFactory())); auto channel = experimental::CreateCustomChannelWithInterceptors( From d79b3fe3207f7bd064d584c6e15517680749e2d5 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 18 Dec 2018 14:28:36 -0800 Subject: [PATCH 251/375] Fix test --- src/objective-c/tests/GRPCClientTests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index b16720557f7..3ef046835e4 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -365,7 +365,7 @@ static GRPCProtoMethod *kFullDuplexCallMethod; GRXWriter *writer = [GRXWriter writerWithValue:[NSData data]]; // Try to set parameters to nil for GRPCCall. This should cause an exception @try { - (void)[[GRPCCall alloc] initWithHost:@"" path:@"" requestsWriter:writer]; + (void)[[GRPCCall alloc] initWithHost:nil path:nil requestsWriter:writer]; XCTFail(@"Did not receive an exception when parameters are nil"); } @catch (NSException *theException) { NSLog(@"Received exception as expected: %@", theException.name); From 3f57e3451bf4a3687e70e92fc218ea25ff7a17c9 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 19 Dec 2018 08:09:12 -0800 Subject: [PATCH 252/375] Try earlier APIv2Tests --- src/objective-c/tests/run_tests.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh index f075d9baadd..aab80ded61b 100755 --- a/src/objective-c/tests/run_tests.sh +++ b/src/objective-c/tests/run_tests.sh @@ -176,7 +176,7 @@ xcodebuild \ echo "TIME: $(date)" xcodebuild \ -workspace Tests.xcworkspace \ - -scheme ChannelTests \ + -scheme APIv2Tests \ -destination name="iPhone 8" \ test \ | egrep -v "$XCODEBUILD_FILTER" \ @@ -186,11 +186,12 @@ xcodebuild \ echo "TIME: $(date)" xcodebuild \ -workspace Tests.xcworkspace \ - -scheme APIv2Tests \ - -destination name="iPhone X" \ + -scheme ChannelTests \ + -destination name="iPhone 8" \ test \ | egrep -v "$XCODEBUILD_FILTER" \ | egrep -v '^$' \ | egrep -v "(GPBDictionary|GPBArray)" - + exit 0 From 25e73664136ea01e2b8a64149a97e782c57d9f7d Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 19 Dec 2018 09:16:26 -0800 Subject: [PATCH 253/375] Revert "Rename getTokenWithHandler" Since the renamed protocol is breaking people and is not general enough, we revert the rename and leave the work to interceptor This reverts commit 92db5fc72488f9d62b81ee311a79832df787f3ef. --- src/objective-c/GRPCClient/GRPCCall.m | 14 ++------------ src/objective-c/GRPCClient/GRPCCallOptions.h | 12 +----------- src/objective-c/ProtoRPC/ProtoRPC.m | 2 +- src/objective-c/tests/APIv2Tests/APIv2Tests.m | 2 +- 4 files changed, 5 insertions(+), 25 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 39e4967ec98..9bcacac0dfc 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -885,7 +885,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; @synchronized(self) { self.isWaitingForToken = YES; } - void (^tokenHandler)(NSString *token) = ^(NSString *token) { + [_callOptions.authTokenProvider getTokenWithHandler:^(NSString *token) { @synchronized(self) { if (self.isWaitingForToken) { if (token) { @@ -895,17 +895,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; self.isWaitingForToken = NO; } } - }; - id authTokenProvider = _callOptions.authTokenProvider; - if ([authTokenProvider respondsToSelector:@selector(provideTokenToHandler:)]) { - [_callOptions.authTokenProvider provideTokenToHandler:tokenHandler]; - } else { - NSAssert([authTokenProvider respondsToSelector:@selector(getTokenWithHandler:)], - @"authTokenProvider has no usable method"); - if ([authTokenProvider respondsToSelector:@selector(getTokenWithHandler:)]) { - [_callOptions.authTokenProvider getTokenWithHandler:tokenHandler]; - } - } + }]; } else { [self startCallWithWriteable:writeable]; } diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.h b/src/objective-c/GRPCClient/GRPCCallOptions.h index b866f268ee1..b5bf4c9eb6c 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.h +++ b/src/objective-c/GRPCClient/GRPCCallOptions.h @@ -60,22 +60,12 @@ typedef NS_ENUM(NSUInteger, GRPCTransportType) { /** * Implement this protocol to provide a token to gRPC when a call is initiated. */ -@protocol GRPCAuthorizationProtocol - -@optional +@protocol GRPCAuthorizationProtocol /** * This method is called when gRPC is about to start the call. When OAuth token is acquired, * \a handler is expected to be called with \a token being the new token to be used for this call. */ -- (void)provideTokenToHandler:(void (^)(NSString *_Nullable token))handler; - -/** - * This method is deprecated. Please use \a provideTokenToHandler. - * - * This method is called when gRPC is about to start the call. When OAuth token is acquired, - * \a handler is expected to be called with \a token being the new token to be used for this call. - */ - (void)getTokenWithHandler:(void (^)(NSString *_Nullable token))handler; @end diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index abf224c3cfd..48a38bd35ac 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -175,7 +175,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } - (void)writeMessage:(GPBMessage *)message { - NSAssert([message isKindOfClass:[GPBMessage class]], @"Parameter message must be a GPBMessage"); + NSAssert([message isKindOfClass:[GPBMessage class]]); if (![message isKindOfClass:[GPBMessage class]]) { NSLog(@"Failed to send a message that is non-proto."); return; diff --git a/src/objective-c/tests/APIv2Tests/APIv2Tests.m b/src/objective-c/tests/APIv2Tests/APIv2Tests.m index fd472aafebd..ca7bf472830 100644 --- a/src/objective-c/tests/APIv2Tests/APIv2Tests.m +++ b/src/objective-c/tests/APIv2Tests/APIv2Tests.m @@ -241,7 +241,7 @@ static const NSTimeInterval kTestTimeout = 16; [self waitForExpectationsWithTimeout:kTestTimeout handler:nil]; } -- (void)provideTokenToHandler:(void (^)(NSString *token))handler { +- (void)getTokenWithHandler:(void (^)(NSString *token))handler { dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); dispatch_sync(queue, ^{ handler(@"test-access-token"); From 72dc62ee2e20919b98939ee2e6337fd63a988f48 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 19 Dec 2018 10:30:54 -0800 Subject: [PATCH 254/375] Revert "Try earlier APIv2Tests" This reverts commit 3f57e3451bf4a3687e70e92fc218ea25ff7a17c9. --- src/objective-c/tests/run_tests.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh index aab80ded61b..f075d9baadd 100755 --- a/src/objective-c/tests/run_tests.sh +++ b/src/objective-c/tests/run_tests.sh @@ -176,7 +176,7 @@ xcodebuild \ echo "TIME: $(date)" xcodebuild \ -workspace Tests.xcworkspace \ - -scheme APIv2Tests \ + -scheme ChannelTests \ -destination name="iPhone 8" \ test \ | egrep -v "$XCODEBUILD_FILTER" \ @@ -186,12 +186,11 @@ xcodebuild \ echo "TIME: $(date)" xcodebuild \ -workspace Tests.xcworkspace \ - -scheme ChannelTests \ - -destination name="iPhone 8" \ + -scheme APIv2Tests \ + -destination name="iPhone X" \ test \ | egrep -v "$XCODEBUILD_FILTER" \ | egrep -v '^$' \ | egrep -v "(GPBDictionary|GPBArray)" - - exit 0 From 92123a4a333719fa3aa55b3db9f36c136e108a47 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 19 Dec 2018 10:42:31 -0800 Subject: [PATCH 255/375] Rebuild APIv2Tests --- .../tests/Tests.xcodeproj/project.pbxproj | 398 +++++++++--------- .../xcschemes/APIv2Tests.xcscheme | 8 +- src/objective-c/tests/run_tests.sh | 2 +- 3 files changed, 208 insertions(+), 200 deletions(-) diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj index 6f24d3512f8..47b79a05345 100644 --- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj +++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj @@ -16,7 +16,7 @@ 333E8FC01C8285B7C547D799 /* libPods-InteropTestsLocalCleartext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD346DB2C23F676C4842F3FF /* libPods-InteropTestsLocalCleartext.a */; }; 5E0282E9215AA697007AC99D /* UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E0282E8215AA697007AC99D /* UnitTests.m */; }; 5E0282EB215AA697007AC99D /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; - 5E10F5AA218CB0D2008BAB68 /* APIv2Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E10F5A9218CB0D2008BAB68 /* APIv2Tests.m */; }; + 5E3B95A521CAC6C500C0A151 /* APIv2Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E3B95A421CAC6C500C0A151 /* APIv2Tests.m */; }; 5E7D71AD210954A8001EA6BA /* TestCertificates.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */; }; 5E7D71B5210B9EC9001EA6BA /* InteropTestsCallOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E7D71B4210B9EC9001EA6BA /* InteropTestsCallOptions.m */; }; 5E7D71B7210B9EC9001EA6BA /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; }; @@ -66,10 +66,10 @@ 6C1A3F81CCF7C998B4813EFD /* libPods-InteropTestsCallOptions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF3FC2CFFE7B0961823BC740 /* libPods-InteropTestsCallOptions.a */; }; 886717A79EFF774F356798E6 /* libPods-InteropTestsMultipleChannels.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 355D0E30AD224763BC9519F4 /* libPods-InteropTestsMultipleChannels.a */; }; 91D4B3C85B6D8562F409CB48 /* libPods-InteropTestsLocalSSLCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F3AB031E0E26AC8EF30A2A2A /* libPods-InteropTestsLocalSSLCFStream.a */; }; + 98478C9F42329DF769A45B6C /* libPods-APIv2Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6AD69CACF67505B0F028E92 /* libPods-APIv2Tests.a */; }; BC111C80CBF7068B62869352 /* libPods-InteropTestsRemoteCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F44AC3F44E3491A8C0D890FE /* libPods-InteropTestsRemoteCFStream.a */; }; C3D6F4270A2FFF634D8849ED /* libPods-InteropTestsLocalCleartextCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BDA4BA011779D5D25B5618C /* libPods-InteropTestsLocalCleartextCFStream.a */; }; CCF5C0719EF608276AE16374 /* libPods-UnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */; }; - E7F4C80FC8FC667B7447BFE7 /* libPods-APIv2Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6AD69CACF67505B0F028E92 /* libPods-APIv2Tests.a */; }; F15EF7852DC70770EFDB1D2C /* libPods-AllTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAE086D5B470DA367D415AB0 /* libPods-AllTests.a */; }; /* End PBXBuildFile section */ @@ -212,9 +212,9 @@ 5E0282E6215AA697007AC99D /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5E0282E8215AA697007AC99D /* UnitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UnitTests.m; sourceTree = ""; }; 5E0282EA215AA697007AC99D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 5E10F5A7218CB0D1008BAB68 /* APIv2Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = APIv2Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 5E10F5A9218CB0D2008BAB68 /* APIv2Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = APIv2Tests.m; sourceTree = ""; }; - 5E10F5AB218CB0D2008BAB68 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 5E3B95A221CAC6C500C0A151 /* APIv2Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = APIv2Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 5E3B95A421CAC6C500C0A151 /* APIv2Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = APIv2Tests.m; sourceTree = ""; }; + 5E3B95A621CAC6C500C0A151 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 5E7D71B2210B9EC8001EA6BA /* InteropTestsCallOptions.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = InteropTestsCallOptions.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5E7D71B4210B9EC9001EA6BA /* InteropTestsCallOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InteropTestsCallOptions.m; sourceTree = ""; }; 5E7D71B6210B9EC9001EA6BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -313,11 +313,11 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5E10F5A4218CB0D1008BAB68 /* Frameworks */ = { + 5E3B959F21CAC6C500C0A151 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - E7F4C80FC8FC667B7447BFE7 /* libPods-APIv2Tests.a in Frameworks */, + 98478C9F42329DF769A45B6C /* libPods-APIv2Tests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -561,11 +561,11 @@ path = UnitTests; sourceTree = ""; }; - 5E10F5A8218CB0D1008BAB68 /* APIv2Tests */ = { + 5E3B95A321CAC6C500C0A151 /* APIv2Tests */ = { isa = PBXGroup; children = ( - 5E10F5A9218CB0D2008BAB68 /* APIv2Tests.m */, - 5E10F5AB218CB0D2008BAB68 /* Info.plist */, + 5E3B95A421CAC6C500C0A151 /* APIv2Tests.m */, + 5E3B95A621CAC6C500C0A151 /* Info.plist */, ); path = APIv2Tests; sourceTree = ""; @@ -636,7 +636,7 @@ 5EB2A2F62109284500EB4B69 /* InteropTestsMultipleChannels */, 5E7D71B3210B9EC9001EA6BA /* InteropTestsCallOptions */, 5E0282E7215AA697007AC99D /* UnitTests */, - 5E10F5A8218CB0D1008BAB68 /* APIv2Tests */, + 5E3B95A321CAC6C500C0A151 /* APIv2Tests */, 635697C81B14FC11007A7283 /* Products */, 51E4650F34F854F41FF053B3 /* Pods */, 136D535E19727099B941D7B1 /* Frameworks */, @@ -662,7 +662,7 @@ 5EB2A2F52109284500EB4B69 /* InteropTestsMultipleChannels.xctest */, 5E7D71B2210B9EC8001EA6BA /* InteropTestsCallOptions.xctest */, 5E0282E6215AA697007AC99D /* UnitTests.xctest */, - 5E10F5A7218CB0D1008BAB68 /* APIv2Tests.xctest */, + 5E3B95A221CAC6C500C0A151 /* APIv2Tests.xctest */, ); name = Products; sourceTree = ""; @@ -715,15 +715,15 @@ productReference = 5E0282E6215AA697007AC99D /* UnitTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - 5E10F5A6218CB0D1008BAB68 /* APIv2Tests */ = { + 5E3B95A121CAC6C500C0A151 /* APIv2Tests */ = { isa = PBXNativeTarget; - buildConfigurationList = 5E10F5B0218CB0D2008BAB68 /* Build configuration list for PBXNativeTarget "APIv2Tests" */; + buildConfigurationList = 5E3B95A721CAC6C500C0A151 /* Build configuration list for PBXNativeTarget "APIv2Tests" */; buildPhases = ( - 031ADD72298D6C6979CB06DB /* [CP] Check Pods Manifest.lock */, - 5E10F5A3218CB0D1008BAB68 /* Sources */, - 5E10F5A4218CB0D1008BAB68 /* Frameworks */, - 5E10F5A5218CB0D1008BAB68 /* Resources */, - FBB92A8B11C52512E67791E8 /* [CP] Copy Pods Resources */, + EDDD3FA856BCA3443ED36D1E /* [CP] Check Pods Manifest.lock */, + 5E3B959E21CAC6C500C0A151 /* Sources */, + 5E3B959F21CAC6C500C0A151 /* Frameworks */, + 5E3B95A021CAC6C500C0A151 /* Resources */, + C17B826BBD02FDD4A5F355AF /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -731,7 +731,7 @@ ); name = APIv2Tests; productName = APIv2Tests; - productReference = 5E10F5A7218CB0D1008BAB68 /* APIv2Tests.xctest */; + productReference = 5E3B95A221CAC6C500C0A151 /* APIv2Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 5E7D71B1210B9EC8001EA6BA /* InteropTestsCallOptions */ = { @@ -1043,7 +1043,7 @@ CreatedOnToolsVersion = 9.2; ProvisioningStyle = Automatic; }; - 5E10F5A6218CB0D1008BAB68 = { + 5E3B95A121CAC6C500C0A151 = { CreatedOnToolsVersion = 10.0; ProvisioningStyle = Automatic; }; @@ -1128,7 +1128,7 @@ 5EB2A2F42109284500EB4B69 /* InteropTestsMultipleChannels */, 5E7D71B1210B9EC8001EA6BA /* InteropTestsCallOptions */, 5E0282E5215AA697007AC99D /* UnitTests */, - 5E10F5A6218CB0D1008BAB68 /* APIv2Tests */, + 5E3B95A121CAC6C500C0A151 /* APIv2Tests */, ); }; /* End PBXProject section */ @@ -1141,7 +1141,7 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5E10F5A5218CB0D1008BAB68 /* Resources */ = { + 5E3B95A021CAC6C500C0A151 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -1271,24 +1271,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 031ADD72298D6C6979CB06DB /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-APIv2Tests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; 0617B5294978A95BEBBFF733 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1721,6 +1703,28 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + C17B826BBD02FDD4A5F355AF /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + ); + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; C2E09DC4BD239F71160F0CC1 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1793,25 +1797,29 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - F07941C0BAF6A7C67AA60C48 /* [CP] Check Pods Manifest.lock */ = { + EDDD3FA856BCA3443ED36D1E /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-UnitTests-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-APIv2Tests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - F3D5B2CDA172580341682830 /* [CP] Check Pods Manifest.lock */ = { + F07941C0BAF6A7C67AA60C48 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1822,14 +1830,14 @@ ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-InteropTestsLocalSSLCFStream-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-UnitTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - F58F17E425446B15028B9F74 /* [CP] Check Pods Manifest.lock */ = { + F3D5B2CDA172580341682830 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1840,29 +1848,29 @@ ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-CoreCronetEnd2EndTests-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-InteropTestsLocalSSLCFStream-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - FBB92A8B11C52512E67791E8 /* [CP] Copy Pods Resources */ = { + F58F17E425446B15028B9F74 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${SRCROOT}/Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); - name = "[CP] Copy Pods Resources"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle", + "$(DERIVED_FILE_DIR)/Pods-CoreCronetEnd2EndTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests-resources.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -1876,11 +1884,11 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5E10F5A3218CB0D1008BAB68 /* Sources */ = { + 5E3B959E21CAC6C500C0A151 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 5E10F5AA218CB0D2008BAB68 /* APIv2Tests.m in Sources */, + 5E3B95A521CAC6C500C0A151 /* APIv2Tests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2207,141 +2215,6 @@ }; name = Release; }; - 5E10F5AC218CB0D2008BAB68 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1286B30AD74CB64CD91FB17D /* Pods-APIv2Tests.debug.xcconfig */; - buildSettings = { - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = APIv2Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 5E10F5AD218CB0D2008BAB68 /* Test */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 51F2A64B7AADBA1B225B132E /* Pods-APIv2Tests.test.xcconfig */; - buildSettings = { - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = APIv2Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Test; - }; - 5E10F5AE218CB0D2008BAB68 /* Cronet */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8C233E85C3EB45B3CAE52EDF /* Pods-APIv2Tests.cronet.xcconfig */; - buildSettings = { - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = APIv2Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Cronet; - }; - 5E10F5AF218CB0D2008BAB68 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 12B238CD1702393C2BA5DE80 /* Pods-APIv2Tests.release.xcconfig */; - buildSettings = { - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = APIv2Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; 5E1228981E4D400F00E8504F /* Test */ = { isa = XCBuildConfiguration; buildSettings = { @@ -2550,6 +2423,141 @@ }; name = Test; }; + 5E3B95A821CAC6C500C0A151 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1286B30AD74CB64CD91FB17D /* Pods-APIv2Tests.debug.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = APIv2Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 5E3B95A921CAC6C500C0A151 /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 51F2A64B7AADBA1B225B132E /* Pods-APIv2Tests.test.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = APIv2Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Test; + }; + 5E3B95AA21CAC6C500C0A151 /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8C233E85C3EB45B3CAE52EDF /* Pods-APIv2Tests.cronet.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = APIv2Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Cronet; + }; + 5E3B95AB21CAC6C500C0A151 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 12B238CD1702393C2BA5DE80 /* Pods-APIv2Tests.release.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = APIv2Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; 5E7D71BB210B9EC9001EA6BA /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 3A98DF08852F60AF1D96481D /* Pods-InteropTestsCallOptions.debug.xcconfig */; @@ -3892,13 +3900,13 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 5E10F5B0218CB0D2008BAB68 /* Build configuration list for PBXNativeTarget "APIv2Tests" */ = { + 5E3B95A721CAC6C500C0A151 /* Build configuration list for PBXNativeTarget "APIv2Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 5E10F5AC218CB0D2008BAB68 /* Debug */, - 5E10F5AD218CB0D2008BAB68 /* Test */, - 5E10F5AE218CB0D2008BAB68 /* Cronet */, - 5E10F5AF218CB0D2008BAB68 /* Release */, + 5E3B95A821CAC6C500C0A151 /* Debug */, + 5E3B95A921CAC6C500C0A151 /* Test */, + 5E3B95AA21CAC6C500C0A151 /* Cronet */, + 5E3B95AB21CAC6C500C0A151 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/APIv2Tests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/APIv2Tests.xcscheme index b444ddc2b67..e0d1d1fdcac 100644 --- a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/APIv2Tests.xcscheme +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/APIv2Tests.xcscheme @@ -14,7 +14,7 @@ buildForAnalyzing = "NO"> @@ -32,7 +32,7 @@ skipped = "NO"> @@ -55,7 +55,7 @@ @@ -73,7 +73,7 @@ diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh index f075d9baadd..e8c3e6ec2a4 100755 --- a/src/objective-c/tests/run_tests.sh +++ b/src/objective-c/tests/run_tests.sh @@ -187,7 +187,7 @@ echo "TIME: $(date)" xcodebuild \ -workspace Tests.xcworkspace \ -scheme APIv2Tests \ - -destination name="iPhone X" \ + -destination name="iPhone 8" \ test \ | egrep -v "$XCODEBUILD_FILTER" \ | egrep -v '^$' \ From ad8f04feca10075982208ef8a4c7ce92900d5077 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 19 Dec 2018 12:57:07 -0800 Subject: [PATCH 256/375] Fix compiler error --- src/core/ext/transport/chttp2/transport/chttp2_transport.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 3b7c48a72ca..9e03c90ccb9 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -568,8 +568,8 @@ static void close_transport_locked(grpc_chttp2_transport* t, cancel_pings(t, GRPC_ERROR_REF(error)); // ContextList::Execute follows semantics of a callback function and does not // need a ref on error - grpc_core::ContextList::Execute(cl, nullptr, error); - cl = nullptr; + grpc_core::ContextList::Execute(t->cl, nullptr, error); + t->cl = nullptr; if (t->closed_with_error == GRPC_ERROR_NONE) { if (!grpc_error_has_clear_grpc_status(error)) { error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, From 1876d0d3669147e68c64d7916082de64025e9b6f Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 19 Dec 2018 13:06:34 -0800 Subject: [PATCH 257/375] ProtoRPC bug --- src/objective-c/ProtoRPC/ProtoRPC.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 48a38bd35ac..03e6839c5a0 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -175,7 +175,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } - (void)writeMessage:(GPBMessage *)message { - NSAssert([message isKindOfClass:[GPBMessage class]]); + NSAssert([message isKindOfClass:[GPBMessage class]], @"Parameter message must be a GPBMessage"); if (![message isKindOfClass:[GPBMessage class]]) { NSLog(@"Failed to send a message that is non-proto."); return; @@ -199,7 +199,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing - (void)didReceiveInitialMetadata:(NSDictionary *)initialMetadata { @synchronized(self) { - if (initialMetadata != nil && [_handler respondsToSelector:@selector(initialMetadata:)]) { + if (initialMetadata != nil && [_handler respondsToSelector:@selector(didReceiveInitialMetadata:)]) { dispatch_async(_dispatchQueue, ^{ id copiedHandler = nil; @synchronized(self) { From 0de27b5d2955c2d19a998e133580b721836676da Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 19 Dec 2018 13:08:04 -0800 Subject: [PATCH 258/375] More fix ProtoRPC --- src/objective-c/ProtoRPC/ProtoRPC.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 03e6839c5a0..053eaf47f2f 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -235,7 +235,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } [copiedHandler didCloseWithTrailingMetadata:nil - error:ErrorForBadProto(message, _responseClass, error)]; + error:ErrorForBadProto(message, self->_responseClass, error)]; }); [_call cancel]; _call = nil; From c5f84c5cb8830ad5ac4a9f097804308adce204be Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 19 Dec 2018 14:09:56 -0800 Subject: [PATCH 259/375] Batch fix --- .../GRPCClient/private/GRPCWrappedCall.m | 4 ++++ src/objective-c/ProtoRPC/ProtoService.h | 6 +++--- src/objective-c/ProtoRPC/ProtoService.m | 13 +++++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 1a848a4b7c3..7d7e77f6ba0 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -292,6 +292,10 @@ gpr_free(ops_array); NSAssert(error == GRPC_CALL_OK, @"Error starting a batch of operations: %i", error); + // To avoid compiler complaint when NSAssert is disabled. + if (error != GRPC_CALL_OK) { + return; + } } } } diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h index d76e96ce2a6..900ec8d0e1e 100644 --- a/src/objective-c/ProtoRPC/ProtoService.h +++ b/src/objective-c/ProtoRPC/ProtoService.h @@ -25,7 +25,7 @@ @class GRPCProtoCall; @class GRPCUnaryProtoCall; @class GRPCStreamingProtoCall; -@protocol GRPCProtoResponseCallbacks; +@protocol GRPCProtoResponseHandler; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnullability-completeness" @@ -49,12 +49,12 @@ __attribute__((deprecated("Please use GRPCProtoService."))) @interface ProtoServ - (nullable GRPCUnaryProtoCall *)RPCToMethod:(nonnull NSString *)method message:(nonnull id)message - responseHandler:(nonnull id)handler + responseHandler:(nonnull id)handler callOptions:(nullable GRPCCallOptions *)callOptions responseClass:(nonnull Class)responseClass; - (nullable GRPCStreamingProtoCall *)RPCToMethod:(nonnull NSString *)method - responseHandler:(nonnull id)handler + responseHandler:(nonnull id)handler callOptions:(nullable GRPCCallOptions *)callOptions responseClass:(nonnull Class)responseClass; diff --git a/src/objective-c/ProtoRPC/ProtoService.m b/src/objective-c/ProtoRPC/ProtoService.m index b7c7fadbcf0..80a1f2f226c 100644 --- a/src/objective-c/ProtoRPC/ProtoService.m +++ b/src/objective-c/ProtoRPC/ProtoService.m @@ -58,11 +58,14 @@ return self; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +// Do not call designated initializer here due to nullability incompatibility. This method is from +// old API and does not assert on nullability of the parameters. + - (instancetype)initWithHost:(NSString *)host packageName:(NSString *)packageName serviceName:(NSString *)serviceName { - // Do not call designated initializer here due to nullability incompatibility. This method is from - // old API and does not assert on nullability of the parameters. if ((self = [super init])) { _host = [host copy]; _packageName = [packageName copy]; @@ -72,6 +75,8 @@ return self; } +#pragma clang diagnostic pop + - (GRPCProtoCall *)RPCToMethod:(NSString *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass @@ -87,7 +92,7 @@ - (GRPCUnaryProtoCall *)RPCToMethod:(NSString *)method message:(id)message - responseHandler:(id)handler + responseHandler:(id)handler callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass { GRPCProtoMethod *methodName = @@ -104,7 +109,7 @@ } - (GRPCStreamingProtoCall *)RPCToMethod:(NSString *)method - responseHandler:(id)handler + responseHandler:(id)handler callOptions:(GRPCCallOptions *)callOptions responseClass:(Class)responseClass { GRPCProtoMethod *methodName = From f7ca97a6fedc4d20aab6a09b26b143a8996c9b48 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 19 Dec 2018 14:15:12 -0800 Subject: [PATCH 260/375] clang-format --- src/objective-c/ProtoRPC/ProtoRPC.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 053eaf47f2f..0ab96a5ba2b 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -199,7 +199,8 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing - (void)didReceiveInitialMetadata:(NSDictionary *)initialMetadata { @synchronized(self) { - if (initialMetadata != nil && [_handler respondsToSelector:@selector(didReceiveInitialMetadata:)]) { + if (initialMetadata != nil && + [_handler respondsToSelector:@selector(didReceiveInitialMetadata:)]) { dispatch_async(_dispatchQueue, ^{ id copiedHandler = nil; @synchronized(self) { From c72a0af7816be07d3bec926f86288f9f97cb6cbd Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 19 Dec 2018 16:19:48 -0800 Subject: [PATCH 261/375] change deployment target --- src/objective-c/tests/Tests.xcodeproj/project.pbxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj index 47b79a05345..b6762cc6001 100644 --- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj +++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj @@ -2449,7 +2449,7 @@ ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = APIv2Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -2483,7 +2483,7 @@ CODE_SIGN_STYLE = Automatic; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = APIv2Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; @@ -2516,7 +2516,7 @@ CODE_SIGN_STYLE = Automatic; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = APIv2Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; @@ -2549,7 +2549,7 @@ CODE_SIGN_STYLE = Automatic; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = APIv2Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = io.grpc.APIv2Tests; From 6cf4622cd1a721704c70be2160b6454937771141 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 19 Dec 2018 23:15:26 -0800 Subject: [PATCH 262/375] provide host --- src/objective-c/tests/run_tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh index e8c3e6ec2a4..8402809c097 100755 --- a/src/objective-c/tests/run_tests.sh +++ b/src/objective-c/tests/run_tests.sh @@ -188,6 +188,7 @@ xcodebuild \ -workspace Tests.xcworkspace \ -scheme APIv2Tests \ -destination name="iPhone 8" \ + HOST_PORT_LOCAL=localhost:5050 \ test \ | egrep -v "$XCODEBUILD_FILTER" \ | egrep -v '^$' \ From 291b4f363bbf7226eb7a3bbd7ad620f5be67c625 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 20 Dec 2018 09:52:26 -0800 Subject: [PATCH 263/375] More test fix --- src/objective-c/GRPCClient/GRPCCall.m | 2 +- src/objective-c/tests/run_tests.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 9bcacac0dfc..b0412cddb09 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -69,7 +69,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; @implementation GRPCRequestOptions - (instancetype)initWithHost:(NSString *)host path:(NSString *)path safety:(GRPCCallSafety)safety { - NSAssert(host.length != 0 && path.length != 0, @"Host and Path cannot be empty"); + NSAssert(host.length != 0 && path.length != 0, @"host and path cannot be empty"); if (host.length == 0 || path.length == 0) { return nil; } diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh index 8402809c097..f6fea96920e 100755 --- a/src/objective-c/tests/run_tests.sh +++ b/src/objective-c/tests/run_tests.sh @@ -189,6 +189,7 @@ xcodebuild \ -scheme APIv2Tests \ -destination name="iPhone 8" \ HOST_PORT_LOCAL=localhost:5050 \ + HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \ test \ | egrep -v "$XCODEBUILD_FILTER" \ | egrep -v '^$' \ From 05b61a5199dd69e33011ed0e677d9d43a77c01a4 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Thu, 20 Dec 2018 12:10:53 -0800 Subject: [PATCH 264/375] Use Pylint to lint gRPC Python examples --- .pylintrc-examples | 100 ++++++++++++++++++ .../helloworld/greeter_client_with_options.py | 2 +- tools/distrib/pylint_code.sh | 6 ++ 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 .pylintrc-examples diff --git a/.pylintrc-examples b/.pylintrc-examples new file mode 100644 index 00000000000..9480d6ea56a --- /dev/null +++ b/.pylintrc-examples @@ -0,0 +1,100 @@ +[MASTER] +ignore= + src/python/grpcio/grpc/beta, + src/python/grpcio/grpc/framework, + src/python/grpcio/grpc/framework/common, + src/python/grpcio/grpc/framework/foundation, + src/python/grpcio/grpc/framework/interfaces, + +[VARIABLES] + +# TODO(https://github.com/PyCQA/pylint/issues/1345): How does the inspection +# not include "unused_" and "ignored_" by default? +dummy-variables-rgx=^ignored_|^unused_ + +[DESIGN] + +# NOTE(nathaniel): Not particularly attached to this value; it just seems to +# be what works for us at the moment (excepting the dead-code-walking Beta +# API). +max-args=6 + +[MISCELLANEOUS] + +# NOTE(nathaniel): We are big fans of "TODO(): " and +# "NOTE(): ". We do not allow "TODO:", +# "TODO():", "FIXME:", or anything else. +notes=FIXME,XXX + +[MESSAGES CONTROL] + +disable= + # -- START OF EXAMPLE-SPECIFIC SUPPRESSIONS -- + no-self-use, + unused-argument, + unused-variable, + # -- END OF EXAMPLE-SPECIFIC SUPPRESSIONS -- + + # TODO(https://github.com/PyCQA/pylint/issues/59#issuecomment-283774279): + # Enable cyclic-import after a 1.7-or-later pylint release that + # recognizes our disable=cyclic-import suppressions. + cyclic-import, + # TODO(https://github.com/grpc/grpc/issues/8622): Enable this after the + # Beta API is removed. + duplicate-code, + # TODO(https://github.com/grpc/grpc/issues/261): Doesn't seem to + # understand enum and concurrent.futures; look into this later with the + # latest pylint version. + import-error, + # TODO(https://github.com/grpc/grpc/issues/261): Enable this one. + # Should take a little configuration but not much. + invalid-name, + # TODO(https://github.com/grpc/grpc/issues/261): This doesn't seem to + # work for now? Try with a later pylint? + locally-disabled, + # NOTE(nathaniel): What even is this? *Enabling* an inspection results + # in a warning? How does that encourage more analysis and coverage? + locally-enabled, + # NOTE(nathaniel): We don't write doc strings for most private code + # elements. + missing-docstring, + # NOTE(nathaniel): In numeric comparisons it is better to have the + # lesser (or lesser-or-equal-to) quantity on the left when the + # expression is true than it is to worry about which is an identifier + # and which a literal value. + misplaced-comparison-constant, + # NOTE(nathaniel): Our completely abstract interface classes don't have + # constructors. + no-init, + # TODO(https://github.com/grpc/grpc/issues/261): Doesn't yet play + # nicely with some of our code being implemented in Cython. Maybe in a + # later version? + no-name-in-module, + # TODO(https://github.com/grpc/grpc/issues/261): Suppress these where + # the odd shape of the authentication portion of the API forces them on + # us and enable everywhere else. + protected-access, + # NOTE(nathaniel): Pylint and I will probably never agree on this. + too-few-public-methods, + # NOTE(nathaniel): Pylint and I wil probably never agree on this for + # private classes. For public classes maybe? + too-many-instance-attributes, + # NOTE(nathaniel): Some of our modules have a lot of lines... of + # specification and documentation. Maybe if this were + # lines-of-code-based we would use it. + too-many-lines, + # TODO(https://github.com/grpc/grpc/issues/261): Maybe we could have + # this one if we extracted just a few more helper functions... + too-many-nested-blocks, + # TODO(https://github.com/grpc/grpc/issues/261): Disable unnecessary + # super-init requirement for abstract class implementations for now. + super-init-not-called, + # NOTE(nathaniel): A single statement that always returns program + # control is better than two statements the first of which sometimes + # returns program control and the second of which always returns + # program control. Probably generally, but definitely in the cases of + # if:/else: and for:/else:. + useless-else-on-loop, + no-else-return, + # NOTE(lidiz): Python 3 make object inheritance default, but not PY2 + useless-object-inheritance, diff --git a/examples/python/helloworld/greeter_client_with_options.py b/examples/python/helloworld/greeter_client_with_options.py index d15871b5195..e9ab5508ddd 100644 --- a/examples/python/helloworld/greeter_client_with_options.py +++ b/examples/python/helloworld/greeter_client_with_options.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""The Python implementation of the GRPC helloworld.Greeter client with channel options and call timeout parameters.""" +"""gRPC Python helloworld.Greeter client with channel options and call timeout parameters.""" from __future__ import print_function import logging diff --git a/tools/distrib/pylint_code.sh b/tools/distrib/pylint_code.sh index 00507775031..abb37dde0ed 100755 --- a/tools/distrib/pylint_code.sh +++ b/tools/distrib/pylint_code.sh @@ -48,4 +48,10 @@ for dir in "${TEST_DIRS[@]}"; do $PYTHON -m pylint --rcfile=.pylintrc-tests -rn "$dir" || EXIT=1 done +find examples/python \ + -iname "*.py" \ + -not -name "*_pb2.py" \ + -not -name "*_pb2_grpc.py" \ + | xargs $PYTHON -m pylint --rcfile=.pylintrc-examples -rn + exit $EXIT From 30e1991bf93e010964ccaf326081398ed3cd4e4e Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 20 Dec 2018 13:22:48 -0800 Subject: [PATCH 265/375] Update context list test --- test/core/transport/chttp2/context_list_test.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/core/transport/chttp2/context_list_test.cc b/test/core/transport/chttp2/context_list_test.cc index edbe658a89f..0379eaaee4c 100644 --- a/test/core/transport/chttp2/context_list_test.cc +++ b/test/core/transport/chttp2/context_list_test.cc @@ -36,8 +36,12 @@ namespace { const uint32_t kByteOffset = 123; -void TestExecuteFlushesListVerifier(void* arg, grpc_core::Timestamps* ts) { +void* DummyArgsCopier(void* arg) { return arg; } + +void TestExecuteFlushesListVerifier(void* arg, grpc_core::Timestamps* ts, + grpc_error* error) { ASSERT_NE(arg, nullptr); + EXPECT_EQ(error, GRPC_ERROR_NONE); EXPECT_EQ(ts->byte_offset, kByteOffset); gpr_atm* done = reinterpret_cast(arg); gpr_atm_rel_store(done, static_cast(1)); @@ -52,6 +56,7 @@ void discard_write(grpc_slice slice) {} TEST(ContextList, ExecuteFlushesList) { grpc_core::ContextList* list = nullptr; grpc_http2_set_write_timestamps_callback(TestExecuteFlushesListVerifier); + grpc_http2_set_fn_get_copied_context(DummyArgsCopier); const int kNumElems = 5; grpc_core::ExecCtx exec_ctx; grpc_stream_refcount ref; From b09ed93d02197235471e6e65df2df2cbeb506f50 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 20 Dec 2018 16:16:00 -0800 Subject: [PATCH 266/375] Revert changes to Context list cleanup --- .../transport/chttp2/transport/chttp2_transport.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 9e03c90ccb9..78833723a2c 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -170,6 +170,14 @@ grpc_chttp2_transport::~grpc_chttp2_transport() { grpc_slice_buffer_destroy_internal(&outbuf); grpc_chttp2_hpack_compressor_destroy(&hpack_compressor); + grpc_error* error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport destroyed"); + // ContextList::Execute follows semantics of a callback function and does not + // take a ref on error + grpc_core::ContextList::Execute(t->cl, nullptr, error); + GRPC_ERROR_UNREF(error); + t->cl = nullptr; + grpc_slice_buffer_destroy_internal(&read_buffer); grpc_chttp2_hpack_parser_destroy(&hpack_parser); grpc_chttp2_goaway_parser_destroy(&goaway_parser); @@ -566,10 +574,6 @@ static void close_transport_locked(grpc_chttp2_transport* t, grpc_error* error) { end_all_the_calls(t, GRPC_ERROR_REF(error)); cancel_pings(t, GRPC_ERROR_REF(error)); - // ContextList::Execute follows semantics of a callback function and does not - // need a ref on error - grpc_core::ContextList::Execute(t->cl, nullptr, error); - t->cl = nullptr; if (t->closed_with_error == GRPC_ERROR_NONE) { if (!grpc_error_has_clear_grpc_status(error)) { error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, From 15460eb3c9f58ba7f8a4db9bebff0aaa00b57d27 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 21 Dec 2018 13:36:59 -0800 Subject: [PATCH 267/375] Fix error --- src/core/ext/transport/chttp2/transport/chttp2_transport.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 78833723a2c..7f4627fa773 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -174,9 +174,9 @@ grpc_chttp2_transport::~grpc_chttp2_transport() { GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport destroyed"); // ContextList::Execute follows semantics of a callback function and does not // take a ref on error - grpc_core::ContextList::Execute(t->cl, nullptr, error); + grpc_core::ContextList::Execute(cl, nullptr, error); GRPC_ERROR_UNREF(error); - t->cl = nullptr; + cl = nullptr; grpc_slice_buffer_destroy_internal(&read_buffer); grpc_chttp2_hpack_parser_destroy(&hpack_parser); From 50eaf4671814f017ed44ce9a220025c87e1a1cc2 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Thu, 20 Dec 2018 17:35:12 -0800 Subject: [PATCH 268/375] Refactor benchmark initial channel wait for ready to be single threaded --- test/cpp/qps/client.h | 89 +++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 32 deletions(-) diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index 668d9419169..73f91eed2d8 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -429,13 +429,7 @@ class ClientImpl : public Client { config.server_targets(i % config.server_targets_size()), config, create_stub_, i); } - std::vector> connecting_threads; - for (auto& c : channels_) { - connecting_threads.emplace_back(c.WaitForReady()); - } - for (auto& t : connecting_threads) { - t->join(); - } + WaitForChannelsToConnect(); median_latency_collection_interval_seconds_ = config.median_latency_collection_interval_millis() / 1e3; ClientRequestCreator create_req(&request_, @@ -443,6 +437,61 @@ class ClientImpl : public Client { } virtual ~ClientImpl() {} + void WaitForChannelsToConnect() { + int connect_deadline_seconds = 10; + /* Allow optionally overriding connect_deadline in order + * to deal with benchmark environments in which the server + * can take a long time to become ready. */ + char* channel_connect_timeout_str = + gpr_getenv("QPS_WORKER_CHANNEL_CONNECT_TIMEOUT"); + if (channel_connect_timeout_str != nullptr && + strcmp(channel_connect_timeout_str, "") != 0) { + connect_deadline_seconds = atoi(channel_connect_timeout_str); + } + gpr_log(GPR_INFO, + "Waiting for up to %d seconds for all channels to connect", + connect_deadline_seconds); + gpr_free(channel_connect_timeout_str); + gpr_timespec connect_deadline = gpr_time_add( + gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_seconds(connect_deadline_seconds, GPR_TIMESPAN)); + CompletionQueue cq; + size_t num_remaining = 0; + for (auto& c : channels_) { + if (!c.is_inproc()) { + Channel* channel = c.get_channel(); + grpc_connectivity_state last_observed = channel->GetState(true); + if (last_observed == GRPC_CHANNEL_READY) { + gpr_log(GPR_INFO, "Channel %p connected!", channel); + } else { + num_remaining++; + channel->NotifyOnStateChange(last_observed, connect_deadline, &cq, + channel); + } + } + } + while (num_remaining > 0) { + bool ok = false; + void* tag = nullptr; + cq.Next(&tag, &ok); + Channel* channel = static_cast(tag); + if (!ok) { + gpr_log(GPR_ERROR, "Channel %p failed to connect within the deadline", + channel); + abort(); + } else { + grpc_connectivity_state last_observed = channel->GetState(true); + if (last_observed == GRPC_CHANNEL_READY) { + gpr_log(GPR_INFO, "Channel %p connected!", channel); + num_remaining--; + } else { + channel->NotifyOnStateChange(last_observed, connect_deadline, &cq, + channel); + } + } + } + } + protected: const int cores_; RequestType request_; @@ -485,31 +534,7 @@ class ClientImpl : public Client { } Channel* get_channel() { return channel_.get(); } StubType* get_stub() { return stub_.get(); } - - std::unique_ptr WaitForReady() { - return std::unique_ptr(new std::thread([this]() { - if (!is_inproc_) { - int connect_deadline = 10; - /* Allow optionally overriding connect_deadline in order - * to deal with benchmark environments in which the server - * can take a long time to become ready. */ - char* channel_connect_timeout_str = - gpr_getenv("QPS_WORKER_CHANNEL_CONNECT_TIMEOUT"); - if (channel_connect_timeout_str != nullptr && - strcmp(channel_connect_timeout_str, "") != 0) { - connect_deadline = atoi(channel_connect_timeout_str); - } - gpr_log(GPR_INFO, - "Waiting for up to %d seconds for the channel %p to connect", - connect_deadline, channel_.get()); - gpr_free(channel_connect_timeout_str); - GPR_ASSERT(channel_->WaitForConnected(gpr_time_add( - gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_seconds(connect_deadline, GPR_TIMESPAN)))); - gpr_log(GPR_INFO, "Channel %p connected!", channel_.get()); - } - })); - } + bool is_inproc() { return is_inproc_; } private: void set_channel_args(const ClientConfig& config, ChannelArguments* args) { From 2f029bade0cdadcfdd955773bd43cc2f061cd3f7 Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Wed, 19 Dec 2018 09:44:38 -0800 Subject: [PATCH 269/375] Clean up server and channel objects in tests --- .../health_check/_health_servicer_test.py | 8 +++-- .../reflection/_reflection_servicer_test.py | 8 +++-- .../grpcio_tests/tests/unit/_api_test.py | 1 + .../tests/unit/_auth_context_test.py | 6 ++-- .../tests/unit/_channel_connectivity_test.py | 6 +++- .../tests/unit/_channel_ready_future_test.py | 5 ++++ .../tests/unit/_compression_test.py | 5 ++++ .../tests/unit/_empty_message_test.py | 1 + .../unit/_error_message_encoding_test.py | 1 + .../tests/unit/_interceptor_test.py | 1 + .../tests/unit/_invalid_metadata_test.py | 3 ++ .../tests/unit/_invocation_defects_test.py | 1 + .../tests/unit/_metadata_code_details_test.py | 14 +++++---- .../tests/unit/_metadata_flags_test.py | 29 ++++++++++--------- .../grpcio_tests/tests/unit/_metadata_test.py | 1 + .../tests/unit/_reconnect_test.py | 2 ++ .../tests/unit/_resource_exhausted_test.py | 1 + .../grpcio_tests/tests/unit/_rpc_test.py | 1 + 18 files changed, 68 insertions(+), 26 deletions(-) diff --git a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py index 350b5eebe5b..c1d9436c2fa 100644 --- a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py +++ b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py @@ -39,8 +39,12 @@ class HealthServicerTest(unittest.TestCase): health_pb2_grpc.add_HealthServicer_to_server(servicer, self._server) self._server.start() - channel = grpc.insecure_channel('localhost:%d' % port) - self._stub = health_pb2_grpc.HealthStub(channel) + self._channel = grpc.insecure_channel('localhost:%d' % port) + self._stub = health_pb2_grpc.HealthStub(self._channel) + + def tearDown(self): + self._server.stop(None) + self._channel.close() def test_empty_service(self): request = health_pb2.HealthCheckRequest() diff --git a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py index bcd9e14a386..560f6d3ddb3 100644 --- a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py +++ b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py @@ -56,8 +56,12 @@ class ReflectionServicerTest(unittest.TestCase): port = self._server.add_insecure_port('[::]:0') self._server.start() - channel = grpc.insecure_channel('localhost:%d' % port) - self._stub = reflection_pb2_grpc.ServerReflectionStub(channel) + self._channel = grpc.insecure_channel('localhost:%d' % port) + self._stub = reflection_pb2_grpc.ServerReflectionStub(self._channel) + + def tearDown(self): + self._server.stop(None) + self._channel.close() def testFileByName(self): requests = ( diff --git a/src/python/grpcio_tests/tests/unit/_api_test.py b/src/python/grpcio_tests/tests/unit/_api_test.py index 427894bfe9f..0dc6a8718c3 100644 --- a/src/python/grpcio_tests/tests/unit/_api_test.py +++ b/src/python/grpcio_tests/tests/unit/_api_test.py @@ -101,6 +101,7 @@ class ChannelTest(unittest.TestCase): def test_secure_channel(self): channel_credentials = grpc.ssl_channel_credentials() channel = grpc.secure_channel('google.com:443', channel_credentials) + channel.close() if __name__ == '__main__': diff --git a/src/python/grpcio_tests/tests/unit/_auth_context_test.py b/src/python/grpcio_tests/tests/unit/_auth_context_test.py index b1b5bbdcab3..96c4e9ec76a 100644 --- a/src/python/grpcio_tests/tests/unit/_auth_context_test.py +++ b/src/python/grpcio_tests/tests/unit/_auth_context_test.py @@ -71,8 +71,8 @@ class AuthContextTest(unittest.TestCase): port = server.add_insecure_port('[::]:0') server.start() - channel = grpc.insecure_channel('localhost:%d' % port) - response = channel.unary_unary(_UNARY_UNARY)(_REQUEST) + with grpc.insecure_channel('localhost:%d' % port) as channel: + response = channel.unary_unary(_UNARY_UNARY)(_REQUEST) server.stop(None) auth_data = pickle.loads(response) @@ -98,6 +98,7 @@ class AuthContextTest(unittest.TestCase): channel_creds, options=_PROPERTY_OPTIONS) response = channel.unary_unary(_UNARY_UNARY)(_REQUEST) + channel.close() server.stop(None) auth_data = pickle.loads(response) @@ -132,6 +133,7 @@ class AuthContextTest(unittest.TestCase): options=_PROPERTY_OPTIONS) response = channel.unary_unary(_UNARY_UNARY)(_REQUEST) + channel.close() server.stop(None) auth_data = pickle.loads(response) diff --git a/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py b/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py index 727fb7d65fe..565bd39b3aa 100644 --- a/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py +++ b/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py @@ -75,6 +75,8 @@ class ChannelConnectivityTest(unittest.TestCase): channel.unsubscribe(callback.update) fifth_connectivities = callback.connectivities() + channel.close() + self.assertSequenceEqual((grpc.ChannelConnectivity.IDLE,), first_connectivities) self.assertNotIn(grpc.ChannelConnectivity.READY, second_connectivities) @@ -108,7 +110,8 @@ class ChannelConnectivityTest(unittest.TestCase): _ready_in_connectivities) second_callback.block_until_connectivities_satisfy( _ready_in_connectivities) - del channel + channel.close() + server.stop(None) self.assertSequenceEqual((grpc.ChannelConnectivity.IDLE,), first_connectivities) @@ -139,6 +142,7 @@ class ChannelConnectivityTest(unittest.TestCase): callback.block_until_connectivities_satisfy( _last_connectivity_is_not_ready) channel.unsubscribe(callback.update) + channel.close() self.assertFalse(thread_pool.was_used()) diff --git a/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py b/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py index 345460ef40d..46a4eb9bb60 100644 --- a/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py +++ b/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py @@ -60,6 +60,8 @@ class ChannelReadyFutureTest(unittest.TestCase): self.assertTrue(ready_future.done()) self.assertFalse(ready_future.running()) + channel.close() + def test_immediately_connectable_channel_connectivity(self): thread_pool = _thread_pool.RecordingThreadPool(max_workers=None) server = grpc.server(thread_pool, options=(('grpc.so_reuseport', 0),)) @@ -84,6 +86,9 @@ class ChannelReadyFutureTest(unittest.TestCase): self.assertFalse(ready_future.running()) self.assertFalse(thread_pool.was_used()) + channel.close() + server.stop(None) + if __name__ == '__main__': logging.basicConfig() diff --git a/src/python/grpcio_tests/tests/unit/_compression_test.py b/src/python/grpcio_tests/tests/unit/_compression_test.py index 876d8e827ea..87884a19dc0 100644 --- a/src/python/grpcio_tests/tests/unit/_compression_test.py +++ b/src/python/grpcio_tests/tests/unit/_compression_test.py @@ -77,6 +77,9 @@ class CompressionTest(unittest.TestCase): self._port = self._server.add_insecure_port('[::]:0') self._server.start() + def tearDown(self): + self._server.stop(None) + def testUnary(self): request = b'\x00' * 100 @@ -102,6 +105,7 @@ class CompressionTest(unittest.TestCase): response = multi_callable( request, metadata=[('grpc-internal-encoding-request', 'gzip')]) self.assertEqual(request, response) + compressed_channel.close() def testStreaming(self): request = b'\x00' * 100 @@ -115,6 +119,7 @@ class CompressionTest(unittest.TestCase): call = multi_callable(iter([request] * test_constants.STREAM_LENGTH)) for response in call: self.assertEqual(request, response) + compressed_channel.close() if __name__ == '__main__': diff --git a/src/python/grpcio_tests/tests/unit/_empty_message_test.py b/src/python/grpcio_tests/tests/unit/_empty_message_test.py index 3e8393b53c3..f27ea422d0c 100644 --- a/src/python/grpcio_tests/tests/unit/_empty_message_test.py +++ b/src/python/grpcio_tests/tests/unit/_empty_message_test.py @@ -96,6 +96,7 @@ class EmptyMessageTest(unittest.TestCase): def tearDown(self): self._server.stop(0) + self._channel.close() def testUnaryUnary(self): response = self._channel.unary_unary(_UNARY_UNARY)(_REQUEST) diff --git a/src/python/grpcio_tests/tests/unit/_error_message_encoding_test.py b/src/python/grpcio_tests/tests/unit/_error_message_encoding_test.py index 6c551df3ec4..81de1dae1d1 100644 --- a/src/python/grpcio_tests/tests/unit/_error_message_encoding_test.py +++ b/src/python/grpcio_tests/tests/unit/_error_message_encoding_test.py @@ -71,6 +71,7 @@ class ErrorMessageEncodingTest(unittest.TestCase): def tearDown(self): self._server.stop(0) + self._channel.close() def testMessageEncoding(self): for message in _UNICODE_ERROR_MESSAGES: diff --git a/src/python/grpcio_tests/tests/unit/_interceptor_test.py b/src/python/grpcio_tests/tests/unit/_interceptor_test.py index 99db0ac58b1..a647e5e720c 100644 --- a/src/python/grpcio_tests/tests/unit/_interceptor_test.py +++ b/src/python/grpcio_tests/tests/unit/_interceptor_test.py @@ -337,6 +337,7 @@ class InterceptorTest(unittest.TestCase): def tearDown(self): self._server.stop(None) self._server_pool.shutdown(wait=True) + self._channel.close() def testTripleRequestMessagesClientInterceptor(self): diff --git a/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py b/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py index 0ff49490d5f..7ed7c838936 100644 --- a/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py +++ b/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py @@ -62,6 +62,9 @@ class InvalidMetadataTest(unittest.TestCase): self._stream_unary = _stream_unary_multi_callable(self._channel) self._stream_stream = _stream_stream_multi_callable(self._channel) + def tearDown(self): + self._channel.close() + def testUnaryRequestBlockingUnaryResponse(self): request = b'\x07\x08' metadata = (('InVaLiD', 'UnaryRequestBlockingUnaryResponse'),) diff --git a/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py b/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py index 00949e22366..e89b521cc5c 100644 --- a/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py +++ b/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py @@ -215,6 +215,7 @@ class InvocationDefectsTest(unittest.TestCase): def tearDown(self): self._server.stop(0) + self._channel.close() def testIterableStreamRequestBlockingUnaryResponse(self): requests = [b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)] diff --git a/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py b/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py index 0dafab827a8..a63664ac5d0 100644 --- a/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py +++ b/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py @@ -198,8 +198,8 @@ class MetadataCodeDetailsTest(unittest.TestCase): port = self._server.add_insecure_port('[::]:0') self._server.start() - channel = grpc.insecure_channel('localhost:{}'.format(port)) - self._unary_unary = channel.unary_unary( + self._channel = grpc.insecure_channel('localhost:{}'.format(port)) + self._unary_unary = self._channel.unary_unary( '/'.join(( '', _SERVICE, @@ -208,17 +208,17 @@ class MetadataCodeDetailsTest(unittest.TestCase): request_serializer=_REQUEST_SERIALIZER, response_deserializer=_RESPONSE_DESERIALIZER, ) - self._unary_stream = channel.unary_stream('/'.join(( + self._unary_stream = self._channel.unary_stream('/'.join(( '', _SERVICE, _UNARY_STREAM, )),) - self._stream_unary = channel.stream_unary('/'.join(( + self._stream_unary = self._channel.stream_unary('/'.join(( '', _SERVICE, _STREAM_UNARY, )),) - self._stream_stream = channel.stream_stream( + self._stream_stream = self._channel.stream_stream( '/'.join(( '', _SERVICE, @@ -228,6 +228,10 @@ class MetadataCodeDetailsTest(unittest.TestCase): response_deserializer=_RESPONSE_DESERIALIZER, ) + def tearDown(self): + self._server.stop(None) + self._channel.close() + def testSuccessfulUnaryUnary(self): self._servicer.set_details(_DETAILS) diff --git a/src/python/grpcio_tests/tests/unit/_metadata_flags_test.py b/src/python/grpcio_tests/tests/unit/_metadata_flags_test.py index 2d352e99d4a..7b32b5b5f3e 100644 --- a/src/python/grpcio_tests/tests/unit/_metadata_flags_test.py +++ b/src/python/grpcio_tests/tests/unit/_metadata_flags_test.py @@ -187,13 +187,14 @@ class MetadataFlagsTest(unittest.TestCase): def test_call_wait_for_ready_default(self): for perform_call in _ALL_CALL_CASES: - self.check_connection_does_failfast(perform_call, - create_dummy_channel()) + with create_dummy_channel() as channel: + self.check_connection_does_failfast(perform_call, channel) def test_call_wait_for_ready_disabled(self): for perform_call in _ALL_CALL_CASES: - self.check_connection_does_failfast( - perform_call, create_dummy_channel(), wait_for_ready=False) + with create_dummy_channel() as channel: + self.check_connection_does_failfast( + perform_call, channel, wait_for_ready=False) def test_call_wait_for_ready_enabled(self): # To test the wait mechanism, Python thread is required to make @@ -210,16 +211,16 @@ class MetadataFlagsTest(unittest.TestCase): wg.done() def test_call(perform_call): - try: - channel = grpc.insecure_channel(addr) - channel.subscribe(wait_for_transient_failure) - perform_call(channel, wait_for_ready=True) - except BaseException as e: # pylint: disable=broad-except - # If the call failed, the thread would be destroyed. The channel - # object can be collected before calling the callback, which - # will result in a deadlock. - wg.done() - unhandled_exceptions.put(e, True) + with grpc.insecure_channel(addr) as channel: + try: + channel.subscribe(wait_for_transient_failure) + perform_call(channel, wait_for_ready=True) + except BaseException as e: # pylint: disable=broad-except + # If the call failed, the thread would be destroyed. The + # channel object can be collected before calling the + # callback, which will result in a deadlock. + wg.done() + unhandled_exceptions.put(e, True) test_threads = [] for perform_call in _ALL_CALL_CASES: diff --git a/src/python/grpcio_tests/tests/unit/_metadata_test.py b/src/python/grpcio_tests/tests/unit/_metadata_test.py index 777ab683e36..892df3df08f 100644 --- a/src/python/grpcio_tests/tests/unit/_metadata_test.py +++ b/src/python/grpcio_tests/tests/unit/_metadata_test.py @@ -186,6 +186,7 @@ class MetadataTest(unittest.TestCase): def tearDown(self): self._server.stop(0) + self._channel.close() def testUnaryUnary(self): multi_callable = self._channel.unary_unary(_UNARY_UNARY) diff --git a/src/python/grpcio_tests/tests/unit/_reconnect_test.py b/src/python/grpcio_tests/tests/unit/_reconnect_test.py index f6d4fcbd0a5..d4ea126e2b5 100644 --- a/src/python/grpcio_tests/tests/unit/_reconnect_test.py +++ b/src/python/grpcio_tests/tests/unit/_reconnect_test.py @@ -98,6 +98,8 @@ class ReconnectTest(unittest.TestCase): server.add_insecure_port('[::]:{}'.format(port)) server.start() self.assertEqual(_RESPONSE, multi_callable(_REQUEST)) + server.stop(None) + channel.close() if __name__ == '__main__': diff --git a/src/python/grpcio_tests/tests/unit/_resource_exhausted_test.py b/src/python/grpcio_tests/tests/unit/_resource_exhausted_test.py index 4fead8fcd54..517c2d2f97b 100644 --- a/src/python/grpcio_tests/tests/unit/_resource_exhausted_test.py +++ b/src/python/grpcio_tests/tests/unit/_resource_exhausted_test.py @@ -148,6 +148,7 @@ class ResourceExhaustedTest(unittest.TestCase): def tearDown(self): self._server.stop(0) + self._channel.close() def testUnaryUnary(self): multi_callable = self._channel.unary_unary(_UNARY_UNARY) diff --git a/src/python/grpcio_tests/tests/unit/_rpc_test.py b/src/python/grpcio_tests/tests/unit/_rpc_test.py index a768d6c7c1c..a99121cee57 100644 --- a/src/python/grpcio_tests/tests/unit/_rpc_test.py +++ b/src/python/grpcio_tests/tests/unit/_rpc_test.py @@ -193,6 +193,7 @@ class RPCTest(unittest.TestCase): def tearDown(self): self._server.stop(None) + self._channel.close() def testUnrecognizedMethod(self): request = b'abc' From b6b745f22dd66748fbcb2e7c0d10dc83be84d63a Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Fri, 21 Dec 2018 14:16:59 -0800 Subject: [PATCH 270/375] disable broken gevent test --- src/python/grpcio_tests/commands.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py index 496bcfbcbff..d5327711d33 100644 --- a/src/python/grpcio_tests/commands.py +++ b/src/python/grpcio_tests/commands.py @@ -133,6 +133,7 @@ class TestGevent(setuptools.Command): # This test will stuck while running higher version of gevent 'unit._auth_context_test.AuthContextTest.testSessionResumption', # TODO(https://github.com/grpc/grpc/issues/15411) enable these tests + 'unit._metadata_flags_test', 'unit._exit_test.ExitTest.test_in_flight_unary_unary_call', 'unit._exit_test.ExitTest.test_in_flight_unary_stream_call', 'unit._exit_test.ExitTest.test_in_flight_stream_unary_call', From 08dc0ade6790087702a9b7a01b6565e5d8b03832 Mon Sep 17 00:00:00 2001 From: Prashant Jaikumar Date: Fri, 21 Dec 2018 15:49:15 -0800 Subject: [PATCH 271/375] Fix bazel build for fling, memory_usage test --- test/core/fling/BUILD | 12 ++++++------ test/core/memory_usage/BUILD | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/test/core/fling/BUILD b/test/core/fling/BUILD index 5c6930cc85b..0c16b2a8799 100644 --- a/test/core/fling/BUILD +++ b/test/core/fling/BUILD @@ -21,7 +21,7 @@ licenses(["notice"]) # Apache v2 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer") grpc_cc_binary( - name = "client", + name = "fling_client", testonly = 1, srcs = ["client.cc"], language = "C++", @@ -34,7 +34,7 @@ grpc_cc_binary( ) grpc_cc_binary( - name = "server", + name = "fling_server", testonly = 1, srcs = ["server.cc"], language = "C++", @@ -50,8 +50,8 @@ grpc_cc_test( name = "fling", srcs = ["fling_test.cc"], data = [ - ":client", - ":server", + ":fling_client", + ":fling_server", ], deps = [ "//:gpr", @@ -65,8 +65,8 @@ grpc_cc_test( name = "fling_stream", srcs = ["fling_stream_test.cc"], data = [ - ":client", - ":server", + ":fling_client", + ":fling_server", ], deps = [ "//:gpr", diff --git a/test/core/memory_usage/BUILD b/test/core/memory_usage/BUILD index 2fe94dfa120..dd185e6577b 100644 --- a/test/core/memory_usage/BUILD +++ b/test/core/memory_usage/BUILD @@ -12,14 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package") +load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_test", "grpc_package") grpc_package(name = "test/core/memory_usage") licenses(["notice"]) # Apache v2 -grpc_cc_library( - name = "client", +grpc_cc_binary( + name = "memory_usage_client", testonly = 1, srcs = ["client.cc"], deps = [ @@ -29,8 +29,8 @@ grpc_cc_library( ], ) -grpc_cc_library( - name = "server", +grpc_cc_binary( + name = "memory_usage_server", testonly = 1, srcs = ["server.cc"], deps = [ @@ -45,8 +45,8 @@ grpc_cc_test( name = "memory_usage_test", srcs = ["memory_usage_test.cc"], data = [ - ":client", - ":server", + ":memory_usage_client", + ":memory_usage_server", ], language = "C++", deps = [ From 2e017da58aeb335e79f7bbf0797aad45a59d293b Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Fri, 21 Dec 2018 18:14:08 -0500 Subject: [PATCH 272/375] Add microbenchmarks for grpc_timer This helps assessing upcoming changes. --- CMakeLists.txt | 48 +++++++ Makefile | 49 ++++++++ build.yaml | 21 ++++ test/cpp/microbenchmarks/BUILD | 7 ++ test/cpp/microbenchmarks/bm_timer.cc | 118 ++++++++++++++++++ .../generated/sources_and_headers.json | 21 ++++ tools/run_tests/generated/tests.json | 22 ++++ 7 files changed, 286 insertions(+) create mode 100644 test/cpp/microbenchmarks/bm_timer.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 76886307813..d3ebb5d1773 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -576,6 +576,9 @@ endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_pollset) endif() +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) +add_dependencies(buildtests_cxx bm_timer) +endif() add_dependencies(buildtests_cxx byte_stream_test) add_dependencies(buildtests_cxx channel_arguments_test) add_dependencies(buildtests_cxx channel_filter_test) @@ -11748,6 +11751,51 @@ target_link_libraries(bm_pollset ) +endif() +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + +add_executable(bm_timer + test/cpp/microbenchmarks/bm_timer.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(bm_timer + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(bm_timer + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_benchmark + ${_gRPC_BENCHMARK_LIBRARIES} + grpc++_test_util_unsecure + grpc_test_util_unsecure + grpc++_unsecure + grpc_unsecure + gpr + grpc++_test_config + ${_gRPC_GFLAGS_LIBRARIES} +) + + endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) diff --git a/Makefile b/Makefile index 147e9505a33..b8a1c921862 100644 --- a/Makefile +++ b/Makefile @@ -1150,6 +1150,7 @@ bm_fullstack_trickle: $(BINDIR)/$(CONFIG)/bm_fullstack_trickle bm_fullstack_unary_ping_pong: $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong bm_metadata: $(BINDIR)/$(CONFIG)/bm_metadata bm_pollset: $(BINDIR)/$(CONFIG)/bm_pollset +bm_timer: $(BINDIR)/$(CONFIG)/bm_timer byte_stream_test: $(BINDIR)/$(CONFIG)/byte_stream_test channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test channel_filter_test: $(BINDIR)/$(CONFIG)/channel_filter_test @@ -1661,6 +1662,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong \ $(BINDIR)/$(CONFIG)/bm_metadata \ $(BINDIR)/$(CONFIG)/bm_pollset \ + $(BINDIR)/$(CONFIG)/bm_timer \ $(BINDIR)/$(CONFIG)/byte_stream_test \ $(BINDIR)/$(CONFIG)/channel_arguments_test \ $(BINDIR)/$(CONFIG)/channel_filter_test \ @@ -1846,6 +1848,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong \ $(BINDIR)/$(CONFIG)/bm_metadata \ $(BINDIR)/$(CONFIG)/bm_pollset \ + $(BINDIR)/$(CONFIG)/bm_timer \ $(BINDIR)/$(CONFIG)/byte_stream_test \ $(BINDIR)/$(CONFIG)/channel_arguments_test \ $(BINDIR)/$(CONFIG)/channel_filter_test \ @@ -2296,6 +2299,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/bm_metadata || ( echo test bm_metadata failed ; exit 1 ) $(E) "[RUN] Testing bm_pollset" $(Q) $(BINDIR)/$(CONFIG)/bm_pollset || ( echo test bm_pollset failed ; exit 1 ) + $(E) "[RUN] Testing bm_timer" + $(Q) $(BINDIR)/$(CONFIG)/bm_timer || ( echo test bm_timer failed ; exit 1 ) $(E) "[RUN] Testing byte_stream_test" $(Q) $(BINDIR)/$(CONFIG)/byte_stream_test || ( echo test byte_stream_test failed ; exit 1 ) $(E) "[RUN] Testing channel_arguments_test" @@ -16747,6 +16752,50 @@ endif endif +BM_TIMER_SRC = \ + test/cpp/microbenchmarks/bm_timer.cc \ + +BM_TIMER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_TIMER_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/bm_timer: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/bm_timer: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/bm_timer: $(PROTOBUF_DEP) $(BM_TIMER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(BM_TIMER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_timer + +endif + +endif + +$(BM_TIMER_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX +$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_timer.o: $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a + +deps_bm_timer: $(BM_TIMER_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(BM_TIMER_OBJS:.o=.dep) +endif +endif + + BYTE_STREAM_TEST_SRC = \ test/core/transport/byte_stream_test.cc \ diff --git a/build.yaml b/build.yaml index 9d73e31b2e5..a41decd84f7 100644 --- a/build.yaml +++ b/build.yaml @@ -4230,6 +4230,27 @@ targets: - mac - linux - posix +- name: bm_timer + build: test + language: c++ + src: + - test/cpp/microbenchmarks/bm_timer.cc + deps: + - grpc_benchmark + - benchmark + - grpc++_test_util_unsecure + - grpc_test_util_unsecure + - grpc++_unsecure + - grpc_unsecure + - gpr + - grpc++_test_config + benchmark: true + defaults: benchmark + platforms: + - mac + - linux + - posix + uses_polling: false - name: byte_stream_test gtest: true build: test diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD index b5890bece73..a29462f78fc 100644 --- a/test/cpp/microbenchmarks/BUILD +++ b/test/cpp/microbenchmarks/BUILD @@ -189,3 +189,10 @@ grpc_cc_binary( "//src/proto/grpc/testing:echo_proto", ], ) + +grpc_cc_binary( + name = "bm_timer", + testonly = 1, + srcs = ["bm_timer.cc"], + deps = [":helpers"], +) diff --git a/test/cpp/microbenchmarks/bm_timer.cc b/test/cpp/microbenchmarks/bm_timer.cc new file mode 100644 index 00000000000..f5a411251b5 --- /dev/null +++ b/test/cpp/microbenchmarks/bm_timer.cc @@ -0,0 +1,118 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include "test/cpp/microbenchmarks/helpers.h" +#include "test/cpp/util/test_config.h" + +#include "src/core/lib/iomgr/timer.h" + +namespace grpc { +namespace testing { + +auto& force_library_initialization = Library::get(); + +struct TimerClosure { + grpc_timer timer; + grpc_closure closure; +}; + +static void BM_InitCancelTimer(benchmark::State& state) { + constexpr int kTimerCount = 1024; + TrackCounters track_counters; + grpc_core::ExecCtx exec_ctx; + std::vector timer_closures(kTimerCount); + int i = 0; + while (state.KeepRunning()) { + TimerClosure* timer_closure = &timer_closures[i++ % kTimerCount]; + GRPC_CLOSURE_INIT(&timer_closure->closure, + [](void* /*args*/, grpc_error* /*err*/) {}, nullptr, + grpc_schedule_on_exec_ctx); + grpc_timer_init(&timer_closure->timer, GRPC_MILLIS_INF_FUTURE, + &timer_closure->closure); + grpc_timer_cancel(&timer_closure->timer); + exec_ctx.Flush(); + } + track_counters.Finish(state); +} +BENCHMARK(BM_InitCancelTimer); + +static void BM_TimerBatch(benchmark::State& state) { + constexpr int kTimerCount = 1024; + const bool check = state.range(0); + const bool reverse = state.range(1); + + const grpc_millis start = + reverse ? GRPC_MILLIS_INF_FUTURE : GRPC_MILLIS_INF_FUTURE - kTimerCount; + const grpc_millis end = + reverse ? GRPC_MILLIS_INF_FUTURE - kTimerCount : GRPC_MILLIS_INF_FUTURE; + const grpc_millis increment = reverse ? -1 : 1; + + TrackCounters track_counters; + grpc_core::ExecCtx exec_ctx; + std::vector timer_closures(kTimerCount); + while (state.KeepRunning()) { + for (grpc_millis deadline = start; deadline != end; deadline += increment) { + TimerClosure* timer_closure = &timer_closures[deadline % kTimerCount]; + GRPC_CLOSURE_INIT(&timer_closure->closure, + [](void* /*args*/, grpc_error* /*err*/) {}, nullptr, + grpc_schedule_on_exec_ctx); + + grpc_timer_init(&timer_closure->timer, deadline, &timer_closure->closure); + } + if (check) { + grpc_millis next; + grpc_timer_check(&next); + } + for (grpc_millis deadline = start; deadline != end; deadline += increment) { + TimerClosure* timer_closure = &timer_closures[deadline % kTimerCount]; + grpc_timer_cancel(&timer_closure->timer); + } + exec_ctx.Flush(); + } + track_counters.Finish(state); +} +BENCHMARK(BM_TimerBatch) + ->Args({/*check=*/false, /*reverse=*/false}) + ->Args({/*check=*/false, /*reverse=*/true}) + ->Args({/*check=*/true, /*reverse=*/false}) + ->Args({/*check=*/true, /*reverse=*/true}) + ->ThreadRange(1, 128); + +} // namespace testing +} // namespace grpc + +// Some distros have RunSpecifiedBenchmarks under the benchmark namespace, +// and others do not. This allows us to support both modes. +namespace benchmark { +void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); } +} // namespace benchmark + +int main(int argc, char** argv) { + ::benchmark::Initialize(&argc, argv); + ::grpc::testing::InitTest(&argc, &argv, false); + benchmark::RunTheBenchmarksNamespaced(); + return 0; +} diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 336d499be9d..8d1bca22be9 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -3005,6 +3005,27 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "benchmark", + "gpr", + "grpc++_test_config", + "grpc++_test_util_unsecure", + "grpc++_unsecure", + "grpc_benchmark", + "grpc_test_util_unsecure", + "grpc_unsecure" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "bm_timer", + "src": [ + "test/cpp/microbenchmarks/bm_timer.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 3a348e4a92f..e35d4db2767 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -3715,6 +3715,28 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": true, + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": false, + "language": "c++", + "name": "bm_timer", + "platforms": [ + "linux", + "mac", + "posix" + ], + "uses_polling": false + }, { "args": [], "benchmark": false, From 5ac6ab67e4278b977dde50891f6aed6cb0e9e078 Mon Sep 17 00:00:00 2001 From: xtao Date: Sat, 22 Dec 2018 09:49:22 +0800 Subject: [PATCH 273/375] * Fixed issue(17563) "Freeing heap block containing an active critical section." reported by Application Verifier on Windows. --- src/core/lib/iomgr/resource_quota.cc | 1 + src/core/lib/transport/metadata.cc | 1 + 2 files changed, 2 insertions(+) diff --git a/src/core/lib/iomgr/resource_quota.cc b/src/core/lib/iomgr/resource_quota.cc index 7e4b3c9b2ff..61c366098e1 100644 --- a/src/core/lib/iomgr/resource_quota.cc +++ b/src/core/lib/iomgr/resource_quota.cc @@ -665,6 +665,7 @@ void grpc_resource_quota_unref_internal(grpc_resource_quota* resource_quota) { GPR_ASSERT(resource_quota->num_threads_allocated == 0); GRPC_COMBINER_UNREF(resource_quota->combiner, "resource_quota"); gpr_free(resource_quota->name); + gpr_mu_destroy(&resource_quota->thread_count_mu); gpr_free(resource_quota); } } diff --git a/src/core/lib/transport/metadata.cc b/src/core/lib/transport/metadata.cc index 60af22393ef..30482a1b3b1 100644 --- a/src/core/lib/transport/metadata.cc +++ b/src/core/lib/transport/metadata.cc @@ -187,6 +187,7 @@ static void gc_mdtab(mdtab_shard* shard) { ((destroy_user_data_func)gpr_atm_no_barrier_load( &md->destroy_user_data))(user_data); } + gpr_mu_destroy(&md->mu_user_data); gpr_free(md); *prev_next = next; num_freed++; From 7bb853ebdd0b6e057de447147ad60ebf42e0903d Mon Sep 17 00:00:00 2001 From: Moiz Haidry Date: Fri, 21 Dec 2018 22:40:38 -0800 Subject: [PATCH 274/375] Addressed PR comments. Made Client::Thread public and removed use of void ptr to refer it. Avoided overloading of NextIssue TIme by renaming it NextRPCIssueTime --- test/cpp/qps/client.h | 116 ++++++++++++++++---------------- test/cpp/qps/client_callback.cc | 18 ++--- 2 files changed, 67 insertions(+), 67 deletions(-) diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index 0b9837660be..4b8ac9bd94e 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -251,64 +251,6 @@ class Client { return static_cast(gpr_atm_acq_load(&thread_pool_done_)); } - protected: - bool closed_loop_; - gpr_atm thread_pool_done_; - double median_latency_collection_interval_seconds_; // In seconds - - void StartThreads(size_t num_threads) { - gpr_atm_rel_store(&thread_pool_done_, static_cast(false)); - threads_remaining_ = num_threads; - for (size_t i = 0; i < num_threads; i++) { - threads_.emplace_back(new Thread(this, i)); - } - } - - void EndThreads() { - MaybeStartRequests(); - threads_.clear(); - } - - virtual void DestroyMultithreading() = 0; - - void SetupLoadTest(const ClientConfig& config, size_t num_threads) { - // Set up the load distribution based on the number of threads - const auto& load = config.load_params(); - - std::unique_ptr random_dist; - switch (load.load_case()) { - case LoadParams::kClosedLoop: - // Closed-loop doesn't use random dist at all - break; - case LoadParams::kPoisson: - random_dist.reset( - new ExpDist(load.poisson().offered_load() / num_threads)); - break; - default: - GPR_ASSERT(false); - } - - // Set closed_loop_ based on whether or not random_dist is set - if (!random_dist) { - closed_loop_ = true; - } else { - closed_loop_ = false; - // set up interarrival timer according to random dist - interarrival_timer_.init(*random_dist, num_threads); - const auto now = gpr_now(GPR_CLOCK_MONOTONIC); - for (size_t i = 0; i < num_threads; i++) { - next_time_.push_back(gpr_time_add( - now, - gpr_time_from_nanos(interarrival_timer_.next(i), GPR_TIMESPAN))); - } - } - } - - std::function NextIssuer(int thread_idx) { - return closed_loop_ ? std::function() - : std::bind(&Client::NextIssueTime, this, thread_idx); - } - class Thread { public: Thread(Client* client, size_t idx) @@ -387,6 +329,64 @@ class Client { double interval_start_time_; }; + protected: + bool closed_loop_; + gpr_atm thread_pool_done_; + double median_latency_collection_interval_seconds_; // In seconds + + void StartThreads(size_t num_threads) { + gpr_atm_rel_store(&thread_pool_done_, static_cast(false)); + threads_remaining_ = num_threads; + for (size_t i = 0; i < num_threads; i++) { + threads_.emplace_back(new Thread(this, i)); + } + } + + void EndThreads() { + MaybeStartRequests(); + threads_.clear(); + } + + virtual void DestroyMultithreading() = 0; + + void SetupLoadTest(const ClientConfig& config, size_t num_threads) { + // Set up the load distribution based on the number of threads + const auto& load = config.load_params(); + + std::unique_ptr random_dist; + switch (load.load_case()) { + case LoadParams::kClosedLoop: + // Closed-loop doesn't use random dist at all + break; + case LoadParams::kPoisson: + random_dist.reset( + new ExpDist(load.poisson().offered_load() / num_threads)); + break; + default: + GPR_ASSERT(false); + } + + // Set closed_loop_ based on whether or not random_dist is set + if (!random_dist) { + closed_loop_ = true; + } else { + closed_loop_ = false; + // set up interarrival timer according to random dist + interarrival_timer_.init(*random_dist, num_threads); + const auto now = gpr_now(GPR_CLOCK_MONOTONIC); + for (size_t i = 0; i < num_threads; i++) { + next_time_.push_back(gpr_time_add( + now, + gpr_time_from_nanos(interarrival_timer_.next(i), GPR_TIMESPAN))); + } + } + } + + std::function NextIssuer(int thread_idx) { + return closed_loop_ ? std::function() + : std::bind(&Client::NextIssueTime, this, thread_idx); + } + virtual void ThreadFunc(size_t thread_idx, Client::Thread* t) = 0; std::vector> threads_; diff --git a/test/cpp/qps/client_callback.cc b/test/cpp/qps/client_callback.cc index 1880f46d43d..4a06325f2b7 100644 --- a/test/cpp/qps/client_callback.cc +++ b/test/cpp/qps/client_callback.cc @@ -90,7 +90,7 @@ class CallbackClient } } - gpr_timespec NextIssueTime() { + gpr_timespec NextRPCIssueTime() { std::lock_guard l(next_issue_time_mu_); return Client::NextIssueTime(0); } @@ -166,7 +166,7 @@ class CallbackUnaryClient final : public CallbackClient { private: void ScheduleRpc(Thread* t, size_t vector_idx) { if (!closed_loop_) { - gpr_timespec next_issue_time = NextIssueTime(); + gpr_timespec next_issue_time = NextRPCIssueTime(); // Start an alarm callback to run the internal callback after // next_issue_time ctx_[vector_idx]->alarm_.experimental().Set( @@ -221,13 +221,13 @@ class CallbackStreamingClient : public CallbackClient { } ~CallbackStreamingClient() {} - void AddHistogramEntry(double start_, bool ok, void* thread_ptr) { + void AddHistogramEntry(double start_, bool ok, Thread* thread_ptr) { // Update Histogram with data from the callback run HistogramEntry entry; if (ok) { entry.set_value((UsageTimer::Now() - start_) * 1e9); } - ((Client::Thread*)thread_ptr)->UpdateHistogram(&entry); + thread_ptr->UpdateHistogram(&entry); } int messages_per_stream() { return messages_per_stream_; } @@ -297,7 +297,7 @@ class CallbackStreamingPingPongReactor final if (client_->ThreadCompleted()) return; if (!client_->IsClosedLoop()) { - gpr_timespec next_issue_time = client_->NextIssueTime(); + gpr_timespec next_issue_time = client_->NextRPCIssueTime(); // Start an alarm callback to run the internal callback after // next_issue_time ctx_->alarm_.experimental().Set(next_issue_time, @@ -307,13 +307,13 @@ class CallbackStreamingPingPongReactor final } } - void set_thread_ptr(void* ptr) { thread_ptr_ = ptr; } + void set_thread_ptr(Client::Thread* ptr) { thread_ptr_ = ptr; } CallbackStreamingPingPongClient* client_; std::unique_ptr ctx_; - void* thread_ptr_; // Needed to update histogram entries - double start_; // Track message start time - int messages_issued_; // Messages issued by this stream + Client::Thread* thread_ptr_; // Needed to update histogram entries + double start_; // Track message start time + int messages_issued_; // Messages issued by this stream }; class CallbackStreamingPingPongClientImpl final From 25e13ac79b67383765c0b786c7647af97676539a Mon Sep 17 00:00:00 2001 From: Max Vorobev Date: Mon, 24 Dec 2018 16:10:27 +0300 Subject: [PATCH 275/375] Fix incompatible_bzl_disallow_load_after_statement, deprecated attribute usage --- bazel/cc_grpc_library.bzl | 2 +- bazel/generate_cc.bzl | 2 +- bazel/grpc_build_system.bzl | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/bazel/cc_grpc_library.bzl b/bazel/cc_grpc_library.bzl index 32885657141..6bfcd653f51 100644 --- a/bazel/cc_grpc_library.bzl +++ b/bazel/cc_grpc_library.bzl @@ -1,6 +1,6 @@ """Generates and compiles C++ grpc stubs from proto_library rules.""" -load("//:bazel/generate_cc.bzl", "generate_cc") +load("//bazel:generate_cc.bzl", "generate_cc") def cc_grpc_library(name, srcs, deps, proto_only, well_known_protos, generate_mocks = False, use_external = False, **kwargs): """Generates C++ grpc classes from a .proto file. diff --git a/bazel/generate_cc.bzl b/bazel/generate_cc.bzl index ae747aa42ca..2f14071f92d 100644 --- a/bazel/generate_cc.bzl +++ b/bazel/generate_cc.bzl @@ -83,7 +83,7 @@ _generate_cc = rule( attrs = { "srcs": attr.label_list( mandatory = True, - non_empty = True, + allow_empty = False, providers = ["proto"], ), "plugin": attr.label( diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl index 65fe5a10aa2..caeafc76b69 100644 --- a/bazel/grpc_build_system.bzl +++ b/bazel/grpc_build_system.bzl @@ -23,6 +23,8 @@ # each change must be ported from one to the other. # +load("//bazel:cc_grpc_library.bzl", "cc_grpc_library") + # The set of pollers to test against if a test exercises polling POLLERS = ["epollex", "epoll1", "poll", "poll-cv"] @@ -111,7 +113,6 @@ def grpc_proto_plugin(name, srcs = [], deps = []): deps = deps, ) -load("//:bazel/cc_grpc_library.bzl", "cc_grpc_library") def grpc_proto_library( name, From 00763bc3eaff1523a70e5e791924c16abd2fe526 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Mon, 30 Jul 2018 17:22:25 -0700 Subject: [PATCH 276/375] Support named scope id's with ipv6 resolver on posix --- BUILD | 3 + CMakeLists.txt | 102 +++++++++++++- Makefile | 106 +++++++++++++-- build.yaml | 38 +++++- config.m4 | 2 + config.w32 | 2 + gRPC-C++.podspec | 2 + gRPC-Core.podspec | 4 + grpc.gemspec | 3 + grpc.gyp | 8 ++ package.xml | 3 + .../filters/client_channel/parse_address.cc | 29 +++- src/core/lib/iomgr/grpc_if_nametoindex.h | 30 +++++ .../lib/iomgr/grpc_if_nametoindex_posix.cc | 41 ++++++ .../iomgr/grpc_if_nametoindex_unsupported.cc | 37 +++++ src/python/grpcio/grpc_core_dependencies.py | 2 + test/core/client_channel/BUILD | 11 ++ .../parse_address_with_named_scope_id_test.cc | 126 ++++++++++++++++++ test/core/iomgr/BUILD | 19 ++- test/core/iomgr/resolve_address_posix_test.cc | 81 ++++++++++- tools/doxygen/Doxyfile.c++.internal | 1 + tools/doxygen/Doxyfile.core.internal | 3 + .../generated/sources_and_headers.json | 38 +++++- tools/run_tests/generated/tests.json | 54 +++++++- 24 files changed, 717 insertions(+), 28 deletions(-) create mode 100644 src/core/lib/iomgr/grpc_if_nametoindex.h create mode 100644 src/core/lib/iomgr/grpc_if_nametoindex_posix.cc create mode 100644 src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc create mode 100644 test/core/client_channel/parse_address_with_named_scope_id_test.cc diff --git a/BUILD b/BUILD index e3c765198b2..5a9e46acf9e 100644 --- a/BUILD +++ b/BUILD @@ -732,6 +732,8 @@ grpc_cc_library( "src/core/lib/iomgr/iomgr_posix.cc", "src/core/lib/iomgr/iomgr_windows.cc", "src/core/lib/iomgr/is_epollexclusive_available.cc", + "src/core/lib/iomgr/grpc_if_nametoindex_posix.cc", + "src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc", "src/core/lib/iomgr/load_file.cc", "src/core/lib/iomgr/lockfree_event.cc", "src/core/lib/iomgr/network_status_tracker.cc", @@ -873,6 +875,7 @@ grpc_cc_library( "src/core/lib/iomgr/executor.h", "src/core/lib/iomgr/gethostname.h", "src/core/lib/iomgr/gevent_util.h", + "src/core/lib/iomgr/grpc_if_nametoindex.h", "src/core/lib/iomgr/internal_errqueue.h", "src/core/lib/iomgr/iocp_windows.h", "src/core/lib/iomgr/iomgr.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index d3ebb5d1773..9e07a204b71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -371,11 +371,17 @@ add_dependencies(buildtests_c murmur_hash_test) add_dependencies(buildtests_c no_server_test) add_dependencies(buildtests_c num_external_connectivity_watchers_test) add_dependencies(buildtests_c parse_address_test) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) +add_dependencies(buildtests_c parse_address_with_named_scope_id_test) +endif() add_dependencies(buildtests_c percent_encoding_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) -add_dependencies(buildtests_c resolve_address_posix_test) +add_dependencies(buildtests_c resolve_address_using_ares_resolver_posix_test) endif() add_dependencies(buildtests_c resolve_address_using_ares_resolver_test) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) +add_dependencies(buildtests_c resolve_address_using_native_resolver_posix_test) +endif() add_dependencies(buildtests_c resolve_address_using_native_resolver_test) add_dependencies(buildtests_c resource_quota_test) add_dependencies(buildtests_c secure_channel_create_test) @@ -989,6 +995,8 @@ add_library(grpc src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_sysconf.cc + src/core/lib/iomgr/grpc_if_nametoindex_posix.cc + src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc src/core/lib/iomgr/internal_errqueue.cc src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iomgr.cc @@ -1411,6 +1419,8 @@ add_library(grpc_cronet src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_sysconf.cc + src/core/lib/iomgr/grpc_if_nametoindex_posix.cc + src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc src/core/lib/iomgr/internal_errqueue.cc src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iomgr.cc @@ -1817,6 +1827,8 @@ add_library(grpc_test_util src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_sysconf.cc + src/core/lib/iomgr/grpc_if_nametoindex_posix.cc + src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc src/core/lib/iomgr/internal_errqueue.cc src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iomgr.cc @@ -2139,6 +2151,8 @@ add_library(grpc_test_util_unsecure src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_sysconf.cc + src/core/lib/iomgr/grpc_if_nametoindex_posix.cc + src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc src/core/lib/iomgr/internal_errqueue.cc src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iomgr.cc @@ -2438,6 +2452,8 @@ add_library(grpc_unsecure src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_sysconf.cc + src/core/lib/iomgr/grpc_if_nametoindex_posix.cc + src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc src/core/lib/iomgr/internal_errqueue.cc src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iomgr.cc @@ -3323,6 +3339,8 @@ add_library(grpc++_cronet src/core/lib/iomgr/gethostname_fallback.cc src/core/lib/iomgr/gethostname_host_name_max.cc src/core/lib/iomgr/gethostname_sysconf.cc + src/core/lib/iomgr/grpc_if_nametoindex_posix.cc + src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc src/core/lib/iomgr/internal_errqueue.cc src/core/lib/iomgr/iocp_windows.cc src/core/lib/iomgr/iomgr.cc @@ -9132,6 +9150,42 @@ target_link_libraries(parse_address_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + +add_executable(parse_address_with_named_scope_id_test + test/core/client_channel/parse_address_with_named_scope_id_test.cc +) + + +target_include_directories(parse_address_with_named_scope_id_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} +) + +target_link_libraries(parse_address_with_named_scope_id_test + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr +) + + # avoid dependency on libstdc++ + if (_gRPC_CORE_NOSTDCXX_FLAGS) + set_target_properties(parse_address_with_named_scope_id_test PROPERTIES LINKER_LANGUAGE C) + target_compile_options(parse_address_with_named_scope_id_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) + endif() + +endif() +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) add_executable(percent_encoding_test test/core/slice/percent_encoding_test.cc @@ -9168,12 +9222,12 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) -add_executable(resolve_address_posix_test +add_executable(resolve_address_using_ares_resolver_posix_test test/core/iomgr/resolve_address_posix_test.cc ) -target_include_directories(resolve_address_posix_test +target_include_directories(resolve_address_using_ares_resolver_posix_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${_gRPC_SSL_INCLUDE_DIR} @@ -9186,7 +9240,7 @@ target_include_directories(resolve_address_posix_test PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} ) -target_link_libraries(resolve_address_posix_test +target_link_libraries(resolve_address_using_ares_resolver_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc @@ -9195,8 +9249,8 @@ target_link_libraries(resolve_address_posix_test # avoid dependency on libstdc++ if (_gRPC_CORE_NOSTDCXX_FLAGS) - set_target_properties(resolve_address_posix_test PROPERTIES LINKER_LANGUAGE C) - target_compile_options(resolve_address_posix_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) + set_target_properties(resolve_address_using_ares_resolver_posix_test PROPERTIES LINKER_LANGUAGE C) + target_compile_options(resolve_address_using_ares_resolver_posix_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) endif() endif() @@ -9236,6 +9290,42 @@ target_link_libraries(resolve_address_using_ares_resolver_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + +add_executable(resolve_address_using_native_resolver_posix_test + test/core/iomgr/resolve_address_posix_test.cc +) + + +target_include_directories(resolve_address_using_native_resolver_posix_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} +) + +target_link_libraries(resolve_address_using_native_resolver_posix_test + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr +) + + # avoid dependency on libstdc++ + if (_gRPC_CORE_NOSTDCXX_FLAGS) + set_target_properties(resolve_address_using_native_resolver_posix_test PROPERTIES LINKER_LANGUAGE C) + target_compile_options(resolve_address_using_native_resolver_posix_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) + endif() + +endif() +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) add_executable(resolve_address_using_native_resolver_test test/core/iomgr/resolve_address_test.cc diff --git a/Makefile b/Makefile index b8a1c921862..9e8e06c5491 100644 --- a/Makefile +++ b/Makefile @@ -1076,11 +1076,13 @@ nanopb_fuzzer_serverlist_test: $(BINDIR)/$(CONFIG)/nanopb_fuzzer_serverlist_test no_server_test: $(BINDIR)/$(CONFIG)/no_server_test num_external_connectivity_watchers_test: $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test parse_address_test: $(BINDIR)/$(CONFIG)/parse_address_test +parse_address_with_named_scope_id_test: $(BINDIR)/$(CONFIG)/parse_address_with_named_scope_id_test percent_decode_fuzzer: $(BINDIR)/$(CONFIG)/percent_decode_fuzzer percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer percent_encoding_test: $(BINDIR)/$(CONFIG)/percent_encoding_test -resolve_address_posix_test: $(BINDIR)/$(CONFIG)/resolve_address_posix_test +resolve_address_using_ares_resolver_posix_test: $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_posix_test resolve_address_using_ares_resolver_test: $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test +resolve_address_using_native_resolver_posix_test: $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_posix_test resolve_address_using_native_resolver_test: $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test resource_quota_test: $(BINDIR)/$(CONFIG)/resource_quota_test secure_channel_create_test: $(BINDIR)/$(CONFIG)/secure_channel_create_test @@ -1527,9 +1529,11 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/no_server_test \ $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test \ $(BINDIR)/$(CONFIG)/parse_address_test \ + $(BINDIR)/$(CONFIG)/parse_address_with_named_scope_id_test \ $(BINDIR)/$(CONFIG)/percent_encoding_test \ - $(BINDIR)/$(CONFIG)/resolve_address_posix_test \ + $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_posix_test \ $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test \ + $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_posix_test \ $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test \ $(BINDIR)/$(CONFIG)/resource_quota_test \ $(BINDIR)/$(CONFIG)/secure_channel_create_test \ @@ -2129,12 +2133,16 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/num_external_connectivity_watchers_test || ( echo test num_external_connectivity_watchers_test failed ; exit 1 ) $(E) "[RUN] Testing parse_address_test" $(Q) $(BINDIR)/$(CONFIG)/parse_address_test || ( echo test parse_address_test failed ; exit 1 ) + $(E) "[RUN] Testing parse_address_with_named_scope_id_test" + $(Q) $(BINDIR)/$(CONFIG)/parse_address_with_named_scope_id_test || ( echo test parse_address_with_named_scope_id_test failed ; exit 1 ) $(E) "[RUN] Testing percent_encoding_test" $(Q) $(BINDIR)/$(CONFIG)/percent_encoding_test || ( echo test percent_encoding_test failed ; exit 1 ) - $(E) "[RUN] Testing resolve_address_posix_test" - $(Q) $(BINDIR)/$(CONFIG)/resolve_address_posix_test || ( echo test resolve_address_posix_test failed ; exit 1 ) + $(E) "[RUN] Testing resolve_address_using_ares_resolver_posix_test" + $(Q) $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_posix_test || ( echo test resolve_address_using_ares_resolver_posix_test failed ; exit 1 ) $(E) "[RUN] Testing resolve_address_using_ares_resolver_test" $(Q) $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test || ( echo test resolve_address_using_ares_resolver_test failed ; exit 1 ) + $(E) "[RUN] Testing resolve_address_using_native_resolver_posix_test" + $(Q) $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_posix_test || ( echo test resolve_address_using_native_resolver_posix_test failed ; exit 1 ) $(E) "[RUN] Testing resolve_address_using_native_resolver_test" $(Q) $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test || ( echo test resolve_address_using_native_resolver_test failed ; exit 1 ) $(E) "[RUN] Testing resource_quota_test" @@ -3504,6 +3512,8 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_posix.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc \ src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ @@ -3920,6 +3930,8 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_posix.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc \ src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ @@ -4319,6 +4331,8 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_posix.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc \ src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ @@ -4628,6 +4642,8 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_posix.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc \ src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ @@ -4901,6 +4917,8 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_posix.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc \ src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ @@ -5763,6 +5781,8 @@ LIBGRPC++_CRONET_SRC = \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_posix.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc \ src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ @@ -13988,6 +14008,38 @@ endif endif +PARSE_ADDRESS_WITH_NAMED_SCOPE_ID_TEST_SRC = \ + test/core/client_channel/parse_address_with_named_scope_id_test.cc \ + +PARSE_ADDRESS_WITH_NAMED_SCOPE_ID_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(PARSE_ADDRESS_WITH_NAMED_SCOPE_ID_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/parse_address_with_named_scope_id_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/parse_address_with_named_scope_id_test: $(PARSE_ADDRESS_WITH_NAMED_SCOPE_ID_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(PARSE_ADDRESS_WITH_NAMED_SCOPE_ID_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/parse_address_with_named_scope_id_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/client_channel/parse_address_with_named_scope_id_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_parse_address_with_named_scope_id_test: $(PARSE_ADDRESS_WITH_NAMED_SCOPE_ID_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(PARSE_ADDRESS_WITH_NAMED_SCOPE_ID_TEST_OBJS:.o=.dep) +endif +endif + + PERCENT_DECODE_FUZZER_SRC = \ test/core/slice/percent_decode_fuzzer.cc \ @@ -14084,34 +14136,34 @@ endif endif -RESOLVE_ADDRESS_POSIX_TEST_SRC = \ +RESOLVE_ADDRESS_USING_ARES_RESOLVER_POSIX_TEST_SRC = \ test/core/iomgr/resolve_address_posix_test.cc \ -RESOLVE_ADDRESS_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_POSIX_TEST_SRC)))) +RESOLVE_ADDRESS_USING_ARES_RESOLVER_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_POSIX_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. -$(BINDIR)/$(CONFIG)/resolve_address_posix_test: openssl_dep_error +$(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_posix_test: openssl_dep_error else -$(BINDIR)/$(CONFIG)/resolve_address_posix_test: $(RESOLVE_ADDRESS_POSIX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_posix_test: $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_POSIX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(RESOLVE_ADDRESS_POSIX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/resolve_address_posix_test + $(Q) $(LD) $(LDFLAGS) $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_POSIX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_posix_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/resolve_address_posix_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_resolve_address_posix_test: $(RESOLVE_ADDRESS_POSIX_TEST_OBJS:.o=.dep) +deps_resolve_address_using_ares_resolver_posix_test: $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_POSIX_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) --include $(RESOLVE_ADDRESS_POSIX_TEST_OBJS:.o=.dep) +-include $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_POSIX_TEST_OBJS:.o=.dep) endif endif @@ -14148,6 +14200,38 @@ endif endif +RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_POSIX_TEST_SRC = \ + test/core/iomgr/resolve_address_posix_test.cc \ + +RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_POSIX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_POSIX_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_posix_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_posix_test: $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_POSIX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_POSIX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_posix_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/iomgr/resolve_address_posix_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_resolve_address_using_native_resolver_posix_test: $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_POSIX_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_POSIX_TEST_OBJS:.o=.dep) +endif +endif + + RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_SRC = \ test/core/iomgr/resolve_address_test.cc \ diff --git a/build.yaml b/build.yaml index a41decd84f7..3985668532d 100644 --- a/build.yaml +++ b/build.yaml @@ -276,6 +276,8 @@ filegroups: - src/core/lib/iomgr/gethostname_fallback.cc - src/core/lib/iomgr/gethostname_host_name_max.cc - src/core/lib/iomgr/gethostname_sysconf.cc + - src/core/lib/iomgr/grpc_if_nametoindex_posix.cc + - src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc - src/core/lib/iomgr/internal_errqueue.cc - src/core/lib/iomgr/iocp_windows.cc - src/core/lib/iomgr/iomgr.cc @@ -452,6 +454,7 @@ filegroups: - src/core/lib/iomgr/exec_ctx.h - src/core/lib/iomgr/executor.h - src/core/lib/iomgr/gethostname.h + - src/core/lib/iomgr/grpc_if_nametoindex.h - src/core/lib/iomgr/internal_errqueue.h - src/core/lib/iomgr/iocp_windows.h - src/core/lib/iomgr/iomgr.h @@ -3241,6 +3244,20 @@ targets: - grpc - gpr uses_polling: false +- name: parse_address_with_named_scope_id_test + build: test + language: c + src: + - test/core/client_channel/parse_address_with_named_scope_id_test.cc + deps: + - grpc_test_util + - grpc + - gpr + platforms: + - mac + - linux + - posix + uses_polling: false - name: percent_decode_fuzzer build: fuzzer language: c @@ -3275,7 +3292,7 @@ targets: - grpc - gpr uses_polling: false -- name: resolve_address_posix_test +- name: resolve_address_using_ares_resolver_posix_test build: test language: c src: @@ -3284,6 +3301,8 @@ targets: - grpc_test_util - grpc - gpr + args: + - --resolver=ares exclude_iomgrs: - uv platforms: @@ -3301,6 +3320,23 @@ targets: - gpr args: - --resolver=ares +- name: resolve_address_using_native_resolver_posix_test + build: test + language: c + src: + - test/core/iomgr/resolve_address_posix_test.cc + deps: + - grpc_test_util + - grpc + - gpr + args: + - --resolver=native + exclude_iomgrs: + - uv + platforms: + - mac + - linux + - posix - name: resolve_address_using_native_resolver_test build: test language: c diff --git a/config.m4 b/config.m4 index 25ffe2148ab..3c3c0210d87 100644 --- a/config.m4 +++ b/config.m4 @@ -128,6 +128,8 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_posix.cc \ + src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc \ src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/iocp_windows.cc \ src/core/lib/iomgr/iomgr.cc \ diff --git a/config.w32 b/config.w32 index b6e71dd09a5..f87859ad09f 100644 --- a/config.w32 +++ b/config.w32 @@ -103,6 +103,8 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\iomgr\\gethostname_fallback.cc " + "src\\core\\lib\\iomgr\\gethostname_host_name_max.cc " + "src\\core\\lib\\iomgr\\gethostname_sysconf.cc " + + "src\\core\\lib\\iomgr\\grpc_if_nametoindex_posix.cc " + + "src\\core\\lib\\iomgr\\grpc_if_nametoindex_unsupported.cc " + "src\\core\\lib\\iomgr\\internal_errqueue.cc " + "src\\core\\lib\\iomgr\\iocp_windows.cc " + "src\\core\\lib\\iomgr\\iomgr.cc " + diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 29a79dd47ab..cdea73abc8b 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -423,6 +423,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/gethostname.h', + 'src/core/lib/iomgr/grpc_if_nametoindex.h', 'src/core/lib/iomgr/internal_errqueue.h', 'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iomgr.h', @@ -616,6 +617,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/gethostname.h', + 'src/core/lib/iomgr/grpc_if_nametoindex.h', 'src/core/lib/iomgr/internal_errqueue.h', 'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iomgr.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index f873bc693bc..6c97dc42dc8 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -417,6 +417,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/gethostname.h', + 'src/core/lib/iomgr/grpc_if_nametoindex.h', 'src/core/lib/iomgr/internal_errqueue.h', 'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iomgr.h', @@ -571,6 +572,8 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_posix.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc', 'src/core/lib/iomgr/internal_errqueue.cc', 'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iomgr.cc', @@ -1040,6 +1043,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/exec_ctx.h', 'src/core/lib/iomgr/executor.h', 'src/core/lib/iomgr/gethostname.h', + 'src/core/lib/iomgr/grpc_if_nametoindex.h', 'src/core/lib/iomgr/internal_errqueue.h', 'src/core/lib/iomgr/iocp_windows.h', 'src/core/lib/iomgr/iomgr.h', diff --git a/grpc.gemspec b/grpc.gemspec index 3c680b044f7..42b1db35b4d 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -353,6 +353,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/exec_ctx.h ) s.files += %w( src/core/lib/iomgr/executor.h ) s.files += %w( src/core/lib/iomgr/gethostname.h ) + s.files += %w( src/core/lib/iomgr/grpc_if_nametoindex.h ) s.files += %w( src/core/lib/iomgr/internal_errqueue.h ) s.files += %w( src/core/lib/iomgr/iocp_windows.h ) s.files += %w( src/core/lib/iomgr/iomgr.h ) @@ -507,6 +508,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/gethostname_fallback.cc ) s.files += %w( src/core/lib/iomgr/gethostname_host_name_max.cc ) s.files += %w( src/core/lib/iomgr/gethostname_sysconf.cc ) + s.files += %w( src/core/lib/iomgr/grpc_if_nametoindex_posix.cc ) + s.files += %w( src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc ) s.files += %w( src/core/lib/iomgr/internal_errqueue.cc ) s.files += %w( src/core/lib/iomgr/iocp_windows.cc ) s.files += %w( src/core/lib/iomgr/iomgr.cc ) diff --git a/grpc.gyp b/grpc.gyp index 80b6d0315a1..13b9c1bc78b 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -310,6 +310,8 @@ 'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_posix.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc', 'src/core/lib/iomgr/internal_errqueue.cc', 'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iomgr.cc', @@ -672,6 +674,8 @@ 'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_posix.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc', 'src/core/lib/iomgr/internal_errqueue.cc', 'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iomgr.cc', @@ -914,6 +918,8 @@ 'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_posix.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc', 'src/core/lib/iomgr/internal_errqueue.cc', 'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iomgr.cc', @@ -1133,6 +1139,8 @@ 'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_posix.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc', 'src/core/lib/iomgr/internal_errqueue.cc', 'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iomgr.cc', diff --git a/package.xml b/package.xml index 2632fcb276b..6c1d902abcd 100644 --- a/package.xml +++ b/package.xml @@ -358,6 +358,7 @@ + @@ -512,6 +513,8 @@ + + diff --git a/src/core/ext/filters/client_channel/parse_address.cc b/src/core/ext/filters/client_channel/parse_address.cc index 707beb88769..c5e1ed811bc 100644 --- a/src/core/ext/filters/client_channel/parse_address.cc +++ b/src/core/ext/filters/client_channel/parse_address.cc @@ -19,6 +19,7 @@ #include #include "src/core/ext/filters/client_channel/parse_address.h" +#include "src/core/lib/iomgr/grpc_if_nametoindex.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/socket_utils.h" @@ -35,6 +36,11 @@ #include "src/core/lib/gpr/host_port.h" #include "src/core/lib/gpr/string.h" +#ifdef GRPC_POSIX_SOCKET +#include +#include +#endif + #ifdef GRPC_HAVE_UNIX_SOCKET bool grpc_parse_unix(const grpc_uri* uri, @@ -69,7 +75,12 @@ bool grpc_parse_ipv4_hostport(const char* hostport, grpc_resolved_address* addr, // Split host and port. char* host; char* port; - if (!gpr_split_host_port(hostport, &host, &port)) return false; + if (!gpr_split_host_port(hostport, &host, &port)) { + if (log_errors) { + gpr_log(GPR_ERROR, "Failed gpr_split_host_port(%s, ...)", hostport); + } + return false; + } // Parse IP address. memset(addr, 0, sizeof(*addr)); addr->len = static_cast(sizeof(grpc_sockaddr_in)); @@ -115,7 +126,12 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr, // Split host and port. char* host; char* port; - if (!gpr_split_host_port(hostport, &host, &port)) return false; + if (!gpr_split_host_port(hostport, &host, &port)) { + if (log_errors) { + gpr_log(GPR_ERROR, "Failed gpr_split_host_port(%s, ...)", hostport); + } + return false; + } // Parse IP address. memset(addr, 0, sizeof(*addr)); addr->len = static_cast(sizeof(grpc_sockaddr_in6)); @@ -150,10 +166,13 @@ bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr, if (gpr_parse_bytes_to_uint32(host_end + 1, strlen(host) - host_without_scope_len - 1, &sin6_scope_id) == 0) { - if (log_errors) { - gpr_log(GPR_ERROR, "invalid ipv6 scope id: '%s'", host_end + 1); + if ((sin6_scope_id = grpc_if_nametoindex(host_end + 1)) == 0) { + gpr_log(GPR_ERROR, + "Invalid interface name: '%s'. " + "Non-numeric and failed if_nametoindex.", + host_end + 1); + goto done; } - goto done; } // Handle "sin6_scope_id" being type "u_long". See grpc issue #10027. in6->sin6_scope_id = sin6_scope_id; diff --git a/src/core/lib/iomgr/grpc_if_nametoindex.h b/src/core/lib/iomgr/grpc_if_nametoindex.h new file mode 100644 index 00000000000..ed9612dcb93 --- /dev/null +++ b/src/core/lib/iomgr/grpc_if_nametoindex.h @@ -0,0 +1,30 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_GRPC_IF_NAMETOINDEX_H +#define GRPC_CORE_LIB_IOMGR_GRPC_IF_NAMETOINDEX_H + +#include + +#include + +/* Returns the interface index corresponding to the interface "name" provided. + * Returns non-zero upon success, and zero upon failure. */ +uint32_t grpc_if_nametoindex(char* name); + +#endif /* GRPC_CORE_LIB_IOMGR_GRPC_IF_NAMETOINDEX_H */ diff --git a/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc b/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc new file mode 100644 index 00000000000..8f9137455d2 --- /dev/null +++ b/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc @@ -0,0 +1,41 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/iomgr/port.h" + +#ifdef GRPC_POSIX_SOCKET + +#include "src/core/lib/iomgr/grpc_if_nametoindex.h" + +#include +#include + +#include + +uint32_t grpc_if_nametoindex(char* name) { + uint32_t out = if_nametoindex(name); + if (out == 0) { + gpr_log(GPR_DEBUG, "if_nametoindex failed for name %s. errno %d", name, + errno); + } + return out; +} + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc b/src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc new file mode 100644 index 00000000000..1faaaa6e420 --- /dev/null +++ b/src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc @@ -0,0 +1,37 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "src/core/lib/iomgr/port.h" + +#ifndef GRPC_POSIX_SOCKET + +#include "src/core/lib/iomgr/grpc_if_nametoindex.h" + +#include + +uint32_t grpc_if_nametoindex(char* name) { + gpr_log(GPR_DEBUG, + "Not attempting to convert interface name %s to index for current " + "platform.", + name); + return 0; +} + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 6a1fd676ca6..06de23903cb 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -102,6 +102,8 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/gethostname_fallback.cc', 'src/core/lib/iomgr/gethostname_host_name_max.cc', 'src/core/lib/iomgr/gethostname_sysconf.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_posix.cc', + 'src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc', 'src/core/lib/iomgr/internal_errqueue.cc', 'src/core/lib/iomgr/iocp_windows.cc', 'src/core/lib/iomgr/iomgr.cc', diff --git a/test/core/client_channel/BUILD b/test/core/client_channel/BUILD index 04485f5240f..57e5191af4c 100644 --- a/test/core/client_channel/BUILD +++ b/test/core/client_channel/BUILD @@ -43,6 +43,17 @@ grpc_cc_test( ], ) +grpc_cc_test( + name = "parse_address_with_named_scope_id_test", + srcs = ["parse_address_with_named_scope_id_test.cc"], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:grpc_test_util", + ], +) + grpc_cc_test( name = "uri_parser_test", srcs = ["uri_parser_test.cc"], diff --git a/test/core/client_channel/parse_address_with_named_scope_id_test.cc b/test/core/client_channel/parse_address_with_named_scope_id_test.cc new file mode 100644 index 00000000000..bfafa745178 --- /dev/null +++ b/test/core/client_channel/parse_address_with_named_scope_id_test.cc @@ -0,0 +1,126 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/ext/filters/client_channel/parse_address.h" +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/iomgr/socket_utils.h" + +#include +#include +#ifdef GRPC_HAVE_UNIX_SOCKET +#include +#endif + +#include +#include +#include + +#include "src/core/lib/gpr/host_port.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/iomgr/socket_utils.h" +#include "test/core/util/test_config.h" + +static void test_grpc_parse_ipv6_parity_with_getaddrinfo( + const char* target, const struct sockaddr_in6 result_from_getaddrinfo) { + // Get the sockaddr that gRPC's ipv6 resolver resolves this too. + grpc_core::ExecCtx exec_ctx; + grpc_uri* uri = grpc_uri_parse(target, 0); + grpc_resolved_address addr; + GPR_ASSERT(1 == grpc_parse_ipv6(uri, &addr)); + grpc_sockaddr_in6* result_from_grpc_parser = + reinterpret_cast(addr.addr); + // Compare the sockaddr returned from gRPC's ipv6 resolver with that returned + // from getaddrinfo. + GPR_ASSERT(result_from_grpc_parser->sin6_family == AF_INET6); + GPR_ASSERT(result_from_getaddrinfo.sin6_family == AF_INET6); + GPR_ASSERT(memcmp(&result_from_grpc_parser->sin6_addr, + &result_from_getaddrinfo.sin6_addr, sizeof(in6_addr)) == 0); + GPR_ASSERT(result_from_grpc_parser->sin6_scope_id == + result_from_getaddrinfo.sin6_scope_id); + GPR_ASSERT(result_from_grpc_parser->sin6_scope_id != 0); + // TODO: compare sin6_flow_info fields? parse_ipv6 zero's this field as is. + // Cleanup + grpc_uri_destroy(uri); +} + +struct sockaddr_in6 resolve_with_gettaddrinfo(const char* uri_text) { + grpc_uri* uri = grpc_uri_parse(uri_text, 0); + char* host = nullptr; + char* port = nullptr; + gpr_split_host_port(uri->path, &host, &port); + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_NUMERICHOST; + struct addrinfo* result; + int res = getaddrinfo(host, port, &hints, &result); + if (res != 0) { + gpr_log(GPR_ERROR, + "getaddrinfo failed to resolve host:%s port:%s. Error: %d.", host, + port, res); + abort(); + } + size_t num_addrs_from_getaddrinfo = 0; + for (struct addrinfo* resp = result; resp != nullptr; resp = resp->ai_next) { + num_addrs_from_getaddrinfo++; + } + GPR_ASSERT(num_addrs_from_getaddrinfo == 1); + GPR_ASSERT(result->ai_family == AF_INET6); + struct sockaddr_in6 out = + *reinterpret_cast(result->ai_addr); + // Cleanup + freeaddrinfo(result); + gpr_free(host); + gpr_free(port); + grpc_uri_destroy(uri); + return out; +} + +int main(int argc, char** argv) { + grpc_test_init(argc, argv); + grpc_init(); + char* arbitrary_interface_name = static_cast(gpr_zalloc(IF_NAMESIZE)); + // Per RFC 3493, an interface index is a "small positive integer starts at 1". + // Probe candidate interface index numbers until we find one that the + // system recognizes, and then use that for the test. + for (size_t i = 1; i < 65536; i++) { + if (if_indextoname(i, arbitrary_interface_name) != nullptr) { + gpr_log( + GPR_DEBUG, + "Found interface at index %d named %s. Will use this for the test", + (int)i, arbitrary_interface_name); + break; + } + } + GPR_ASSERT(strlen(arbitrary_interface_name) > 0); + char* target = nullptr; + gpr_asprintf(&target, "ipv6:[fe80::1234%%%s]:12345", + arbitrary_interface_name); + struct sockaddr_in6 result_from_getaddrinfo = + resolve_with_gettaddrinfo(target); + // Run the test + gpr_log(GPR_DEBUG, + "Run test_grpc_parse_ipv6_parity_with_getaddrinfo with target: %s", + target); + test_grpc_parse_ipv6_parity_with_getaddrinfo(target, result_from_getaddrinfo); + // Cleanup + gpr_free(target); + gpr_free(arbitrary_interface_name); + grpc_shutdown(); +} diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index e920ceacf00..5acf269988b 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -128,8 +128,25 @@ grpc_cc_test( ) grpc_cc_test( - name = "resolve_address_posix_test", + name = "resolve_address_using_ares_resolver_posix_test", srcs = ["resolve_address_posix_test.cc"], + args = [ + "--resolver=ares", + ], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:grpc_test_util", + ], +) + +grpc_cc_test( + name = "resolve_address_using_native_resolver_posix_test", + srcs = ["resolve_address_posix_test.cc"], + args = [ + "--resolver=native", + ], language = "C++", deps = [ "//:gpr", diff --git a/test/core/iomgr/resolve_address_posix_test.cc b/test/core/iomgr/resolve_address_posix_test.cc index 5785c73e225..826c7e1fafa 100644 --- a/test/core/iomgr/resolve_address_posix_test.cc +++ b/test/core/iomgr/resolve_address_posix_test.cc @@ -18,12 +18,14 @@ #include "src/core/lib/iomgr/resolve_address.h" +#include #include #include #include #include #include +#include #include #include @@ -33,6 +35,7 @@ #include "src/core/lib/gprpp/thd.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr.h" +#include "test/core/util/cmdline.h" #include "test/core/util/test_config.h" static gpr_timespec test_deadline(void) { @@ -117,12 +120,18 @@ static void must_succeed(void* argsp, grpc_error* err) { GPR_ASSERT(args->addrs != nullptr); GPR_ASSERT(args->addrs->naddrs > 0); gpr_atm_rel_store(&args->done_atm, 1); + gpr_mu_lock(args->mu); + GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, nullptr)); + gpr_mu_unlock(args->mu); } static void must_fail(void* argsp, grpc_error* err) { args_struct* args = static_cast(argsp); GPR_ASSERT(err != GRPC_ERROR_NONE); gpr_atm_rel_store(&args->done_atm, 1); + gpr_mu_lock(args->mu); + GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, nullptr)); + gpr_mu_unlock(args->mu); } static void test_unix_socket(void) { @@ -159,22 +168,92 @@ static void test_unix_socket_path_name_too_long(void) { args_finish(&args); } +static void resolve_address_must_succeed(const char* target) { + grpc_core::ExecCtx exec_ctx; + args_struct args; + args_init(&args); + poll_pollset_until_request_done(&args); + grpc_resolve_address( + target, "1" /* port number */, args.pollset_set, + GRPC_CLOSURE_CREATE(must_succeed, &args, grpc_schedule_on_exec_ctx), + &args.addrs); + grpc_core::ExecCtx::Get()->Flush(); + args_finish(&args); +} + +static void test_named_and_numeric_scope_ids(void) { + char* arbitrary_interface_name = static_cast(gpr_zalloc(IF_NAMESIZE)); + int interface_index = 0; + // Probe candidate interface index numbers until we find one that the + // system recognizes, and then use that for the test. + for (size_t i = 1; i < 65536; i++) { + if (if_indextoname(i, arbitrary_interface_name) != nullptr) { + gpr_log( + GPR_DEBUG, + "Found interface at index %d named %s. Will use this for the test", + (int)i, arbitrary_interface_name); + interface_index = (int)i; + break; + } + } + GPR_ASSERT(strlen(arbitrary_interface_name) > 0); + // Test resolution of an ipv6 address with a named scope ID + gpr_log(GPR_DEBUG, "test resolution with a named scope ID"); + char* target_with_named_scope_id = nullptr; + gpr_asprintf(&target_with_named_scope_id, "fe80::1234%%%s", + arbitrary_interface_name); + resolve_address_must_succeed(target_with_named_scope_id); + gpr_free(target_with_named_scope_id); + gpr_free(arbitrary_interface_name); + // Test resolution of an ipv6 address with a numeric scope ID + gpr_log(GPR_DEBUG, "test resolution with a numeric scope ID"); + char* target_with_numeric_scope_id = nullptr; + gpr_asprintf(&target_with_numeric_scope_id, "fe80::1234%%%d", + interface_index); + resolve_address_must_succeed(target_with_numeric_scope_id); + gpr_free(target_with_numeric_scope_id); +} + int main(int argc, char** argv) { + // First set the resolver type based off of --resolver + const char* resolver_type = nullptr; + gpr_cmdline* cl = gpr_cmdline_create("resolve address test"); + gpr_cmdline_add_string(cl, "resolver", "Resolver type (ares or native)", + &resolver_type); + // In case that there are more than one argument on the command line, + // --resolver will always be the first one, so only parse the first argument + // (other arguments may be unknown to cl) + gpr_cmdline_parse(cl, argc > 2 ? 2 : argc, argv); + const char* cur_resolver = gpr_getenv("GRPC_DNS_RESOLVER"); + if (cur_resolver != nullptr && strlen(cur_resolver) != 0) { + gpr_log(GPR_INFO, "Warning: overriding resolver setting of %s", + cur_resolver); + } + if (gpr_stricmp(resolver_type, "native") == 0) { + gpr_setenv("GRPC_DNS_RESOLVER", "native"); + } else if (gpr_stricmp(resolver_type, "ares") == 0) { + gpr_setenv("GRPC_DNS_RESOLVER", "ares"); + } else { + gpr_log(GPR_ERROR, "--resolver_type was not set to ares or native"); + abort(); + } grpc::testing::TestEnvironment env(argc, argv); grpc_init(); { grpc_core::ExecCtx exec_ctx; - char* resolver_env = gpr_getenv("GRPC_DNS_RESOLVER"); + test_named_and_numeric_scope_ids(); // c-ares resolver doesn't support UDS (ability for native DNS resolver // to handle this is only expected to be used by servers, which // unconditionally use the native DNS resolver). + char* resolver_env = gpr_getenv("GRPC_DNS_RESOLVER"); if (resolver_env == nullptr || gpr_stricmp(resolver_env, "native") == 0) { test_unix_socket(); test_unix_socket_path_name_too_long(); } gpr_free(resolver_env); } + gpr_cmdline_destroy(cl); grpc_shutdown(); return 0; diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 5f488d51940..08741168275 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1100,6 +1100,7 @@ src/core/lib/iomgr/ev_posix.h \ src/core/lib/iomgr/exec_ctx.h \ src/core/lib/iomgr/executor.h \ src/core/lib/iomgr/gethostname.h \ +src/core/lib/iomgr/grpc_if_nametoindex.h \ src/core/lib/iomgr/internal_errqueue.h \ src/core/lib/iomgr/iocp_windows.h \ src/core/lib/iomgr/iomgr.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index ba2eaecafda..38d17b6f21f 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1214,6 +1214,9 @@ src/core/lib/iomgr/gethostname.h \ src/core/lib/iomgr/gethostname_fallback.cc \ src/core/lib/iomgr/gethostname_host_name_max.cc \ src/core/lib/iomgr/gethostname_sysconf.cc \ +src/core/lib/iomgr/grpc_if_nametoindex.h \ +src/core/lib/iomgr/grpc_if_nametoindex_posix.cc \ +src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc \ src/core/lib/iomgr/internal_errqueue.cc \ src/core/lib/iomgr/internal_errqueue.h \ src/core/lib/iomgr/iocp_windows.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8d1bca22be9..1478ac2cd5e 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -1722,6 +1722,22 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "parse_address_with_named_scope_id_test", + "src": [ + "test/core/client_channel/parse_address_with_named_scope_id_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -1779,7 +1795,7 @@ "headers": [], "is_filegroup": false, "language": "c", - "name": "resolve_address_posix_test", + "name": "resolve_address_using_ares_resolver_posix_test", "src": [ "test/core/iomgr/resolve_address_posix_test.cc" ], @@ -1802,6 +1818,22 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "resolve_address_using_native_resolver_posix_test", + "src": [ + "test/core/iomgr/resolve_address_posix_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -9371,6 +9403,8 @@ "src/core/lib/iomgr/gethostname_fallback.cc", "src/core/lib/iomgr/gethostname_host_name_max.cc", "src/core/lib/iomgr/gethostname_sysconf.cc", + "src/core/lib/iomgr/grpc_if_nametoindex_posix.cc", + "src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc", "src/core/lib/iomgr/internal_errqueue.cc", "src/core/lib/iomgr/iocp_windows.cc", "src/core/lib/iomgr/iomgr.cc", @@ -9548,6 +9582,7 @@ "src/core/lib/iomgr/exec_ctx.h", "src/core/lib/iomgr/executor.h", "src/core/lib/iomgr/gethostname.h", + "src/core/lib/iomgr/grpc_if_nametoindex.h", "src/core/lib/iomgr/internal_errqueue.h", "src/core/lib/iomgr/iocp_windows.h", "src/core/lib/iomgr/iomgr.h", @@ -9701,6 +9736,7 @@ "src/core/lib/iomgr/exec_ctx.h", "src/core/lib/iomgr/executor.h", "src/core/lib/iomgr/gethostname.h", + "src/core/lib/iomgr/grpc_if_nametoindex.h", "src/core/lib/iomgr/internal_errqueue.h", "src/core/lib/iomgr/iocp_windows.h", "src/core/lib/iomgr/iomgr.h", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index e35d4db2767..f2d0cab5ede 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -2057,6 +2057,28 @@ ], "uses_polling": false }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "parse_address_with_named_scope_id_test", + "platforms": [ + "linux", + "mac", + "posix" + ], + "uses_polling": false + }, { "args": [], "benchmark": false, @@ -2082,7 +2104,9 @@ "uses_polling": false }, { - "args": [], + "args": [ + "--resolver=ares" + ], "benchmark": false, "ci_platforms": [ "linux", @@ -2097,7 +2121,7 @@ "flaky": false, "gtest": false, "language": "c", - "name": "resolve_address_posix_test", + "name": "resolve_address_using_ares_resolver_posix_test", "platforms": [ "linux", "mac", @@ -2131,6 +2155,32 @@ ], "uses_polling": true }, + { + "args": [ + "--resolver=native" + ], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "gtest": false, + "language": "c", + "name": "resolve_address_using_native_resolver_posix_test", + "platforms": [ + "linux", + "mac", + "posix" + ], + "uses_polling": true + }, { "args": [ "--resolver=native" From 39ac83a49ea73f619edbfd7ebde47f12d67a18f3 Mon Sep 17 00:00:00 2001 From: Tommy Chen Date: Wed, 26 Dec 2018 11:17:48 -0800 Subject: [PATCH 277/375] ruby-sigint ready to be merged! --- examples/ruby/greeter_server.rb | 5 +- .../ruby/route_guide/route_guide_server.rb | 5 +- .../end2end/graceful_sig_handling_client.rb | 61 ++++++++++++++ .../end2end/graceful_sig_handling_driver.rb | 83 +++++++++++++++++++ src/ruby/end2end/graceful_sig_stop_client.rb | 78 +++++++++++++++++ src/ruby/end2end/graceful_sig_stop_driver.rb | 62 ++++++++++++++ src/ruby/lib/grpc/generic/rpc_server.rb | 61 ++++++++++++++ .../helper_scripts/run_ruby_end2end_tests.sh | 2 + 8 files changed, 355 insertions(+), 2 deletions(-) create mode 100755 src/ruby/end2end/graceful_sig_handling_client.rb create mode 100755 src/ruby/end2end/graceful_sig_handling_driver.rb create mode 100755 src/ruby/end2end/graceful_sig_stop_client.rb create mode 100755 src/ruby/end2end/graceful_sig_stop_driver.rb diff --git a/examples/ruby/greeter_server.rb b/examples/ruby/greeter_server.rb index dca61714b88..52904297426 100755 --- a/examples/ruby/greeter_server.rb +++ b/examples/ruby/greeter_server.rb @@ -39,7 +39,10 @@ def main s = GRPC::RpcServer.new s.add_http2_port('0.0.0.0:50051', :this_port_is_insecure) s.handle(GreeterServer) - s.run_till_terminated + # Runs the server with SIGHUP, SIGINT and SIGQUIT signal handlers to + # gracefully shutdown. + # User could also choose to run server via call to run_till_terminated + s.run_till_terminated_or_interrupted([1, 'int', 'SIGQUIT']) end main diff --git a/examples/ruby/route_guide/route_guide_server.rb b/examples/ruby/route_guide/route_guide_server.rb index 5eb268b5336..ffcebd8418d 100755 --- a/examples/ruby/route_guide/route_guide_server.rb +++ b/examples/ruby/route_guide/route_guide_server.rb @@ -172,7 +172,10 @@ def main s.add_http2_port(port, :this_port_is_insecure) GRPC.logger.info("... running insecurely on #{port}") s.handle(ServerImpl.new(feature_db)) - s.run_till_terminated + # Runs the server with SIGHUP, SIGINT and SIGQUIT signal handlers to + # gracefully shutdown. + # User could also choose to run server via call to run_till_terminated + s.run_till_terminated_or_interrupted([1, 'int', 'SIGQUIT']) end main diff --git a/src/ruby/end2end/graceful_sig_handling_client.rb b/src/ruby/end2end/graceful_sig_handling_client.rb new file mode 100755 index 00000000000..14a67a62ccc --- /dev/null +++ b/src/ruby/end2end/graceful_sig_handling_client.rb @@ -0,0 +1,61 @@ +#!/usr/bin/env ruby + +# Copyright 2015 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require_relative './end2end_common' + +# Test client. Sends RPC's as normal but process also has signal handlers +class SigHandlingClientController < ClientControl::ClientController::Service + def initialize(stub) + @stub = stub + end + + def do_echo_rpc(req, _) + response = @stub.echo(Echo::EchoRequest.new(request: req.request)) + fail 'bad response' unless response.response == req.request + ClientControl::Void.new + end +end + +def main + client_control_port = '' + server_port = '' + OptionParser.new do |opts| + opts.on('--client_control_port=P', String) do |p| + client_control_port = p + end + opts.on('--server_port=P', String) do |p| + server_port = p + end + end.parse! + + # Allow a few seconds to be safe. + srv = new_rpc_server_for_testing + srv.add_http2_port("0.0.0.0:#{client_control_port}", + :this_port_is_insecure) + stub = Echo::EchoServer::Stub.new("localhost:#{server_port}", + :this_channel_is_insecure) + control_service = SigHandlingClientController.new(stub) + srv.handle(control_service) + server_thread = Thread.new do + srv.run_till_terminated_or_interrupted(['int']) + end + srv.wait_till_running + # send a first RPC to notify the parent process that we've started + stub.echo(Echo::EchoRequest.new(request: 'client/child started')) + server_thread.join +end + +main diff --git a/src/ruby/end2end/graceful_sig_handling_driver.rb b/src/ruby/end2end/graceful_sig_handling_driver.rb new file mode 100755 index 00000000000..e12ae284858 --- /dev/null +++ b/src/ruby/end2end/graceful_sig_handling_driver.rb @@ -0,0 +1,83 @@ +#!/usr/bin/env ruby + +# Copyright 2016 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# smoke test for a grpc-using app that receives and +# handles process-ending signals + +require_relative './end2end_common' + +# A service that calls back it's received_rpc_callback +# upon receiving an RPC. Used for synchronization/waiting +# for child process to start. +class ClientStartedService < Echo::EchoServer::Service + def initialize(received_rpc_callback) + @received_rpc_callback = received_rpc_callback + end + + def echo(echo_req, _) + @received_rpc_callback.call unless @received_rpc_callback.nil? + @received_rpc_callback = nil + Echo::EchoReply.new(response: echo_req.request) + end +end + +def main + STDERR.puts 'start server' + client_started = false + client_started_mu = Mutex.new + client_started_cv = ConditionVariable.new + received_rpc_callback = proc do + client_started_mu.synchronize do + client_started = true + client_started_cv.signal + end + end + + client_started_service = ClientStartedService.new(received_rpc_callback) + server_runner = ServerRunner.new(client_started_service) + server_port = server_runner.run + STDERR.puts 'start client' + control_stub, client_pid = start_client('graceful_sig_handling_client.rb', server_port) + + client_started_mu.synchronize do + client_started_cv.wait(client_started_mu) until client_started + end + + control_stub.do_echo_rpc( + ClientControl::DoEchoRpcRequest.new(request: 'hello')) + + STDERR.puts 'killing client' + Process.kill('SIGINT', client_pid) + Process.wait(client_pid) + client_exit_status = $CHILD_STATUS + + if client_exit_status.exited? + if client_exit_status.exitstatus != 0 + STDERR.puts 'Client did not close gracefully' + exit(1) + end + else + STDERR.puts 'Client did not close gracefully' + exit(1) + end + + STDERR.puts 'Client ended gracefully' + + # no need to call cleanup, client should already be dead + server_runner.stop +end + +main diff --git a/src/ruby/end2end/graceful_sig_stop_client.rb b/src/ruby/end2end/graceful_sig_stop_client.rb new file mode 100755 index 00000000000..b672dc3f2ac --- /dev/null +++ b/src/ruby/end2end/graceful_sig_stop_client.rb @@ -0,0 +1,78 @@ +#!/usr/bin/env ruby + +# Copyright 2015 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require_relative './end2end_common' + +# Test client. Sends RPC's as normal but process also has signal handlers +class SigHandlingClientController < ClientControl::ClientController::Service + def initialize(srv, stub) + @srv = srv + @stub = stub + end + + def do_echo_rpc(req, _) + response = @stub.echo(Echo::EchoRequest.new(request: req.request)) + fail 'bad response' unless response.response == req.request + ClientControl::Void.new + end + + def shutdown(_, _) + # Spawn a new thread because RpcServer#stop is + # synchronous and blocks until either this RPC has finished, + # or the server's "poll_period" seconds have passed. + @shutdown_thread = Thread.new do + @srv.stop + end + ClientControl::Void.new + end + + def join_shutdown_thread + @shutdown_thread.join + end +end + +def main + client_control_port = '' + server_port = '' + OptionParser.new do |opts| + opts.on('--client_control_port=P', String) do |p| + client_control_port = p + end + opts.on('--server_port=P', String) do |p| + server_port = p + end + end.parse! + + # The "shutdown" RPC should end very quickly. + # Allow a few seconds to be safe. + srv = new_rpc_server_for_testing(poll_period: 3) + srv.add_http2_port("0.0.0.0:#{client_control_port}", + :this_port_is_insecure) + stub = Echo::EchoServer::Stub.new("localhost:#{server_port}", + :this_channel_is_insecure) + control_service = SigHandlingClientController.new(srv, stub) + srv.handle(control_service) + server_thread = Thread.new do + srv.run_till_terminated_or_interrupted(['int']) + end + srv.wait_till_running + # send a first RPC to notify the parent process that we've started + stub.echo(Echo::EchoRequest.new(request: 'client/child started')) + server_thread.join + control_service.join_shutdown_thread +end + +main diff --git a/src/ruby/end2end/graceful_sig_stop_driver.rb b/src/ruby/end2end/graceful_sig_stop_driver.rb new file mode 100755 index 00000000000..7a132403ebf --- /dev/null +++ b/src/ruby/end2end/graceful_sig_stop_driver.rb @@ -0,0 +1,62 @@ +#!/usr/bin/env ruby + +# Copyright 2016 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# smoke test for a grpc-using app that receives and +# handles process-ending signals + +require_relative './end2end_common' + +# A service that calls back it's received_rpc_callback +# upon receiving an RPC. Used for synchronization/waiting +# for child process to start. +class ClientStartedService < Echo::EchoServer::Service + def initialize(received_rpc_callback) + @received_rpc_callback = received_rpc_callback + end + + def echo(echo_req, _) + @received_rpc_callback.call unless @received_rpc_callback.nil? + @received_rpc_callback = nil + Echo::EchoReply.new(response: echo_req.request) + end +end + +def main + STDERR.puts 'start server' + client_started = false + client_started_mu = Mutex.new + client_started_cv = ConditionVariable.new + received_rpc_callback = proc do + client_started_mu.synchronize do + client_started = true + client_started_cv.signal + end + end + + client_started_service = ClientStartedService.new(received_rpc_callback) + server_runner = ServerRunner.new(client_started_service) + server_port = server_runner.run + STDERR.puts 'start client' + control_stub, client_pid = start_client('./graceful_sig_stop_client.rb', server_port) + + client_started_mu.synchronize do + client_started_cv.wait(client_started_mu) until client_started + end + + cleanup(control_stub, client_pid, server_runner) +end + +main diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index 3b5a0ce27f3..f0f73dc56ea 100644 --- a/src/ruby/lib/grpc/generic/rpc_server.rb +++ b/src/ruby/lib/grpc/generic/rpc_server.rb @@ -240,6 +240,13 @@ module GRPC # the call has no impact if the server is already stopped, otherwise # server's current call loop is it's last. def stop + # if called via run_till_terminated_or_interrupted, + # signal stop_server_thread and dont do anything + if @stop_server.nil? == false && @stop_server == false + @stop_server = true + @stop_server_cv.broadcast + return + end @run_mutex.synchronize do fail 'Cannot stop before starting' if @running_state == :not_started return if @running_state != :running @@ -354,6 +361,60 @@ module GRPC alias_method :run_till_terminated, :run + # runs the server with signal handlers + # @param signals + # List of String, Integer or both representing signals that the user + # would like to send to the server for graceful shutdown + # @param wait_interval (optional) + # Integer seconds that user would like stop_server_thread to poll + # stop_server + def run_till_terminated_or_interrupted(signals, wait_interval = 60) + @stop_server = false + @stop_server_mu = Mutex.new + @stop_server_cv = ConditionVariable.new + + @stop_server_thread = Thread.new do + loop do + break if @stop_server + @stop_server_mu.synchronize do + @stop_server_cv.wait(@stop_server_mu, wait_interval) + end + end + + # stop is surrounded by mutex, should handle multiple calls to stop + # correctly + stop + end + + valid_signals = Signal.list + + # register signal handlers + signals.each do |sig| + # input validation + if sig.class == String + sig.upcase! + if sig.start_with?('SIG') + # cut out the SIG prefix to see if valid signal + sig = sig[3..-1] + end + end + + # register signal traps for all valid signals + if valid_signals.value?(sig) || valid_signals.key?(sig) + Signal.trap(sig) do + @stop_server = true + @stop_server_cv.broadcast + end + else + fail "#{sig} not a valid signal" + end + end + + run + + @stop_server_thread.join + end + # Sends RESOURCE_EXHAUSTED if there are too many unprocessed jobs def available?(an_rpc) return an_rpc if @pool.ready_for_work? diff --git a/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh b/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh index 7ff877e8306..1c48ed20ba6 100755 --- a/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh +++ b/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh @@ -30,4 +30,6 @@ time ruby src/ruby/end2end/multiple_killed_watching_threads_driver.rb || EXIT_CO time ruby src/ruby/end2end/load_grpc_with_gc_stress_driver.rb || EXIT_CODE=1 time ruby src/ruby/end2end/client_memory_usage_driver.rb || EXIT_CODE=1 time ruby src/ruby/end2end/package_with_underscore_checker.rb || EXIT_CODE=1 +time ruby src/ruby/end2end/graceful_sig_handling_driver.rb || EXIT_CODE=1 +time ruby src/ruby/end2end/graceful_sig_stop_driver.rb || EXIT_CODE=1 exit $EXIT_CODE From 71e7e6ddc73175df0793748e290e29321934fd7c Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Wed, 26 Dec 2018 12:29:52 -0800 Subject: [PATCH 278/375] Add Watch method to health check service --- .../grpc_health/v1/health.py | 76 +++++++- .../health_check/_health_servicer_test.py | 174 ++++++++++++++++-- 2 files changed, 223 insertions(+), 27 deletions(-) diff --git a/src/python/grpcio_health_checking/grpc_health/v1/health.py b/src/python/grpcio_health_checking/grpc_health/v1/health.py index 05836594281..75c480b0a7a 100644 --- a/src/python/grpcio_health_checking/grpc_health/v1/health.py +++ b/src/python/grpcio_health_checking/grpc_health/v1/health.py @@ -23,15 +23,61 @@ from grpc_health.v1 import health_pb2_grpc as _health_pb2_grpc SERVICE_NAME = _health_pb2.DESCRIPTOR.services_by_name['Health'].full_name +class _Watcher(): + + def __init__(self): + self._condition = threading.Condition() + self._responses = list() + self._open = True + + def __iter__(self): + return self + + def _next(self): + with self._condition: + while not self._responses and self._open: + self._condition.wait() + if self._responses: + return self._responses.pop(0) + else: + raise StopIteration() + + def next(self): + return self._next() + + def __next__(self): + return self._next() + + def add(self, response): + with self._condition: + self._responses.append(response) + self._condition.notify() + + def close(self): + with self._condition: + self._open = False + self._condition.notify() + + class HealthServicer(_health_pb2_grpc.HealthServicer): """Servicer handling RPCs for service statuses.""" def __init__(self): - self._server_status_lock = threading.Lock() + self._lock = threading.RLock() self._server_status = {} + self._watchers = {} + + def _on_close_callback(self, watcher, service): + + def callback(): + with self._lock: + self._watchers[service].remove(watcher) + watcher.close() + + return callback def Check(self, request, context): - with self._server_status_lock: + with self._lock: status = self._server_status.get(request.service) if status is None: context.set_code(grpc.StatusCode.NOT_FOUND) @@ -39,14 +85,30 @@ class HealthServicer(_health_pb2_grpc.HealthServicer): else: return _health_pb2.HealthCheckResponse(status=status) + def Watch(self, request, context): + service = request.service + with self._lock: + status = self._server_status.get(service) + if status is None: + status = _health_pb2.HealthCheckResponse.SERVICE_UNKNOWN # pylint: disable=no-member + watcher = _Watcher() + watcher.add(_health_pb2.HealthCheckResponse(status=status)) + if service not in self._watchers: + self._watchers[service] = set() + self._watchers[service].add(watcher) + context.add_callback(self._on_close_callback(watcher, service)) + return watcher + def set(self, service, status): """Sets the status of a service. Args: - service: string, the name of the service. - NOTE, '' must be set. - status: HealthCheckResponse.status enum value indicating - the status of the service + service: string, the name of the service. NOTE, '' must be set. + status: HealthCheckResponse.status enum value indicating the status of + the service """ - with self._server_status_lock: + with self._lock: self._server_status[service] = status + if service in self._watchers: + for watcher in self._watchers[service]: + watcher.add(_health_pb2.HealthCheckResponse(status=status)) diff --git a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py index c1d9436c2fa..657ceef1e48 100644 --- a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py +++ b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py @@ -13,6 +13,7 @@ # limitations under the License. """Tests of grpc_health.v1.health.""" +import threading import unittest import grpc @@ -22,21 +23,36 @@ from grpc_health.v1 import health_pb2_grpc from tests.unit import test_common +from six.moves import queue + +_QUEUE_TIMEOUT_S = 5 + +_SERVING_SERVICE = 'grpc.test.TestServiceServing' +_UNKNOWN_SERVICE = 'grpc.test.TestServiceUnknown' +_NOT_SERVING_SERVICE = 'grpc.test.TestServiceNotServing' +_WATCH_SERVICE = 'grpc.test.WatchService' + + +def _consume_responses(response_iterator, response_queue): + for response in response_iterator: + response_queue.put(response) + class HealthServicerTest(unittest.TestCase): def setUp(self): - servicer = health.HealthServicer() - servicer.set('', health_pb2.HealthCheckResponse.SERVING) - servicer.set('grpc.test.TestServiceServing', - health_pb2.HealthCheckResponse.SERVING) - servicer.set('grpc.test.TestServiceUnknown', - health_pb2.HealthCheckResponse.UNKNOWN) - servicer.set('grpc.test.TestServiceNotServing', - health_pb2.HealthCheckResponse.NOT_SERVING) + self._servicer = health.HealthServicer() + self._servicer.set('', health_pb2.HealthCheckResponse.SERVING) + self._servicer.set(_SERVING_SERVICE, + health_pb2.HealthCheckResponse.SERVING) + self._servicer.set(_UNKNOWN_SERVICE, + health_pb2.HealthCheckResponse.UNKNOWN) + self._servicer.set(_NOT_SERVING_SERVICE, + health_pb2.HealthCheckResponse.NOT_SERVING) self._server = test_common.test_server() port = self._server.add_insecure_port('[::]:0') - health_pb2_grpc.add_HealthServicer_to_server(servicer, self._server) + health_pb2_grpc.add_HealthServicer_to_server(self._servicer, + self._server) self._server.start() self._channel = grpc.insecure_channel('localhost:%d' % port) @@ -46,37 +62,155 @@ class HealthServicerTest(unittest.TestCase): self._server.stop(None) self._channel.close() - def test_empty_service(self): + def test_check_empty_service(self): request = health_pb2.HealthCheckRequest() resp = self._stub.Check(request) self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status) - def test_serving_service(self): - request = health_pb2.HealthCheckRequest( - service='grpc.test.TestServiceServing') + def test_check_serving_service(self): + request = health_pb2.HealthCheckRequest(service=_SERVING_SERVICE) resp = self._stub.Check(request) self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status) - def test_unknown_serivce(self): - request = health_pb2.HealthCheckRequest( - service='grpc.test.TestServiceUnknown') + def test_check_unknown_serivce(self): + request = health_pb2.HealthCheckRequest(service=_UNKNOWN_SERVICE) resp = self._stub.Check(request) self.assertEqual(health_pb2.HealthCheckResponse.UNKNOWN, resp.status) - def test_not_serving_service(self): - request = health_pb2.HealthCheckRequest( - service='grpc.test.TestServiceNotServing') + def test_check_not_serving_service(self): + request = health_pb2.HealthCheckRequest(service=_NOT_SERVING_SERVICE) resp = self._stub.Check(request) self.assertEqual(health_pb2.HealthCheckResponse.NOT_SERVING, resp.status) - def test_not_found_service(self): + def test_check_not_found_service(self): request = health_pb2.HealthCheckRequest(service='not-found') with self.assertRaises(grpc.RpcError) as context: resp = self._stub.Check(request) self.assertEqual(grpc.StatusCode.NOT_FOUND, context.exception.code()) + def test_watch_empty_service(self): + request = health_pb2.HealthCheckRequest(service='') + response_queue = queue.Queue() + rendezvous = self._stub.Watch(request) + thread = threading.Thread( + target=_consume_responses, args=(rendezvous, response_queue)) + thread.start() + + response = response_queue.get(timeout=_QUEUE_TIMEOUT_S) + self.assertEqual(health_pb2.HealthCheckResponse.SERVING, + response.status) + + rendezvous.cancel() + thread.join() + self.assertTrue(response_queue.empty()) + + def test_watch_new_service(self): + request = health_pb2.HealthCheckRequest(service=_WATCH_SERVICE) + response_queue = queue.Queue() + rendezvous = self._stub.Watch(request) + thread = threading.Thread( + target=_consume_responses, args=(rendezvous, response_queue)) + thread.start() + + response = response_queue.get(timeout=_QUEUE_TIMEOUT_S) + self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN, + response.status) + + self._servicer.set(_WATCH_SERVICE, + health_pb2.HealthCheckResponse.SERVING) + response = response_queue.get(timeout=_QUEUE_TIMEOUT_S) + self.assertEqual(health_pb2.HealthCheckResponse.SERVING, + response.status) + + self._servicer.set(_WATCH_SERVICE, + health_pb2.HealthCheckResponse.NOT_SERVING) + response = response_queue.get(timeout=_QUEUE_TIMEOUT_S) + self.assertEqual(health_pb2.HealthCheckResponse.NOT_SERVING, + response.status) + + rendezvous.cancel() + thread.join() + self.assertTrue(response_queue.empty()) + + def test_watch_service_isolation(self): + request = health_pb2.HealthCheckRequest(service=_WATCH_SERVICE) + response_queue = queue.Queue() + rendezvous = self._stub.Watch(request) + thread = threading.Thread( + target=_consume_responses, args=(rendezvous, response_queue)) + thread.start() + + response = response_queue.get(timeout=_QUEUE_TIMEOUT_S) + self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN, + response.status) + + self._servicer.set('some-other-service', + health_pb2.HealthCheckResponse.SERVING) + with self.assertRaises(queue.Empty) as context: + response_queue.get(timeout=_QUEUE_TIMEOUT_S) + + rendezvous.cancel() + thread.join() + self.assertTrue(response_queue.empty()) + + def test_two_watchers(self): + request = health_pb2.HealthCheckRequest(service=_WATCH_SERVICE) + response_queue1 = queue.Queue() + response_queue2 = queue.Queue() + rendezvous1 = self._stub.Watch(request) + rendezvous2 = self._stub.Watch(request) + thread1 = threading.Thread( + target=_consume_responses, args=(rendezvous1, response_queue1)) + thread2 = threading.Thread( + target=_consume_responses, args=(rendezvous2, response_queue2)) + thread1.start() + thread2.start() + + response1 = response_queue1.get(timeout=_QUEUE_TIMEOUT_S) + response2 = response_queue2.get(timeout=_QUEUE_TIMEOUT_S) + self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN, + response1.status) + self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN, + response2.status) + + self._servicer.set(_WATCH_SERVICE, + health_pb2.HealthCheckResponse.SERVING) + response1 = response_queue1.get(timeout=_QUEUE_TIMEOUT_S) + response2 = response_queue2.get(timeout=_QUEUE_TIMEOUT_S) + self.assertEqual(health_pb2.HealthCheckResponse.SERVING, + response1.status) + self.assertEqual(health_pb2.HealthCheckResponse.SERVING, + response2.status) + + rendezvous1.cancel() + rendezvous2.cancel() + thread1.join() + thread2.join() + self.assertTrue(response_queue1.empty()) + self.assertTrue(response_queue2.empty()) + + def test_cancelled_watch_removed_from_watch_list(self): + request = health_pb2.HealthCheckRequest(service=_WATCH_SERVICE) + response_queue = queue.Queue() + rendezvous = self._stub.Watch(request) + thread = threading.Thread( + target=_consume_responses, args=(rendezvous, response_queue)) + thread.start() + + response = response_queue.get(timeout=_QUEUE_TIMEOUT_S) + self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN, + response.status) + + rendezvous.cancel() + self._servicer.set(_WATCH_SERVICE, + health_pb2.HealthCheckResponse.SERVING) + thread.join() + self.assertFalse(self._servicer._watchers[_WATCH_SERVICE], + 'watch set should be empty') + self.assertTrue(response_queue.empty()) + def test_health_service_name(self): self.assertEqual(health.SERVICE_NAME, 'grpc.health.v1.Health') From b74af8c70bad274c4955a0e242c725409872342d Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Wed, 26 Dec 2018 15:04:38 -0800 Subject: [PATCH 279/375] skip test with gevent --- src/python/grpcio_tests/commands.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py index d5327711d33..582ce898dee 100644 --- a/src/python/grpcio_tests/commands.py +++ b/src/python/grpcio_tests/commands.py @@ -141,6 +141,7 @@ class TestGevent(setuptools.Command): 'unit._exit_test.ExitTest.test_in_flight_partial_unary_stream_call', 'unit._exit_test.ExitTest.test_in_flight_partial_stream_unary_call', 'unit._exit_test.ExitTest.test_in_flight_partial_stream_stream_call', + 'health_check._health_servicer_test.HealthServicerTest.test_cancelled_watch_removed_from_watch_list', # TODO(https://github.com/grpc/grpc/issues/17330) enable these three tests 'channelz._channelz_servicer_test.ChannelzServicerTest.test_many_subchannels', 'channelz._channelz_servicer_test.ChannelzServicerTest.test_many_subchannels_and_sockets', From e678187996bb7239315f30d9e50734c50ee4027b Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Thu, 27 Dec 2018 09:39:53 -0800 Subject: [PATCH 280/375] use test constants, fix formatting --- .../grpc_health/v1/health.py | 10 +++---- .../health_check/_health_servicer_test.py | 27 +++++++++---------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/python/grpcio_health_checking/grpc_health/v1/health.py b/src/python/grpcio_health_checking/grpc_health/v1/health.py index 75c480b0a7a..0a5bbb5504c 100644 --- a/src/python/grpcio_health_checking/grpc_health/v1/health.py +++ b/src/python/grpcio_health_checking/grpc_health/v1/health.py @@ -102,11 +102,11 @@ class HealthServicer(_health_pb2_grpc.HealthServicer): def set(self, service, status): """Sets the status of a service. - Args: - service: string, the name of the service. NOTE, '' must be set. - status: HealthCheckResponse.status enum value indicating the status of - the service - """ + Args: + service: string, the name of the service. NOTE, '' must be set. + status: HealthCheckResponse.status enum value indicating the status of + the service + """ with self._lock: self._server_status[service] = status if service in self._watchers: diff --git a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py index 657ceef1e48..bf90fa15c0e 100644 --- a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py +++ b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py @@ -22,11 +22,10 @@ from grpc_health.v1 import health_pb2 from grpc_health.v1 import health_pb2_grpc from tests.unit import test_common +from tests.unit.framework.common import test_constants from six.moves import queue -_QUEUE_TIMEOUT_S = 5 - _SERVING_SERVICE = 'grpc.test.TestServiceServing' _UNKNOWN_SERVICE = 'grpc.test.TestServiceUnknown' _NOT_SERVING_SERVICE = 'grpc.test.TestServiceNotServing' @@ -98,7 +97,7 @@ class HealthServicerTest(unittest.TestCase): target=_consume_responses, args=(rendezvous, response_queue)) thread.start() - response = response_queue.get(timeout=_QUEUE_TIMEOUT_S) + response = response_queue.get(timeout=test_constants.SHORT_TIMEOUT) self.assertEqual(health_pb2.HealthCheckResponse.SERVING, response.status) @@ -114,19 +113,19 @@ class HealthServicerTest(unittest.TestCase): target=_consume_responses, args=(rendezvous, response_queue)) thread.start() - response = response_queue.get(timeout=_QUEUE_TIMEOUT_S) + response = response_queue.get(timeout=test_constants.SHORT_TIMEOUT) self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN, response.status) self._servicer.set(_WATCH_SERVICE, health_pb2.HealthCheckResponse.SERVING) - response = response_queue.get(timeout=_QUEUE_TIMEOUT_S) + response = response_queue.get(timeout=test_constants.SHORT_TIMEOUT) self.assertEqual(health_pb2.HealthCheckResponse.SERVING, response.status) self._servicer.set(_WATCH_SERVICE, health_pb2.HealthCheckResponse.NOT_SERVING) - response = response_queue.get(timeout=_QUEUE_TIMEOUT_S) + response = response_queue.get(timeout=test_constants.SHORT_TIMEOUT) self.assertEqual(health_pb2.HealthCheckResponse.NOT_SERVING, response.status) @@ -142,14 +141,14 @@ class HealthServicerTest(unittest.TestCase): target=_consume_responses, args=(rendezvous, response_queue)) thread.start() - response = response_queue.get(timeout=_QUEUE_TIMEOUT_S) + response = response_queue.get(timeout=test_constants.SHORT_TIMEOUT) self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN, response.status) self._servicer.set('some-other-service', health_pb2.HealthCheckResponse.SERVING) - with self.assertRaises(queue.Empty) as context: - response_queue.get(timeout=_QUEUE_TIMEOUT_S) + with self.assertRaises(queue.Empty): + response_queue.get(timeout=test_constants.SHORT_TIMEOUT) rendezvous.cancel() thread.join() @@ -168,8 +167,8 @@ class HealthServicerTest(unittest.TestCase): thread1.start() thread2.start() - response1 = response_queue1.get(timeout=_QUEUE_TIMEOUT_S) - response2 = response_queue2.get(timeout=_QUEUE_TIMEOUT_S) + response1 = response_queue1.get(timeout=test_constants.SHORT_TIMEOUT) + response2 = response_queue2.get(timeout=test_constants.SHORT_TIMEOUT) self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN, response1.status) self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN, @@ -177,8 +176,8 @@ class HealthServicerTest(unittest.TestCase): self._servicer.set(_WATCH_SERVICE, health_pb2.HealthCheckResponse.SERVING) - response1 = response_queue1.get(timeout=_QUEUE_TIMEOUT_S) - response2 = response_queue2.get(timeout=_QUEUE_TIMEOUT_S) + response1 = response_queue1.get(timeout=test_constants.SHORT_TIMEOUT) + response2 = response_queue2.get(timeout=test_constants.SHORT_TIMEOUT) self.assertEqual(health_pb2.HealthCheckResponse.SERVING, response1.status) self.assertEqual(health_pb2.HealthCheckResponse.SERVING, @@ -199,7 +198,7 @@ class HealthServicerTest(unittest.TestCase): target=_consume_responses, args=(rendezvous, response_queue)) thread.start() - response = response_queue.get(timeout=_QUEUE_TIMEOUT_S) + response = response_queue.get(timeout=test_constants.SHORT_TIMEOUT) self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN, response.status) From 4e3e46df2249bbd6ba8f3330c0a44ca508d0f35c Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Thu, 27 Dec 2018 11:53:54 -0800 Subject: [PATCH 281/375] fix test --- src/python/grpcio_tests/tests/health_check/BUILD.bazel | 1 + .../tests/health_check/_health_servicer_test.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/python/grpcio_tests/tests/health_check/BUILD.bazel b/src/python/grpcio_tests/tests/health_check/BUILD.bazel index 19e1e1b2e1e..77bc61aa30e 100644 --- a/src/python/grpcio_tests/tests/health_check/BUILD.bazel +++ b/src/python/grpcio_tests/tests/health_check/BUILD.bazel @@ -9,6 +9,7 @@ py_test( "//src/python/grpcio/grpc:grpcio", "//src/python/grpcio_health_checking/grpc_health/v1:grpc_health", "//src/python/grpcio_tests/tests/unit:test_common", + "//src/python/grpcio_tests/tests/unit/framework/common:common", ], imports = ["../../",], ) diff --git a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py index bf90fa15c0e..35794987bc8 100644 --- a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py +++ b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py @@ -14,6 +14,7 @@ """Tests of grpc_health.v1.health.""" import threading +import time import unittest import grpc @@ -206,6 +207,11 @@ class HealthServicerTest(unittest.TestCase): self._servicer.set(_WATCH_SERVICE, health_pb2.HealthCheckResponse.SERVING) thread.join() + + # Wait, if necessary, for serving thread to process client cancellation + timeout = time.time() + test_constants.SHORT_TIMEOUT + while time.time() < timeout and self._servicer._watchers[_WATCH_SERVICE]: + time.sleep(1) self.assertFalse(self._servicer._watchers[_WATCH_SERVICE], 'watch set should be empty') self.assertTrue(response_queue.empty()) From dd4830eae80143f5b0a9a3a1a024af4cf60e7d02 Mon Sep 17 00:00:00 2001 From: Richard Belleville Date: Fri, 21 Dec 2018 13:44:20 -0800 Subject: [PATCH 282/375] Make gRPC version string available as grpc.__version__ --- doc/python/sphinx/grpc.rst | 5 ++++ src/python/grpcio/grpc/__init__.py | 5 ++++ src/python/grpcio_tests/tests/tests.json | 1 + .../grpcio_tests/tests/unit/BUILD.bazel | 1 + .../grpcio_tests/tests/unit/_version_test.py | 30 +++++++++++++++++++ 5 files changed, 42 insertions(+) create mode 100644 src/python/grpcio_tests/tests/unit/_version_test.py diff --git a/doc/python/sphinx/grpc.rst b/doc/python/sphinx/grpc.rst index bd2df9596b0..f534d25c639 100644 --- a/doc/python/sphinx/grpc.rst +++ b/doc/python/sphinx/grpc.rst @@ -19,6 +19,11 @@ Go to `gRPC Python Examples Date: Thu, 27 Dec 2018 15:21:12 -0800 Subject: [PATCH 283/375] Free grpc_channel_args after creation --- .../grpc/_cython/_cygrpc/arguments.pxd.pxi | 13 ++++--- .../grpc/_cython/_cygrpc/arguments.pyx.pxi | 37 +++++++++++-------- .../grpc/_cython/_cygrpc/channel.pyx.pxi | 9 ++--- .../grpc/_cython/_cygrpc/server.pxd.pxi | 1 - .../grpc/_cython/_cygrpc/server.pyx.pxi | 8 ++-- 5 files changed, 37 insertions(+), 31 deletions(-) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/arguments.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/arguments.pxd.pxi index e0e068e4524..01b82374845 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/arguments.pxd.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/arguments.pxd.pxi @@ -28,19 +28,22 @@ cdef tuple _wrap_grpc_arg(grpc_arg arg) cdef grpc_arg _unwrap_grpc_arg(tuple wrapped_arg) -cdef class _ArgumentProcessor: +cdef class _ChannelArg: cdef grpc_arg c_argument cdef void c(self, argument, grpc_arg_pointer_vtable *vtable, references) except * -cdef class _ArgumentsProcessor: +cdef class _ChannelArgs: cdef readonly tuple _arguments - cdef list _argument_processors + cdef list _channel_args cdef readonly list _references cdef grpc_channel_args _c_arguments - cdef grpc_channel_args *c(self, grpc_arg_pointer_vtable *vtable) except * - cdef un_c(self) + cdef void _c(self, grpc_arg_pointer_vtable *vtable) except * + cdef grpc_channel_args *c_args(self) except * + + @staticmethod + cdef _ChannelArgs from_args(object arguments, grpc_arg_pointer_vtable * vtable) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/arguments.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/arguments.pyx.pxi index b7a4277ff64..bf12871015d 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/arguments.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/arguments.pyx.pxi @@ -50,7 +50,7 @@ cdef grpc_arg _unwrap_grpc_arg(tuple wrapped_arg): return wrapped.arg -cdef class _ArgumentProcessor: +cdef class _ChannelArg: cdef void c(self, argument, grpc_arg_pointer_vtable *vtable, references) except *: key, value = argument @@ -82,27 +82,34 @@ cdef class _ArgumentProcessor: 'Expected int, bytes, or behavior, got {}'.format(type(value))) -cdef class _ArgumentsProcessor: +cdef class _ChannelArgs: def __cinit__(self, arguments): self._arguments = () if arguments is None else tuple(arguments) - self._argument_processors = [] + self._channel_args = [] self._references = [] + self._c_arguments.arguments = NULL - cdef grpc_channel_args *c(self, grpc_arg_pointer_vtable *vtable) except *: + cdef void _c(self, grpc_arg_pointer_vtable *vtable) except *: self._c_arguments.arguments_length = len(self._arguments) - if self._c_arguments.arguments_length == 0: - return NULL - else: + if self._c_arguments.arguments_length != 0: self._c_arguments.arguments = gpr_malloc( self._c_arguments.arguments_length * sizeof(grpc_arg)) for index, argument in enumerate(self._arguments): - argument_processor = _ArgumentProcessor() - argument_processor.c(argument, vtable, self._references) - self._c_arguments.arguments[index] = argument_processor.c_argument - self._argument_processors.append(argument_processor) - return &self._c_arguments - - cdef un_c(self): - if self._arguments: + channel_arg = _ChannelArg() + channel_arg.c(argument, vtable, self._references) + self._c_arguments.arguments[index] = channel_arg.c_argument + self._channel_args.append(channel_arg) + + cdef grpc_channel_args *c_args(self) except *: + return &self._c_arguments + + def __dealloc__(self): + if self._c_arguments.arguments != NULL: gpr_free(self._c_arguments.arguments) + + @staticmethod + cdef _ChannelArgs from_args(object arguments, grpc_arg_pointer_vtable * vtable): + cdef _ChannelArgs channel_args = _ChannelArgs(arguments) + channel_args._c(vtable) + return channel_args diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi index 135d224095e..70d4abb7308 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi @@ -423,16 +423,15 @@ cdef class Channel: self._vtable.copy = &_copy_pointer self._vtable.destroy = &_destroy_pointer self._vtable.cmp = &_compare_pointer - cdef _ArgumentsProcessor arguments_processor = _ArgumentsProcessor( - arguments) - cdef grpc_channel_args *c_arguments = arguments_processor.c(&self._vtable) + cdef _ChannelArgs channel_args = _ChannelArgs.from_args( + arguments, &self._vtable) if channel_credentials is None: self._state.c_channel = grpc_insecure_channel_create( - target, c_arguments, NULL) + target, channel_args.c_args(), NULL) else: c_channel_credentials = channel_credentials.c() self._state.c_channel = grpc_secure_channel_create( - c_channel_credentials, target, c_arguments, NULL) + c_channel_credentials, target, channel_args.c_args(), NULL) grpc_channel_credentials_release(c_channel_credentials) self._state.c_call_completion_queue = ( grpc_completion_queue_create_for_next(NULL)) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi index 52cfccb6779..4a6fbe0f96c 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi @@ -16,7 +16,6 @@ cdef class Server: cdef grpc_arg_pointer_vtable _vtable - cdef readonly _ArgumentsProcessor _arguments_processor cdef grpc_server *c_server cdef bint is_started # start has been called cdef bint is_shutting_down # shutdown has been called diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi index e89e02b171e..d72648a35d0 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi @@ -29,11 +29,9 @@ cdef class Server: self._vtable.copy = &_copy_pointer self._vtable.destroy = &_destroy_pointer self._vtable.cmp = &_compare_pointer - cdef _ArgumentsProcessor arguments_processor = _ArgumentsProcessor( - arguments) - cdef grpc_channel_args *c_arguments = arguments_processor.c(&self._vtable) - self.c_server = grpc_server_create(c_arguments, NULL) - arguments_processor.un_c() + cdef _ChannelArgs channel_args = _ChannelArgs.from_args( + arguments, &self._vtable) + self.c_server = grpc_server_create(channel_args.c_args(), NULL) self.references.append(arguments) self.is_started = False self.is_shutting_down = False From aecc5f7285faedec634c99aff0b48eea86d3861a Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 28 Dec 2018 16:03:20 -0800 Subject: [PATCH 284/375] Add client interceptor test for bidi streaming hijacking interceptor --- .../client_interceptors_end2end_test.cc | 91 +++++++++++++++++++ test/cpp/end2end/interceptors_util.cc | 10 ++ test/cpp/end2end/interceptors_util.h | 3 + 3 files changed, 104 insertions(+) diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 8abf4eb3f49..ab387aa9144 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -270,6 +270,84 @@ class HijackingInterceptorMakesAnotherCallFactory } }; +class BidiStreamingRpcHijackingInterceptor : public experimental::Interceptor { + public: + BidiStreamingRpcHijackingInterceptor(experimental::ClientRpcInfo* info) { + info_ = info; + } + + virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + bool hijack = false; + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { + CheckMetadata(*methods->GetSendInitialMetadata(), "testkey", "testvalue"); + hijack = true; + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + EchoRequest req; + auto* buffer = methods->GetSendMessage(); + auto copied_buffer = *buffer; + EXPECT_TRUE( + SerializationTraits::Deserialize(&copied_buffer, &req) + .ok()); + EXPECT_EQ(req.message().find("Hello"), 0); + msg = req.message(); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { + // Got nothing to do here for now + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_STATUS)) { + CheckMetadata(*methods->GetRecvTrailingMetadata(), "testkey", + "testvalue"); + auto* status = methods->GetRecvStatus(); + EXPECT_EQ(status->ok(), true); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) { + EchoResponse* resp = + static_cast(methods->GetRecvMessage()); + resp->set_message(msg); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { + EXPECT_EQ(static_cast(methods->GetRecvMessage()) + ->message() + .find("Hello"), + 0); + } + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { + auto* map = methods->GetRecvTrailingMetadata(); + // insert the metadata that we want + EXPECT_EQ(map->size(), static_cast(0)); + map->insert(std::make_pair("testkey", "testvalue")); + auto* status = methods->GetRecvStatus(); + *status = Status(StatusCode::OK, ""); + } + if (hijack) { + methods->Hijack(); + } else { + methods->Proceed(); + } + } + + private: + experimental::ClientRpcInfo* info_; + grpc::string msg; +}; + +class BidiStreamingRpcHijackingInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new BidiStreamingRpcHijackingInterceptor(info); + } +}; + class LoggingInterceptor : public experimental::Interceptor { public: LoggingInterceptor(experimental::ClientRpcInfo* info) { info_ = info; } @@ -546,6 +624,19 @@ TEST_F(ClientInterceptorsStreamingEnd2endTest, ServerStreamingTest) { EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); } +TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingHijackingTest) { + ChannelArguments args; + DummyInterceptor::Reset(); + std::vector> + creators; + creators.push_back( + std::unique_ptr( + new BidiStreamingRpcHijackingInterceptorFactory())); + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, InsecureChannelCredentials(), args, std::move(creators)); + MakeBidiStreamingCall(channel); +} + TEST_F(ClientInterceptorsStreamingEnd2endTest, BidiStreamingTest) { ChannelArguments args; DummyInterceptor::Reset(); diff --git a/test/cpp/end2end/interceptors_util.cc b/test/cpp/end2end/interceptors_util.cc index e0ad7d1526c..900f02b5f36 100644 --- a/test/cpp/end2end/interceptors_util.cc +++ b/test/cpp/end2end/interceptors_util.cc @@ -132,6 +132,16 @@ bool CheckMetadata(const std::multimap& map, return false; } +bool CheckMetadata(const std::multimap& map, + const string& key, const string& value) { + for (const auto& pair : map) { + if (pair.first == key && pair.second == value) { + return true; + } + } + return false; +} + std::vector> CreateDummyClientInterceptors() { std::vector> diff --git a/test/cpp/end2end/interceptors_util.h b/test/cpp/end2end/interceptors_util.h index 659e613d2eb..419845e5f61 100644 --- a/test/cpp/end2end/interceptors_util.h +++ b/test/cpp/end2end/interceptors_util.h @@ -165,6 +165,9 @@ void MakeCallbackCall(const std::shared_ptr& channel); bool CheckMetadata(const std::multimap& map, const string& key, const string& value); +bool CheckMetadata(const std::multimap& map, + const string& key, const string& value); + std::vector> CreateDummyClientInterceptors(); From 4aeba4252893755ff13b2cc0edfcc954c6d04a6b Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 28 Dec 2018 17:27:38 -0800 Subject: [PATCH 285/375] Provide GetOriginalSendMessage for some APIs --- include/grpcpp/impl/codegen/call_op_set.h | 29 +++++++++++++++++-- include/grpcpp/impl/codegen/client_callback.h | 6 ++-- .../grpcpp/impl/codegen/client_unary_call.h | 2 +- include/grpcpp/impl/codegen/interceptor.h | 6 ++++ .../grpcpp/impl/codegen/interceptor_common.h | 16 +++++++++- include/grpcpp/impl/codegen/server_callback.h | 8 ++--- include/grpcpp/impl/codegen/sync_stream.h | 10 +++---- .../client_interceptors_end2end_test.cc | 5 ++++ 8 files changed, 66 insertions(+), 16 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index b2100c68b7f..ddee5280cb3 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -303,6 +303,18 @@ class CallOpSendMessage { template Status SendMessage(const M& message) GRPC_MUST_USE_RESULT; + /// Send \a message using \a options for the write. The \a options are cleared + /// after use. This form of SendMessage allows gRPC to reference \a message + /// beyond the lifetime of SendMessage. + template + Status SendMessage(const M* message, + WriteOptions options) GRPC_MUST_USE_RESULT; + + /// This form of SendMessage allows gRPC to reference \a message beyond the + /// lifetime of SendMessage. + template + Status SendMessage(const M* message) GRPC_MUST_USE_RESULT; + protected: void AddOp(grpc_op* ops, size_t* nops) { if (!send_buf_.Valid() || hijacked_) return; @@ -321,14 +333,14 @@ class CallOpSendMessage { if (!send_buf_.Valid()) return; interceptor_methods->AddInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_MESSAGE); - interceptor_methods->SetSendMessage(&send_buf_); + interceptor_methods->SetSendMessage(&send_buf_, msg_); } void SetFinishInterceptionHookPoint( InterceptorBatchMethodsImpl* interceptor_methods) { // The contents of the SendMessage value that was previously set // has had its references stolen by core's operations - interceptor_methods->SetSendMessage(nullptr); + interceptor_methods->SetSendMessage(nullptr, nullptr); } void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) { @@ -336,6 +348,7 @@ class CallOpSendMessage { } private: + const void* msg_ = nullptr; // The original non-serialized message bool hijacked_ = false; ByteBuffer send_buf_; WriteOptions write_options_; @@ -362,6 +375,18 @@ Status CallOpSendMessage::SendMessage(const M& message) { return SendMessage(message, WriteOptions()); } +template +Status CallOpSendMessage::SendMessage(const M* message, WriteOptions options) { + msg_ = message; + return SendMessage(*message, options); +} + +template +Status CallOpSendMessage::SendMessage(const M* message) { + msg_ = message; + return SendMessage(*message, WriteOptions()); +} + template class CallOpRecvMessage { public: diff --git a/include/grpcpp/impl/codegen/client_callback.h b/include/grpcpp/impl/codegen/client_callback.h index 66cf9b7754c..f164db19ec7 100644 --- a/include/grpcpp/impl/codegen/client_callback.h +++ b/include/grpcpp/impl/codegen/client_callback.h @@ -73,7 +73,7 @@ class CallbackUnaryCallImpl { CallbackWithStatusTag(call.call(), on_completion, ops); // TODO(vjpai): Unify code with sync API as much as possible - Status s = ops->SendMessage(*request); + Status s = ops->SendMessage(request); if (!s.ok()) { tag->force_run(s); return; @@ -341,7 +341,7 @@ class ClientCallbackReaderWriterImpl start_corked_ = false; } // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*msg).ok()); + GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok()); if (options.is_last_message()) { options.set_buffer_hint(); @@ -650,7 +650,7 @@ class ClientCallbackWriterImpl start_corked_ = false; } // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*msg).ok()); + GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok()); if (options.is_last_message()) { options.set_buffer_hint(); diff --git a/include/grpcpp/impl/codegen/client_unary_call.h b/include/grpcpp/impl/codegen/client_unary_call.h index 5151839412b..f34da234824 100644 --- a/include/grpcpp/impl/codegen/client_unary_call.h +++ b/include/grpcpp/impl/codegen/client_unary_call.h @@ -57,7 +57,7 @@ class BlockingUnaryCallImpl { CallOpRecvInitialMetadata, CallOpRecvMessage, CallOpClientSendClose, CallOpClientRecvStatus> ops; - status_ = ops.SendMessage(request); + status_ = ops.SendMessage(&request); if (!status_.ok()) { return; } diff --git a/include/grpcpp/impl/codegen/interceptor.h b/include/grpcpp/impl/codegen/interceptor.h index 46175cd73b8..a83d285d130 100644 --- a/include/grpcpp/impl/codegen/interceptor.h +++ b/include/grpcpp/impl/codegen/interceptor.h @@ -111,6 +111,12 @@ class InterceptorBatchMethods { /// A return value of nullptr indicates that this ByteBuffer is not valid. virtual ByteBuffer* GetSendMessage() = 0; + /// Returns a non-modifiable pointer to the original non-serialized form of + /// the message. Valid for PRE_SEND_MESSAGE interceptions. A return value of + /// nullptr indicates that this field is not valid. Also note that this is + /// only supported for sync and callback APIs at the present moment. + virtual const void* GetOriginalSendMessage() = 0; + /// Returns a modifiable multimap of the initial metadata to be sent. Valid /// for PRE_SEND_INITIAL_METADATA interceptions. A value of nullptr indicates /// that this field is not valid. diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index d0aa23cb0a0..bf936368d4c 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -81,6 +81,8 @@ class InterceptorBatchMethodsImpl ByteBuffer* GetSendMessage() override { return send_message_; } + const void* GetOriginalSendMessage() override { return orig_send_message_; } + std::multimap* GetSendInitialMetadata() override { return send_initial_metadata_; } @@ -115,7 +117,10 @@ class InterceptorBatchMethodsImpl return recv_trailing_metadata_->map(); } - void SetSendMessage(ByteBuffer* buf) { send_message_ = buf; } + void SetSendMessage(ByteBuffer* buf, const void* msg) { + send_message_ = buf; + orig_send_message_ = msg; + } void SetSendInitialMetadata( std::multimap* metadata) { @@ -334,6 +339,7 @@ class InterceptorBatchMethodsImpl std::function callback_; ByteBuffer* send_message_ = nullptr; + const void* orig_send_message_ = nullptr; std::multimap* send_initial_metadata_; @@ -386,6 +392,14 @@ class CancelInterceptorBatchMethods return nullptr; } + const void* GetOriginalSendMessage() override { + GPR_CODEGEN_ASSERT( + false && + "It is illegal to call GetOriginalSendMessage on a method which " + "has a Cancel notification"); + return nullptr; + } + std::multimap* GetSendInitialMetadata() override { GPR_CODEGEN_ASSERT(false && "It is illegal to call GetSendInitialMetadata on a " diff --git a/include/grpcpp/impl/codegen/server_callback.h b/include/grpcpp/impl/codegen/server_callback.h index 1854f6ef2f5..b28b7fd9315 100644 --- a/include/grpcpp/impl/codegen/server_callback.h +++ b/include/grpcpp/impl/codegen/server_callback.h @@ -642,7 +642,7 @@ class CallbackServerStreamingHandler : public MethodHandler { ctx_->sent_initial_metadata_ = true; } // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*resp, options).ok()); + GPR_CODEGEN_ASSERT(write_ops_.SendMessage(resp, options).ok()); call_.PerformOps(&write_ops_); } @@ -652,7 +652,7 @@ class CallbackServerStreamingHandler : public MethodHandler { // Don't send any message if the status is bad if (s.ok()) { // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(*resp, options).ok()); + GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(resp, options).ok()); } Finish(std::move(s)); } @@ -804,7 +804,7 @@ class CallbackBidiHandler : public MethodHandler { ctx_->sent_initial_metadata_ = true; } // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*resp, options).ok()); + GPR_CODEGEN_ASSERT(write_ops_.SendMessage(resp, options).ok()); call_.PerformOps(&write_ops_); } @@ -813,7 +813,7 @@ class CallbackBidiHandler : public MethodHandler { // Don't send any message if the status is bad if (s.ok()) { // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(*resp, options).ok()); + GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(resp, options).ok()); } Finish(std::move(s)); } diff --git a/include/grpcpp/impl/codegen/sync_stream.h b/include/grpcpp/impl/codegen/sync_stream.h index 6981076f04e..4645ea3e2f5 100644 --- a/include/grpcpp/impl/codegen/sync_stream.h +++ b/include/grpcpp/impl/codegen/sync_stream.h @@ -253,7 +253,7 @@ class ClientReader final : public ClientReaderInterface { ops.SendInitialMetadata(&context->send_initial_metadata_, context->initial_metadata_flags()); // TODO(ctiller): don't assert - GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok()); + GPR_CODEGEN_ASSERT(ops.SendMessage(&request).ok()); ops.ClientSendClose(); call_.PerformOps(&ops); cq_.Pluck(&ops); @@ -331,7 +331,7 @@ class ClientWriter : public ClientWriterInterface { context_->initial_metadata_flags()); context_->set_initial_metadata_corked(false); } - if (!ops.SendMessage(msg, options).ok()) { + if (!ops.SendMessage(&msg, options).ok()) { return false; } @@ -502,7 +502,7 @@ class ClientReaderWriter final : public ClientReaderWriterInterface { context_->initial_metadata_flags()); context_->set_initial_metadata_corked(false); } - if (!ops.SendMessage(msg, options).ok()) { + if (!ops.SendMessage(&msg, options).ok()) { return false; } @@ -656,7 +656,7 @@ class ServerWriter final : public ServerWriterInterface { options.set_buffer_hint(); } - if (!ctx_->pending_ops_.SendMessage(msg, options).ok()) { + if (!ctx_->pending_ops_.SendMessage(&msg, options).ok()) { return false; } if (!ctx_->sent_initial_metadata_) { @@ -734,7 +734,7 @@ class ServerReaderWriterBody final { if (options.is_last_message()) { options.set_buffer_hint(); } - if (!ctx_->pending_ops_.SendMessage(msg, options).ok()) { + if (!ctx_->pending_ops_.SendMessage(&msg, options).ok()) { return false; } if (!ctx_->sent_initial_metadata_) { diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 8abf4eb3f49..3414ebe64e2 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -293,6 +293,11 @@ class LoggingInterceptor : public experimental::Interceptor { SerializationTraits::Deserialize(&copied_buffer, &req) .ok()); EXPECT_TRUE(req.message().find("Hello") == 0); + EXPECT_EQ( + static_cast(methods->GetOriginalSendMessage()) + ->message() + .find("Hello"), + 0); } if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { From f0e960714e84a1893edc9c971eac6d1df21f3f8c Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 2 Jan 2019 17:22:40 +0100 Subject: [PATCH 286/375] Revert "Revert "basic tcp_trace support for windows"" This reverts commit f438d72e6c5e5bd839a255322fb91c416822f629. --- src/core/lib/iomgr/tcp_windows.cc | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc index 4b5250803d1..aaf9fb4ea8a 100644 --- a/src/core/lib/iomgr/tcp_windows.cc +++ b/src/core/lib/iomgr/tcp_windows.cc @@ -42,6 +42,7 @@ #include "src/core/lib/iomgr/tcp_windows.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/slice/slice_string_helpers.h" #if defined(__MSYS__) && defined(GPR_ARCH_64) /* Nasty workaround for nasty bug when using the 64 bits msys compiler @@ -182,6 +183,10 @@ static void on_read(void* tcpp, grpc_error* error) { grpc_slice sub; grpc_winsocket_callback_info* info = &socket->read_info; + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, "TCP:%p on_read", tcp); + } + GRPC_ERROR_REF(error); if (error == GRPC_ERROR_NONE) { @@ -194,7 +199,21 @@ static void on_read(void* tcpp, grpc_error* error) { if (info->bytes_transfered != 0 && !tcp->shutting_down) { sub = grpc_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered); grpc_slice_buffer_add(tcp->read_slices, sub); + + if (grpc_tcp_trace.enabled()) { + size_t i; + for (i = 0; i < tcp->read_slices->count; i++) { + char* dump = grpc_dump_slice(tcp->read_slices->slices[i], + GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_INFO, "READ %p (peer=%s): %s", tcp, tcp->peer_string, + dump); + gpr_free(dump); + } + } } else { + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, "TCP:%p unref read_slice", tcp); + } grpc_slice_unref_internal(tcp->read_slice); error = tcp->shutting_down ? GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( @@ -219,6 +238,10 @@ static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices, DWORD flags = 0; WSABUF buffer; + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, "TCP:%p win_read", tcp); + } + if (tcp->shutting_down) { GRPC_CLOSURE_SCHED( cb, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( @@ -275,6 +298,10 @@ static void on_write(void* tcpp, grpc_error* error) { grpc_winsocket_callback_info* info = &handle->write_info; grpc_closure* cb; + if (grpc_tcp_trace.enabled()) { + gpr_log(GPR_INFO, "TCP:%p on_write", tcp); + } + GRPC_ERROR_REF(error); gpr_mu_lock(&tcp->mu); @@ -308,6 +335,16 @@ static void win_write(grpc_endpoint* ep, grpc_slice_buffer* slices, WSABUF* buffers = local_buffers; size_t len; + if (grpc_tcp_trace.enabled()) { + size_t i; + for (i = 0; i < slices->count; i++) { + char* data = + grpc_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_INFO, "WRITE %p (peer=%s): %s", tcp, tcp->peer_string, data); + gpr_free(data); + } + } + if (tcp->shutting_down) { GRPC_CLOSURE_SCHED( cb, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( From 12aae4f7bbf996c121550e5934b6da9f52578ef7 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 2 Jan 2019 17:23:00 +0100 Subject: [PATCH 287/375] Revert "Revert "better slice management for win_read"" This reverts commit a050ae8ddc3a64151b344fd1a4d438db9dea2acb. --- src/core/lib/iomgr/tcp_windows.cc | 57 ++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc index aaf9fb4ea8a..86ee1010cf7 100644 --- a/src/core/lib/iomgr/tcp_windows.cc +++ b/src/core/lib/iomgr/tcp_windows.cc @@ -113,7 +113,10 @@ typedef struct grpc_tcp { grpc_closure* read_cb; grpc_closure* write_cb; - grpc_slice read_slice; + + /* garbage after the last read */ + grpc_slice_buffer last_read_buffer; + grpc_slice_buffer* write_slices; grpc_slice_buffer* read_slices; @@ -132,6 +135,7 @@ static void tcp_free(grpc_tcp* tcp) { grpc_winsocket_destroy(tcp->socket); gpr_mu_destroy(&tcp->mu); gpr_free(tcp->peer_string); + grpc_slice_buffer_destroy_internal(&tcp->last_read_buffer); grpc_resource_user_unref(tcp->resource_user); if (tcp->shutting_down) GRPC_ERROR_UNREF(tcp->shutdown_error); gpr_free(tcp); @@ -180,7 +184,6 @@ static void on_read(void* tcpp, grpc_error* error) { grpc_tcp* tcp = (grpc_tcp*)tcpp; grpc_closure* cb = tcp->read_cb; grpc_winsocket* socket = tcp->socket; - grpc_slice sub; grpc_winsocket_callback_info* info = &socket->read_info; if (grpc_tcp_trace.enabled()) { @@ -194,11 +197,19 @@ static void on_read(void* tcpp, grpc_error* error) { char* utf8_message = gpr_format_message(info->wsa_error); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(utf8_message); gpr_free(utf8_message); - grpc_slice_unref_internal(tcp->read_slice); + grpc_slice_buffer_reset_and_unref_internal(tcp->read_slices); } else { if (info->bytes_transfered != 0 && !tcp->shutting_down) { - sub = grpc_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered); - grpc_slice_buffer_add(tcp->read_slices, sub); + GPR_ASSERT((size_t)info->bytes_transfered <= tcp->read_slices->length); + if (static_cast(info->bytes_transfered) != + tcp->read_slices->length) { + grpc_slice_buffer_trim_end( + tcp->read_slices, + tcp->read_slices->length - + static_cast(info->bytes_transfered), + &tcp->last_read_buffer); + } + GPR_ASSERT((size_t)info->bytes_transfered == tcp->read_slices->length); if (grpc_tcp_trace.enabled()) { size_t i; @@ -214,7 +225,7 @@ static void on_read(void* tcpp, grpc_error* error) { if (grpc_tcp_trace.enabled()) { gpr_log(GPR_INFO, "TCP:%p unref read_slice", tcp); } - grpc_slice_unref_internal(tcp->read_slice); + grpc_slice_buffer_reset_and_unref_internal(tcp->read_slices); error = tcp->shutting_down ? GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "TCP stream shutting down", &tcp->shutdown_error, 1) @@ -228,6 +239,8 @@ static void on_read(void* tcpp, grpc_error* error) { GRPC_CLOSURE_SCHED(cb, error); } +#define DEFAULT_TARGET_READ_SIZE 8192 +#define MAX_WSABUF_COUNT 16 static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices, grpc_closure* cb) { grpc_tcp* tcp = (grpc_tcp*)ep; @@ -236,7 +249,8 @@ static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices, int status; DWORD bytes_read = 0; DWORD flags = 0; - WSABUF buffer; + WSABUF buffers[MAX_WSABUF_COUNT]; + size_t i; if (grpc_tcp_trace.enabled()) { gpr_log(GPR_INFO, "TCP:%p win_read", tcp); @@ -252,18 +266,27 @@ static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices, tcp->read_cb = cb; tcp->read_slices = read_slices; grpc_slice_buffer_reset_and_unref_internal(read_slices); + grpc_slice_buffer_swap(read_slices, &tcp->last_read_buffer); - tcp->read_slice = GRPC_SLICE_MALLOC(8192); + if (tcp->read_slices->length < DEFAULT_TARGET_READ_SIZE / 2 && + tcp->read_slices->count < MAX_WSABUF_COUNT) { + // TODO(jtattermusch): slice should be allocated using resource quota + grpc_slice_buffer_add(tcp->read_slices, + GRPC_SLICE_MALLOC(DEFAULT_TARGET_READ_SIZE)); + } - buffer.len = (ULONG)GRPC_SLICE_LENGTH( - tcp->read_slice); // we know slice size fits in 32bit. - buffer.buf = (char*)GRPC_SLICE_START_PTR(tcp->read_slice); + GPR_ASSERT(tcp->read_slices->count <= MAX_WSABUF_COUNT); + for (i = 0; i < tcp->read_slices->count; i++) { + buffers[i].len = (ULONG)GRPC_SLICE_LENGTH( + tcp->read_slices->slices[i]); // we know slice size fits in 32bit. + buffers[i].buf = (char*)GRPC_SLICE_START_PTR(tcp->read_slices->slices[i]); + } TCP_REF(tcp, "read"); /* First let's try a synchronous, non-blocking read. */ - status = - WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, NULL, NULL); + status = WSARecv(tcp->socket->socket, buffers, (DWORD)tcp->read_slices->count, + &bytes_read, &flags, NULL, NULL); info->wsa_error = status == 0 ? 0 : WSAGetLastError(); /* Did we get data immediately ? Yay. */ @@ -275,8 +298,8 @@ static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices, /* Otherwise, let's retry, by queuing a read. */ memset(&tcp->socket->read_info.overlapped, 0, sizeof(OVERLAPPED)); - status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, - &info->overlapped, NULL); + status = WSARecv(tcp->socket->socket, buffers, (DWORD)tcp->read_slices->count, + &bytes_read, &flags, &info->overlapped, NULL); if (status != 0) { int wsa_error = WSAGetLastError(); @@ -330,7 +353,7 @@ static void win_write(grpc_endpoint* ep, grpc_slice_buffer* slices, unsigned i; DWORD bytes_sent; int status; - WSABUF local_buffers[16]; + WSABUF local_buffers[MAX_WSABUF_COUNT]; WSABUF* allocated = NULL; WSABUF* buffers = local_buffers; size_t len; @@ -449,6 +472,7 @@ static void win_shutdown(grpc_endpoint* ep, grpc_error* why) { static void win_destroy(grpc_endpoint* ep) { grpc_network_status_unregister_endpoint(ep); grpc_tcp* tcp = (grpc_tcp*)ep; + grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); TCP_UNREF(tcp, "destroy"); } @@ -500,6 +524,7 @@ grpc_endpoint* grpc_tcp_create(grpc_winsocket* socket, GRPC_CLOSURE_INIT(&tcp->on_read, on_read, tcp, grpc_schedule_on_exec_ctx); GRPC_CLOSURE_INIT(&tcp->on_write, on_write, tcp, grpc_schedule_on_exec_ctx); tcp->peer_string = gpr_strdup(peer_string); + grpc_slice_buffer_init(&tcp->last_read_buffer); tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); /* Tell network status tracking code about the new endpoint */ grpc_network_status_register_endpoint(&tcp->base); From 80e2022cbe117313c53fc89be388c213342a058f Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 2 Jan 2019 17:20:03 +0100 Subject: [PATCH 288/375] use stderr buffering for "+trace" windows tests --- test/core/end2end/fixtures/h2_full+trace.cc | 9 +++++++++ test/core/end2end/fixtures/h2_sockpair+trace.cc | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/test/core/end2end/fixtures/h2_full+trace.cc b/test/core/end2end/fixtures/h2_full+trace.cc index 2bbad487013..ce8f6bf13a5 100644 --- a/test/core/end2end/fixtures/h2_full+trace.cc +++ b/test/core/end2end/fixtures/h2_full+trace.cc @@ -113,6 +113,15 @@ int main(int argc, char** argv) { g_fixture_slowdown_factor = 10; #endif +#ifdef GPR_WINDOWS + /* on Windows, writing logs to stderr is very slow + when stderr is redirected to a disk file. + The "trace" tests fixtures generates large amount + of logs, so setting a buffer for stderr prevents certain + test cases from timing out. */ + setvbuf(stderr, NULL, _IOLBF, 1024); +#endif + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.cc b/test/core/end2end/fixtures/h2_sockpair+trace.cc index 45f78b59642..4494d5c4746 100644 --- a/test/core/end2end/fixtures/h2_sockpair+trace.cc +++ b/test/core/end2end/fixtures/h2_sockpair+trace.cc @@ -140,6 +140,15 @@ int main(int argc, char** argv) { g_fixture_slowdown_factor = 10; #endif +#ifdef GPR_WINDOWS + /* on Windows, writing logs to stderr is very slow + when stderr is redirected to a disk file. + The "trace" tests fixtures generates large amount + of logs, so setting a buffer for stderr prevents certain + test cases from timing out. */ + setvbuf(stderr, NULL, _IOLBF, 1024); +#endif + grpc::testing::TestEnvironment env(argc, argv); grpc_end2end_tests_pre_init(); grpc_init(); From 9c5ca8365c650c8891ef222b43edb1514e7d36f3 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 2 Jan 2019 23:03:30 +0100 Subject: [PATCH 289/375] Revert "Implement a lock-free fast path for queue_call_request()" --- src/core/lib/surface/server.cc | 104 +++++++++++++-------------------- 1 file changed, 41 insertions(+), 63 deletions(-) diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc index 67b38e6f0c0..7ae6e51a5fb 100644 --- a/src/core/lib/surface/server.cc +++ b/src/core/lib/surface/server.cc @@ -194,13 +194,10 @@ struct call_data { }; struct request_matcher { - request_matcher(grpc_server* server); - ~request_matcher(); - grpc_server* server; - std::atomic pending_head{nullptr}; - call_data* pending_tail = nullptr; - gpr_locked_mpscq* requests_per_cq = nullptr; + call_data* pending_head; + call_data* pending_tail; + gpr_locked_mpscq* requests_per_cq; }; struct registered_method { @@ -349,30 +346,22 @@ static void channel_broadcaster_shutdown(channel_broadcaster* cb, * request_matcher */ -namespace { -request_matcher::request_matcher(grpc_server* server) : server(server) { - requests_per_cq = static_cast( - gpr_malloc(sizeof(*requests_per_cq) * server->cq_count)); - for (size_t i = 0; i < server->cq_count; i++) { - gpr_locked_mpscq_init(&requests_per_cq[i]); - } -} - -request_matcher::~request_matcher() { +static void request_matcher_init(request_matcher* rm, grpc_server* server) { + memset(rm, 0, sizeof(*rm)); + rm->server = server; + rm->requests_per_cq = static_cast( + gpr_malloc(sizeof(*rm->requests_per_cq) * server->cq_count)); for (size_t i = 0; i < server->cq_count; i++) { - GPR_ASSERT(gpr_locked_mpscq_pop(&requests_per_cq[i]) == nullptr); - gpr_locked_mpscq_destroy(&requests_per_cq[i]); + gpr_locked_mpscq_init(&rm->requests_per_cq[i]); } - gpr_free(requests_per_cq); -} -} // namespace - -static void request_matcher_init(request_matcher* rm, grpc_server* server) { - new (rm) request_matcher(server); } static void request_matcher_destroy(request_matcher* rm) { - rm->~request_matcher(); + for (size_t i = 0; i < rm->server->cq_count; i++) { + GPR_ASSERT(gpr_locked_mpscq_pop(&rm->requests_per_cq[i]) == nullptr); + gpr_locked_mpscq_destroy(&rm->requests_per_cq[i]); + } + gpr_free(rm->requests_per_cq); } static void kill_zombie(void* elem, grpc_error* error) { @@ -381,10 +370,9 @@ static void kill_zombie(void* elem, grpc_error* error) { } static void request_matcher_zombify_all_pending_calls(request_matcher* rm) { - call_data* calld; - while ((calld = rm->pending_head.load(std::memory_order_relaxed)) != - nullptr) { - rm->pending_head.store(calld->pending_next, std::memory_order_relaxed); + while (rm->pending_head) { + call_data* calld = rm->pending_head; + rm->pending_head = calld->pending_next; gpr_atm_no_barrier_store(&calld->state, ZOMBIED); GRPC_CLOSURE_INIT( &calld->kill_zombie_closure, kill_zombie, @@ -582,9 +570,8 @@ static void publish_new_rpc(void* arg, grpc_error* error) { } gpr_atm_no_barrier_store(&calld->state, PENDING); - if (rm->pending_head.load(std::memory_order_relaxed) == nullptr) { - rm->pending_head.store(calld, std::memory_order_relaxed); - rm->pending_tail = calld; + if (rm->pending_head == nullptr) { + rm->pending_tail = rm->pending_head = calld; } else { rm->pending_tail->pending_next = calld; rm->pending_tail = calld; @@ -1448,39 +1435,30 @@ static grpc_call_error queue_call_request(grpc_server* server, size_t cq_idx, rm = &rc->data.registered.method->matcher; break; } - - // Fast path: if there is no pending request to be processed, immediately - // return. - if (!gpr_locked_mpscq_push(&rm->requests_per_cq[cq_idx], &rc->request_link) || - // Note: We are reading the pending_head without holding the server's call - // mutex. Even if we read a non-null value here due to reordering, - // we will check it below again after grabbing the lock. - rm->pending_head.load(std::memory_order_relaxed) == nullptr) { - return GRPC_CALL_OK; - } - // Slow path: This was the first queued request and there are pendings: - // We need to lock and start matching calls. - gpr_mu_lock(&server->mu_call); - while ((calld = rm->pending_head.load(std::memory_order_relaxed)) != - nullptr) { - rc = reinterpret_cast( - gpr_locked_mpscq_pop(&rm->requests_per_cq[cq_idx])); - if (rc == nullptr) break; - rm->pending_head.store(calld->pending_next, std::memory_order_relaxed); - gpr_mu_unlock(&server->mu_call); - if (!gpr_atm_full_cas(&calld->state, PENDING, ACTIVATED)) { - // Zombied Call - GRPC_CLOSURE_INIT( - &calld->kill_zombie_closure, kill_zombie, - grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0), - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_SCHED(&calld->kill_zombie_closure, GRPC_ERROR_NONE); - } else { - publish_call(server, calld, cq_idx, rc); - } + if (gpr_locked_mpscq_push(&rm->requests_per_cq[cq_idx], &rc->request_link)) { + /* this was the first queued request: we need to lock and start + matching calls */ gpr_mu_lock(&server->mu_call); + while ((calld = rm->pending_head) != nullptr) { + rc = reinterpret_cast( + gpr_locked_mpscq_pop(&rm->requests_per_cq[cq_idx])); + if (rc == nullptr) break; + rm->pending_head = calld->pending_next; + gpr_mu_unlock(&server->mu_call); + if (!gpr_atm_full_cas(&calld->state, PENDING, ACTIVATED)) { + // Zombied Call + GRPC_CLOSURE_INIT( + &calld->kill_zombie_closure, kill_zombie, + grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0), + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_SCHED(&calld->kill_zombie_closure, GRPC_ERROR_NONE); + } else { + publish_call(server, calld, cq_idx, rc); + } + gpr_mu_lock(&server->mu_call); + } + gpr_mu_unlock(&server->mu_call); } - gpr_mu_unlock(&server->mu_call); return GRPC_CALL_OK; } From 69e99a827555ce69cb796589189dab4fc6a9375f Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 2 Jan 2019 14:24:30 -0800 Subject: [PATCH 290/375] Add clang fallthrough annotation --- test/core/memory_usage/server.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/test/core/memory_usage/server.cc b/test/core/memory_usage/server.cc index 7424797e6f5..c79d661a422 100644 --- a/test/core/memory_usage/server.cc +++ b/test/core/memory_usage/server.cc @@ -295,6 +295,7 @@ int main(int argc, char** argv) { /* fallthrough */ // no break here since we want to continue to case // FLING_SERVER_SEND_STATUS_SNAPSHOT to destroy the snapshot call + [[fallthrough]]; case FLING_SERVER_SEND_STATUS_SNAPSHOT: grpc_byte_buffer_destroy(payload_buffer); grpc_byte_buffer_destroy(terminal_buffer); From c6261f4b918a88f5b1fc5cd60e1e2b44e8f83a76 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 2 Jan 2019 14:46:52 -0800 Subject: [PATCH 291/375] Rename new SendMessage types to SendMessagePtr --- include/grpcpp/impl/codegen/call_op_set.h | 11 +++--- include/grpcpp/impl/codegen/client_callback.h | 8 ++--- .../grpcpp/impl/codegen/client_unary_call.h | 2 +- .../grpcpp/impl/codegen/method_handler_impl.h | 4 +-- include/grpcpp/impl/codegen/server_callback.h | 12 +++---- include/grpcpp/impl/codegen/sync_stream.h | 10 +++--- .../client_interceptors_end2end_test.cc | 6 ++-- .../server_interceptors_end2end_test.cc | 35 ++++++++++++++++++- 8 files changed, 61 insertions(+), 27 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index ddee5280cb3..310bea93ca7 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -307,13 +307,13 @@ class CallOpSendMessage { /// after use. This form of SendMessage allows gRPC to reference \a message /// beyond the lifetime of SendMessage. template - Status SendMessage(const M* message, - WriteOptions options) GRPC_MUST_USE_RESULT; + Status SendMessagePtr(const M* message, + WriteOptions options) GRPC_MUST_USE_RESULT; /// This form of SendMessage allows gRPC to reference \a message beyond the /// lifetime of SendMessage. template - Status SendMessage(const M* message) GRPC_MUST_USE_RESULT; + Status SendMessagePtr(const M* message) GRPC_MUST_USE_RESULT; protected: void AddOp(grpc_op* ops, size_t* nops) { @@ -376,13 +376,14 @@ Status CallOpSendMessage::SendMessage(const M& message) { } template -Status CallOpSendMessage::SendMessage(const M* message, WriteOptions options) { +Status CallOpSendMessage::SendMessagePtr(const M* message, + WriteOptions options) { msg_ = message; return SendMessage(*message, options); } template -Status CallOpSendMessage::SendMessage(const M* message) { +Status CallOpSendMessage::SendMessagePtr(const M* message) { msg_ = message; return SendMessage(*message, WriteOptions()); } diff --git a/include/grpcpp/impl/codegen/client_callback.h b/include/grpcpp/impl/codegen/client_callback.h index f164db19ec7..c20e8458106 100644 --- a/include/grpcpp/impl/codegen/client_callback.h +++ b/include/grpcpp/impl/codegen/client_callback.h @@ -73,7 +73,7 @@ class CallbackUnaryCallImpl { CallbackWithStatusTag(call.call(), on_completion, ops); // TODO(vjpai): Unify code with sync API as much as possible - Status s = ops->SendMessage(request); + Status s = ops->SendMessagePtr(request); if (!s.ok()) { tag->force_run(s); return; @@ -341,7 +341,7 @@ class ClientCallbackReaderWriterImpl start_corked_ = false; } // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok()); + GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg).ok()); if (options.is_last_message()) { options.set_buffer_hint(); @@ -524,7 +524,7 @@ class ClientCallbackReaderImpl : context_(context), call_(call), reactor_(reactor) { this->BindReactor(reactor); // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(start_ops_.SendMessage(*request).ok()); + GPR_CODEGEN_ASSERT(start_ops_.SendMessagePtr(request).ok()); start_ops_.ClientSendClose(); } @@ -650,7 +650,7 @@ class ClientCallbackWriterImpl start_corked_ = false; } // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok()); + GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg).ok()); if (options.is_last_message()) { options.set_buffer_hint(); diff --git a/include/grpcpp/impl/codegen/client_unary_call.h b/include/grpcpp/impl/codegen/client_unary_call.h index f34da234824..b9f8e1663f1 100644 --- a/include/grpcpp/impl/codegen/client_unary_call.h +++ b/include/grpcpp/impl/codegen/client_unary_call.h @@ -57,7 +57,7 @@ class BlockingUnaryCallImpl { CallOpRecvInitialMetadata, CallOpRecvMessage, CallOpClientSendClose, CallOpClientRecvStatus> ops; - status_ = ops.SendMessage(&request); + status_ = ops.SendMessagePtr(&request); if (!status_.ok()) { return; } diff --git a/include/grpcpp/impl/codegen/method_handler_impl.h b/include/grpcpp/impl/codegen/method_handler_impl.h index dd53f975f68..094286294c2 100644 --- a/include/grpcpp/impl/codegen/method_handler_impl.h +++ b/include/grpcpp/impl/codegen/method_handler_impl.h @@ -79,7 +79,7 @@ class RpcMethodHandler : public MethodHandler { ops.set_compression_level(param.server_context->compression_level()); } if (status.ok()) { - status = ops.SendMessage(rsp); + status = ops.SendMessagePtr(&rsp); } ops.ServerSendStatus(¶m.server_context->trailing_metadata_, status); param.call->PerformOps(&ops); @@ -139,7 +139,7 @@ class ClientStreamingHandler : public MethodHandler { } } if (status.ok()) { - status = ops.SendMessage(rsp); + status = ops.SendMessagePtr(&rsp); } ops.ServerSendStatus(¶m.server_context->trailing_metadata_, status); param.call->PerformOps(&ops); diff --git a/include/grpcpp/impl/codegen/server_callback.h b/include/grpcpp/impl/codegen/server_callback.h index b28b7fd9315..a0e59215dd6 100644 --- a/include/grpcpp/impl/codegen/server_callback.h +++ b/include/grpcpp/impl/codegen/server_callback.h @@ -320,7 +320,7 @@ class CallbackUnaryHandler : public MethodHandler { // The response is dropped if the status is not OK. if (s.ok()) { finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, - finish_ops_.SendMessage(resp_)); + finish_ops_.SendMessagePtr(&resp_)); } else { finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s); } @@ -449,7 +449,7 @@ class CallbackClientStreamingHandler : public MethodHandler { // The response is dropped if the status is not OK. if (s.ok()) { finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, - finish_ops_.SendMessage(resp_)); + finish_ops_.SendMessagePtr(&resp_)); } else { finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s); } @@ -642,7 +642,7 @@ class CallbackServerStreamingHandler : public MethodHandler { ctx_->sent_initial_metadata_ = true; } // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(write_ops_.SendMessage(resp, options).ok()); + GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(resp, options).ok()); call_.PerformOps(&write_ops_); } @@ -652,7 +652,7 @@ class CallbackServerStreamingHandler : public MethodHandler { // Don't send any message if the status is bad if (s.ok()) { // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(resp, options).ok()); + GPR_CODEGEN_ASSERT(finish_ops_.SendMessagePtr(resp, options).ok()); } Finish(std::move(s)); } @@ -804,7 +804,7 @@ class CallbackBidiHandler : public MethodHandler { ctx_->sent_initial_metadata_ = true; } // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(write_ops_.SendMessage(resp, options).ok()); + GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(resp, options).ok()); call_.PerformOps(&write_ops_); } @@ -813,7 +813,7 @@ class CallbackBidiHandler : public MethodHandler { // Don't send any message if the status is bad if (s.ok()) { // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(resp, options).ok()); + GPR_CODEGEN_ASSERT(finish_ops_.SendMessagePtr(resp, options).ok()); } Finish(std::move(s)); } diff --git a/include/grpcpp/impl/codegen/sync_stream.h b/include/grpcpp/impl/codegen/sync_stream.h index 4645ea3e2f5..d9edad42153 100644 --- a/include/grpcpp/impl/codegen/sync_stream.h +++ b/include/grpcpp/impl/codegen/sync_stream.h @@ -253,7 +253,7 @@ class ClientReader final : public ClientReaderInterface { ops.SendInitialMetadata(&context->send_initial_metadata_, context->initial_metadata_flags()); // TODO(ctiller): don't assert - GPR_CODEGEN_ASSERT(ops.SendMessage(&request).ok()); + GPR_CODEGEN_ASSERT(ops.SendMessagePtr(&request).ok()); ops.ClientSendClose(); call_.PerformOps(&ops); cq_.Pluck(&ops); @@ -331,7 +331,7 @@ class ClientWriter : public ClientWriterInterface { context_->initial_metadata_flags()); context_->set_initial_metadata_corked(false); } - if (!ops.SendMessage(&msg, options).ok()) { + if (!ops.SendMessagePtr(&msg, options).ok()) { return false; } @@ -502,7 +502,7 @@ class ClientReaderWriter final : public ClientReaderWriterInterface { context_->initial_metadata_flags()); context_->set_initial_metadata_corked(false); } - if (!ops.SendMessage(&msg, options).ok()) { + if (!ops.SendMessagePtr(&msg, options).ok()) { return false; } @@ -656,7 +656,7 @@ class ServerWriter final : public ServerWriterInterface { options.set_buffer_hint(); } - if (!ctx_->pending_ops_.SendMessage(&msg, options).ok()) { + if (!ctx_->pending_ops_.SendMessagePtr(&msg, options).ok()) { return false; } if (!ctx_->sent_initial_metadata_) { @@ -734,7 +734,7 @@ class ServerReaderWriterBody final { if (options.is_last_message()) { options.set_buffer_hint(); } - if (!ctx_->pending_ops_.SendMessage(&msg, options).ok()) { + if (!ctx_->pending_ops_.SendMessagePtr(&msg, options).ok()) { return false; } if (!ctx_->sent_initial_metadata_) { diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 3414ebe64e2..1ed1fb686dc 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -292,12 +292,12 @@ class LoggingInterceptor : public experimental::Interceptor { EXPECT_TRUE( SerializationTraits::Deserialize(&copied_buffer, &req) .ok()); - EXPECT_TRUE(req.message().find("Hello") == 0); + EXPECT_TRUE(req.message().find("Hello") == 0u); EXPECT_EQ( static_cast(methods->GetOriginalSendMessage()) ->message() .find("Hello"), - 0); + 0u); } if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { @@ -313,7 +313,7 @@ class LoggingInterceptor : public experimental::Interceptor { experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { EchoResponse* resp = static_cast(methods->GetRecvMessage()); - EXPECT_TRUE(resp->message().find("Hello") == 0); + EXPECT_TRUE(resp->message().find("Hello") == 0u); } if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::POST_RECV_STATUS)) { diff --git a/test/cpp/end2end/server_interceptors_end2end_test.cc b/test/cpp/end2end/server_interceptors_end2end_test.cc index 53d8c4dc960..28f51bb2fce 100644 --- a/test/cpp/end2end/server_interceptors_end2end_test.cc +++ b/test/cpp/end2end/server_interceptors_end2end_test.cc @@ -73,7 +73,7 @@ class LoggingInterceptor : public experimental::Interceptor { type == experimental::ServerRpcInfo::Type::BIDI_STREAMING)); } - virtual void Intercept(experimental::InterceptorBatchMethods* methods) { + void Intercept(experimental::InterceptorBatchMethods* methods) override { if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) { auto* map = methods->GetSendInitialMetadata(); @@ -142,6 +142,33 @@ class LoggingInterceptorFactory } }; +// Test if GetOriginalSendMessage works as expected +class GetOriginalSendMessageTester : public experimental::Interceptor { + public: + GetOriginalSendMessageTester(experimental::ServerRpcInfo* info) {} + + void Intercept(experimental::InterceptorBatchMethods* methods) override { + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + EXPECT_EQ( + static_cast(methods->GetOriginalSendMessage()) + ->message() + .find("Hello"), + 0u); + } + methods->Proceed(); + } +}; + +class GetOriginalSendMessageTesterFactory + : public experimental::ServerInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateServerInterceptor( + experimental::ServerRpcInfo* info) override { + return new GetOriginalSendMessageTester(info); + } +}; + void MakeBidiStreamingCall(const std::shared_ptr& channel) { auto stub = grpc::testing::EchoTestService::NewStub(channel); ClientContext ctx; @@ -176,6 +203,9 @@ class ServerInterceptorsEnd2endSyncUnaryTest : public ::testing::Test { creators.push_back( std::unique_ptr( new LoggingInterceptorFactory())); + creators.push_back( + std::unique_ptr( + new GetOriginalSendMessageTesterFactory())); // Add 20 dummy interceptor factories and null interceptor factories for (auto i = 0; i < 20; i++) { creators.push_back(std::unique_ptr( @@ -216,6 +246,9 @@ class ServerInterceptorsEnd2endSyncStreamingTest : public ::testing::Test { creators.push_back( std::unique_ptr( new LoggingInterceptorFactory())); + creators.push_back( + std::unique_ptr( + new GetOriginalSendMessageTesterFactory())); for (auto i = 0; i < 20; i++) { creators.push_back(std::unique_ptr( new DummyInterceptorFactory())); From 1f3829180c32c8c2ee1a3d546d6c2bcb3287e312 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 2 Jan 2019 15:52:42 -0800 Subject: [PATCH 292/375] Fix missing ConnectivityMonitor usage --- src/objective-c/GRPCClient/GRPCCall.m | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index b0412cddb09..83c6edc6e3f 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -841,6 +841,12 @@ const char *kCFStreamVarName = "grpc_cfstream"; [self sendHeaders]; [self invokeCall]; + + // Connectivity monitor is not required for CFStream + char *enableCFStream = getenv(kCFStreamVarName); + if (enableCFStream == nil || enableCFStream[0] != '1') { + [GRPCConnectivityMonitor registerObserver:self selector:@selector(connectivityChanged:)]; + } } - (void)startWithWriteable:(id)writeable { From 3af464f29cb7701a432518a71b0615c47ba58077 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Thu, 3 Jan 2019 08:19:51 -0800 Subject: [PATCH 293/375] return targets to library --- test/core/memory_usage/BUILD | 6 +++--- test/core/memory_usage/server.cc | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/test/core/memory_usage/BUILD b/test/core/memory_usage/BUILD index dd185e6577b..38b088c75c7 100644 --- a/test/core/memory_usage/BUILD +++ b/test/core/memory_usage/BUILD @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_test", "grpc_package") +load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package") grpc_package(name = "test/core/memory_usage") licenses(["notice"]) # Apache v2 -grpc_cc_binary( +grpc_cc_library( name = "memory_usage_client", testonly = 1, srcs = ["client.cc"], @@ -29,7 +29,7 @@ grpc_cc_binary( ], ) -grpc_cc_binary( +grpc_cc_library( name = "memory_usage_server", testonly = 1, srcs = ["server.cc"], diff --git a/test/core/memory_usage/server.cc b/test/core/memory_usage/server.cc index c79d661a422..7424797e6f5 100644 --- a/test/core/memory_usage/server.cc +++ b/test/core/memory_usage/server.cc @@ -295,7 +295,6 @@ int main(int argc, char** argv) { /* fallthrough */ // no break here since we want to continue to case // FLING_SERVER_SEND_STATUS_SNAPSHOT to destroy the snapshot call - [[fallthrough]]; case FLING_SERVER_SEND_STATUS_SNAPSHOT: grpc_byte_buffer_destroy(payload_buffer); grpc_byte_buffer_destroy(terminal_buffer); From 67f523ce13a3d6c8adf02530173679cf1dc0ddd6 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Fri, 28 Dec 2018 07:55:36 -0800 Subject: [PATCH 294/375] Add support for ruby 2.6.0 binary package builds, drop 2.1 and 2.0 binary package builds; pin bundler to 1.17.3 where necessary --- Rakefile | 6 +-- templates/tools/dockerfile/ruby_deps.include | 14 +++---- third_party/rake-compiler-dock/Dockerfile | 3 +- tools/distrib/build_ruby_environment_macos.sh | 2 +- .../distribtest/ruby_centos6_x64/Dockerfile | 15 +++++-- .../distribtest/ruby_centos7_x64/Dockerfile | 18 +++++++- .../distribtest/ruby_fedora20_x64/Dockerfile | 21 +++++++++- .../distribtest/ruby_fedora21_x64/Dockerfile | 19 ++++++++- .../ruby_jessie_x64_ruby_2_2/Dockerfile | 40 ++++++++++++++++++ .../ruby_jessie_x64_ruby_2_3/Dockerfile | 41 +++++++++++++++++++ .../ruby_jessie_x64_ruby_2_4/Dockerfile | 40 ++++++++++++++++++ .../ruby_jessie_x64_ruby_2_5/Dockerfile | 40 ++++++++++++++++++ .../Dockerfile | 14 +++---- .../grpc_artifact_linux_x64/Dockerfile | 2 +- .../grpc_artifact_linux_x86/Dockerfile | 2 +- .../interoptest/grpc_interop_ruby/Dockerfile | 14 +++---- .../grpc_interop_ruby/build_interop.sh | 2 +- .../test/ruby_jessie_x64/Dockerfile | 14 +++---- .../helper_scripts/prepare_build_macos_rc | 2 +- .../artifacts/distribtest_targets.py | 8 ++-- 20 files changed, 267 insertions(+), 50 deletions(-) create mode 100644 tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_2/Dockerfile create mode 100644 tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_3/Dockerfile create mode 100644 tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_4/Dockerfile create mode 100644 tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_5/Dockerfile rename tools/dockerfile/distribtest/{ruby_jessie_x64_ruby_2_0_0 => ruby_jessie_x64_ruby_2_6}/Dockerfile (73%) diff --git a/Rakefile b/Rakefile index 0068a3b8e4f..d604f7935b1 100755 --- a/Rakefile +++ b/Rakefile @@ -105,7 +105,7 @@ task 'dlls' do env_comp = "CC=#{opt[:cross]}-gcc " env_comp += "CXX=#{opt[:cross]}-g++ " env_comp += "LD=#{opt[:cross]}-gcc " - docker_for_windows "gem update --system --no-ri --no-doc && #{env} #{env_comp} make -j #{out} && #{opt[:cross]}-strip -x -S #{out} && cp #{out} #{opt[:out]}" + docker_for_windows "gem update --system --no-document && #{env} #{env_comp} make -j #{out} && #{opt[:cross]}-strip -x -S #{out} && cp #{out} #{opt[:out]}" end end @@ -124,10 +124,10 @@ task 'gem:native' do "invoked on macos with ruby #{RUBY_VERSION}. The ruby macos artifact " \ "build should be running on ruby 2.5." end - system "rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}" + system "rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.0:2.4.0:2.3.0:2.2.2 V=#{verbose} GRPC_CONFIG=#{grpc_config}" else Rake::Task['dlls'].execute - docker_for_windows "gem update --system --no-ri --no-doc && bundle && rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}" + docker_for_windows "gem update --system --no-document && bundle && rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.0:2.4.0:2.3.0:2.2.2 V=#{verbose} GRPC_CONFIG=#{grpc_config}" end end diff --git a/templates/tools/dockerfile/ruby_deps.include b/templates/tools/dockerfile/ruby_deps.include index a8ee3ec7dc6..c2d330988c6 100644 --- a/templates/tools/dockerfile/ruby_deps.include +++ b/templates/tools/dockerfile/ruby_deps.include @@ -2,13 +2,13 @@ # Ruby dependencies # Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB RUN \curl -sSL https://get.rvm.io | bash -s stable -# Install Ruby 2.1 -RUN /bin/bash -l -c "rvm install ruby-2.1" -RUN /bin/bash -l -c "rvm use --default ruby-2.1" -RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" +# Install Ruby 2.5 +RUN /bin/bash -l -c "rvm install ruby-2.5" +RUN /bin/bash -l -c "rvm use --default ruby-2.5" +RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc" RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" -RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc" -RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc" +RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.5' >> ~/.bashrc" +RUN /bin/bash -l -c "gem install bundler --no-document" diff --git a/third_party/rake-compiler-dock/Dockerfile b/third_party/rake-compiler-dock/Dockerfile index 06c721c39ba..44eddc82e80 100644 --- a/third_party/rake-compiler-dock/Dockerfile +++ b/third_party/rake-compiler-dock/Dockerfile @@ -1,8 +1,7 @@ -FROM larskanis/rake-compiler-dock:0.6.2 +FROM larskanis/rake-compiler-dock-mri:0.7.0 RUN find / -name rbconfig.rb | while read f ; do sed -i 's/0x0501/0x0600/' $f ; done RUN find / -name win32.h | while read f ; do sed -i 's/gettimeofday/rb_gettimeofday/' $f ; done -RUN sed -i 's/defined.__MINGW64__.$/1/' /usr/local/rake-compiler/ruby/i686-w64-mingw32/ruby-2.0.0-p645/include/ruby-2.0.0/ruby/win32.h RUN find / -name libwinpthread.dll.a | xargs rm RUN find / -name libwinpthread-1.dll | xargs rm RUN find / -name *msvcrt-ruby*.dll.a | while read f ; do n=`echo $f | sed s/.dll//` ; mv $f $n ; done diff --git a/tools/distrib/build_ruby_environment_macos.sh b/tools/distrib/build_ruby_environment_macos.sh index 9e3e3b46f80..c2c0dcde6bd 100644 --- a/tools/distrib/build_ruby_environment_macos.sh +++ b/tools/distrib/build_ruby_environment_macos.sh @@ -49,7 +49,7 @@ EOF MAKE="make -j8" -for v in 2.5.0 2.4.0 2.3.0 2.2.2 2.1.6 2.0.0-p645 ; do +for v in 2.6.0 2.5.0 2.4.0 2.3.0 2.2.2 ; do ccache -c rake -f "$CROSS_RUBY" cross-ruby VERSION="$v" HOST=x86_64-darwin11 MAKE="$MAKE" done diff --git a/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile index c3d6e03f6a1..b53ffc22d4f 100644 --- a/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile +++ b/tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile @@ -19,10 +19,19 @@ RUN yum install -y curl RUN yum install -y tar which # Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN curl -sSL https://get.rvm.io | bash -s stable + +# Install Ruby 2.2 # Running the installation twice to work around docker issue when using overlay. # https://github.com/docker/docker/issues/10180 -RUN (curl -sSL https://get.rvm.io | bash -s stable --ruby) || (curl -sSL https://get.rvm.io | bash -s stable --ruby) +RUN (/bin/bash -l -c "rvm install ruby-2.2.10") || (/bin/bash -l -c "rvm install ruby-2.2.10") +RUN /bin/bash -l -c "rvm use --default ruby-2.2.10" +RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc" +RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" +RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc" +RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document" + +RUN mkdir /var/local/jenkins RUN /bin/bash -l -c "echo '. /etc/profile.d/rvm.sh' >> ~/.bashrc" -RUN /bin/bash -l -c "gem install --update bundler" diff --git a/tools/dockerfile/distribtest/ruby_centos7_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_centos7_x64/Dockerfile index 73207e4210d..72235bfba7f 100644 --- a/tools/dockerfile/distribtest/ruby_centos7_x64/Dockerfile +++ b/tools/dockerfile/distribtest/ruby_centos7_x64/Dockerfile @@ -14,6 +14,20 @@ FROM centos:7 -RUN yum install -y ruby +RUN yum update && yum install -y curl tar which -RUN gem install bundler +# Install rvm +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN curl -sSL https://get.rvm.io | bash -s stable + +# Install Ruby 2.2 +RUN /bin/bash -l -c "rvm install ruby-2.2.10" +RUN /bin/bash -l -c "rvm use --default ruby-2.2.10" +RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc" +RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" +RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc" +RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document" + +RUN mkdir /var/local/jenkins + +RUN /bin/bash -l -c "echo '. /etc/profile.d/rvm.sh' >> ~/.bashrc" diff --git a/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile index 200c5c28033..3d688a889f0 100644 --- a/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile +++ b/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile @@ -14,6 +14,23 @@ FROM fedora:20 -RUN yum clean all && yum update -y && yum install -y ruby findutils +# distro-sync and install openssl, per https://github.com/fedora-cloud/docker-brew-fedora/issues/19 +RUN yum clean all && yum update -y && yum distro-sync -y && yum install -y openssl gnupg which findutils -RUN gem install bundler +# Install rvm +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN curl -sSL https://get.rvm.io | bash -s stable + +# Install Ruby 2.2 +# Running the installation twice to work around docker issue when using overlay. +# https://github.com/docker/docker/issues/10180 +RUN (/bin/bash -l -c "rvm install ruby-2.2.10") || (/bin/bash -l -c "rvm install ruby-2.2.10") +RUN /bin/bash -l -c "rvm use --default ruby-2.2.10" +RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc" +RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" +RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc" +RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document" + +RUN mkdir /var/local/jenkins + +RUN /bin/bash -l -c "echo '. /etc/profile.d/rvm.sh' >> ~/.bashrc" diff --git a/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile index e1177fd99af..8044adf15dc 100644 --- a/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile +++ b/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile @@ -19,6 +19,21 @@ FROM fedora:21 # https://github.com/docker/docker/issues/10180 RUN yum install -y yum-plugin-ovl -RUN yum clean all && yum update -y && yum install -y ruby findutils +# distro-sync and install openssl, per https://github.com/fedora-cloud/docker-brew-fedora/issues/19 +RUN yum clean all && yum update -y && yum distro-sync -y && yum install -y openssl gnupg which findutils tar -RUN gem install bundler +# Install rvm +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN curl -sSL https://get.rvm.io | bash -s stable + +# Install Ruby 2.2 +RUN /bin/bash -l -c "rvm install ruby-2.2.10" +RUN /bin/bash -l -c "rvm use --default ruby-2.2.10" +RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc" +RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" +RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc" +RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document" + +RUN mkdir /var/local/jenkins + +RUN /bin/bash -l -c "echo '. /etc/profile.d/rvm.sh' >> ~/.bashrc" diff --git a/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_2/Dockerfile b/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_2/Dockerfile new file mode 100644 index 00000000000..337fc3b5d8e --- /dev/null +++ b/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_2/Dockerfile @@ -0,0 +1,40 @@ +# Copyright 2015 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM debian:jessie + +# Install Git and basic packages. +RUN apt-get update && apt-get install -y \ + curl \ + gcc && apt-get clean + +#================== +# Ruby dependencies + +# Install rvm +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN \curl -sSL https://get.rvm.io | bash -s stable + +# Install Ruby 2.2 +RUN /bin/bash -l -c "rvm install ruby-2.2.10" +RUN /bin/bash -l -c "rvm use --default ruby-2.2.10" +RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc" +RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" +RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc" +RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document" + +RUN mkdir /var/local/jenkins + +# Define the default command. +CMD ["bash"] diff --git a/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_3/Dockerfile b/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_3/Dockerfile new file mode 100644 index 00000000000..9deff0661b7 --- /dev/null +++ b/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_3/Dockerfile @@ -0,0 +1,41 @@ +# Copyright 2015 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM debian:jessie + +# Install Git and basic packages. +RUN apt-get update && apt-get install -y \ + curl \ + gcc && apt-get clean + +#================== +# Ruby dependencies + +# Install rvm +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN \curl -sSL https://get.rvm.io | bash -s stable + +# Install Ruby 2.3 +RUN /bin/bash -l -c "rvm install ruby-2.3.8" +RUN /bin/bash -l -c "rvm use --default ruby-2.3.8" +RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc" +RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" +RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.3.8' >> ~/.bashrc" +RUN /bin/bash -l -c "gem update --system" +RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document" + +RUN mkdir /var/local/jenkins + +# Define the default command. +CMD ["bash"] diff --git a/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_4/Dockerfile b/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_4/Dockerfile new file mode 100644 index 00000000000..55b1b1e731d --- /dev/null +++ b/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_4/Dockerfile @@ -0,0 +1,40 @@ +# Copyright 2015 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM debian:jessie + +# Install Git and basic packages. +RUN apt-get update && apt-get install -y \ + curl \ + gcc && apt-get clean + +#================== +# Ruby dependencies + +# Install rvm +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN \curl -sSL https://get.rvm.io | bash -s stable + +# Install Ruby 2.4 +RUN /bin/bash -l -c "rvm install ruby-2.4.5" +RUN /bin/bash -l -c "rvm use --default ruby-2.4.5" +RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc" +RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" +RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.4.5' >> ~/.bashrc" +RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document" + +RUN mkdir /var/local/jenkins + +# Define the default command. +CMD ["bash"] diff --git a/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_5/Dockerfile b/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_5/Dockerfile new file mode 100644 index 00000000000..bed4b3a93ef --- /dev/null +++ b/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_5/Dockerfile @@ -0,0 +1,40 @@ +# Copyright 2015 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM debian:jessie + +# Install Git and basic packages. +RUN apt-get update && apt-get install -y \ + curl \ + gcc && apt-get clean + +#================== +# Ruby dependencies + +# Install rvm +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN \curl -sSL https://get.rvm.io | bash -s stable + +# Install Ruby 2.5 +RUN /bin/bash -l -c "rvm install ruby-2.5.3" +RUN /bin/bash -l -c "rvm use --default ruby-2.5.3" +RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc" +RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" +RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.5.3' >> ~/.bashrc" +RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document" + +RUN mkdir /var/local/jenkins + +# Define the default command. +CMD ["bash"] diff --git a/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_0_0/Dockerfile b/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_6/Dockerfile similarity index 73% rename from tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_0_0/Dockerfile rename to tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_6/Dockerfile index ff43c92c9e5..af1839eba93 100644 --- a/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_0_0/Dockerfile +++ b/tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_6/Dockerfile @@ -23,16 +23,16 @@ RUN apt-get update && apt-get install -y \ # Ruby dependencies # Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB RUN \curl -sSL https://get.rvm.io | bash -s stable -# Install Ruby 2.1 -RUN /bin/bash -l -c "rvm install ruby-2.0" -RUN /bin/bash -l -c "rvm use --default ruby-2.0" -RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" +# Install Ruby 2.6 +RUN /bin/bash -l -c "rvm install ruby-2.6.0" +RUN /bin/bash -l -c "rvm use --default ruby-2.6.0" +RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc" RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" -RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.0' >> ~/.bashrc" -RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc" +RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.6.0' >> ~/.bashrc" +RUN /bin/bash -l -c "gem install bundler --no-document" RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile index 7ec061ebe58..e3e549f9874 100644 --- a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile @@ -58,7 +58,7 @@ RUN /bin/bash -l -c "rvm use --default ruby-2.1" RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc" -RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc" +RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-ri --no-rdoc" ################## diff --git a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile index f81d8e5ba02..ec4fcbae368 100644 --- a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile @@ -58,7 +58,7 @@ RUN /bin/bash -l -c "rvm use --default ruby-2.1" RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc" -RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc" +RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-ri --no-rdoc" ################## # C# dependencies (needed to build grpc_csharp_ext) diff --git a/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile index 97c146bb53a..1f6f03edd89 100644 --- a/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile @@ -68,16 +68,16 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t # Ruby dependencies # Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB RUN \curl -sSL https://get.rvm.io | bash -s stable -# Install Ruby 2.1 -RUN /bin/bash -l -c "rvm install ruby-2.1" -RUN /bin/bash -l -c "rvm use --default ruby-2.1" -RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" +# Install Ruby 2.5 +RUN /bin/bash -l -c "rvm install ruby-2.5" +RUN /bin/bash -l -c "rvm use --default ruby-2.5" +RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc" RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" -RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc" -RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc" +RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.5' >> ~/.bashrc" +RUN /bin/bash -l -c "gem install bundler --no-document" RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh index b6b122ef0fd..67f66090ae9 100755 --- a/tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh +++ b/tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh @@ -27,7 +27,7 @@ ${name}') cp -r /var/local/jenkins/service_account $HOME || true cd /var/local/git/grpc -rvm --default use ruby-2.1 +rvm --default use ruby-2.5 # build Ruby interop client and server (cd src/ruby && gem update bundler && bundle && rake compile) diff --git a/tools/dockerfile/test/ruby_jessie_x64/Dockerfile b/tools/dockerfile/test/ruby_jessie_x64/Dockerfile index 321b501de21..cf6a5b254f1 100644 --- a/tools/dockerfile/test/ruby_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/ruby_jessie_x64/Dockerfile @@ -72,16 +72,16 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t # Ruby dependencies # Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB RUN \curl -sSL https://get.rvm.io | bash -s stable -# Install Ruby 2.1 -RUN /bin/bash -l -c "rvm install ruby-2.1" -RUN /bin/bash -l -c "rvm use --default ruby-2.1" -RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" +# Install Ruby 2.5 +RUN /bin/bash -l -c "rvm install ruby-2.5" +RUN /bin/bash -l -c "rvm use --default ruby-2.5" +RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc" RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" -RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc" -RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc" +RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.5' >> ~/.bashrc" +RUN /bin/bash -l -c "gem install bundler --no-document" RUN mkdir /var/local/jenkins diff --git a/tools/internal_ci/helper_scripts/prepare_build_macos_rc b/tools/internal_ci/helper_scripts/prepare_build_macos_rc index ce054ac2594..632db5ae145 100644 --- a/tools/internal_ci/helper_scripts/prepare_build_macos_rc +++ b/tools/internal_ci/helper_scripts/prepare_build_macos_rc @@ -42,7 +42,7 @@ source $HOME/.rvm/scripts/rvm set -e # rvm commands are very verbose time rvm install 2.5.0 rvm use 2.5.0 --default -time gem install bundler --no-ri --no-doc +time gem install bundler -v 1.17.3 --no-ri --no-doc time gem install cocoapods --version 1.3.1 --no-ri --no-doc time gem install rake-compiler --no-ri --no-doc rvm osx-ssl-certs status all diff --git a/tools/run_tests/artifacts/distribtest_targets.py b/tools/run_tests/artifacts/distribtest_targets.py index e02f4bffcd4..fd68a4dc747 100644 --- a/tools/run_tests/artifacts/distribtest_targets.py +++ b/tools/run_tests/artifacts/distribtest_targets.py @@ -336,9 +336,11 @@ def targets(): PythonDistribTest('linux', 'x64', 'ubuntu1404', source=True), PythonDistribTest('linux', 'x64', 'ubuntu1604', source=True), RubyDistribTest('linux', 'x64', 'wheezy'), - RubyDistribTest('linux', 'x64', 'jessie'), - RubyDistribTest('linux', 'x86', 'jessie'), - RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_0_0'), + RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_2'), + RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_3'), + RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_4'), + RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_5'), + RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_6'), RubyDistribTest('linux', 'x64', 'centos6'), RubyDistribTest('linux', 'x64', 'centos7'), RubyDistribTest('linux', 'x64', 'fedora20'), From 50c60f03ba84b4e1b1d31819a295ef4e1076907b Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 3 Jan 2019 12:21:19 -0800 Subject: [PATCH 295/375] Rename GetSendMessage to GetSerializedSendMessage and GetOriginalSendMessage to GetSendMessage --- include/grpcpp/impl/codegen/interceptor.h | 4 +-- .../grpcpp/impl/codegen/interceptor_common.h | 8 +++--- .../client_interceptors_end2end_test.cc | 15 ++++++----- .../server_interceptors_end2end_test.cc | 25 +++++++++---------- 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/include/grpcpp/impl/codegen/interceptor.h b/include/grpcpp/impl/codegen/interceptor.h index a83d285d130..5a9a3a44e6e 100644 --- a/include/grpcpp/impl/codegen/interceptor.h +++ b/include/grpcpp/impl/codegen/interceptor.h @@ -109,13 +109,13 @@ class InterceptorBatchMethods { /// Returns a modifable ByteBuffer holding the serialized form of the message /// that is going to be sent. Valid for PRE_SEND_MESSAGE interceptions. /// A return value of nullptr indicates that this ByteBuffer is not valid. - virtual ByteBuffer* GetSendMessage() = 0; + virtual ByteBuffer* GetSerializedSendMessage() = 0; /// Returns a non-modifiable pointer to the original non-serialized form of /// the message. Valid for PRE_SEND_MESSAGE interceptions. A return value of /// nullptr indicates that this field is not valid. Also note that this is /// only supported for sync and callback APIs at the present moment. - virtual const void* GetOriginalSendMessage() = 0; + virtual const void* GetSendMessage() = 0; /// Returns a modifiable multimap of the initial metadata to be sent. Valid /// for PRE_SEND_INITIAL_METADATA interceptions. A value of nullptr indicates diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index bf936368d4c..4b7eaefee1b 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -79,9 +79,9 @@ class InterceptorBatchMethodsImpl hooks_[static_cast(type)] = true; } - ByteBuffer* GetSendMessage() override { return send_message_; } + ByteBuffer* GetSerializedSendMessage() override { return send_message_; } - const void* GetOriginalSendMessage() override { return orig_send_message_; } + const void* GetSendMessage() override { return orig_send_message_; } std::multimap* GetSendInitialMetadata() override { return send_initial_metadata_; @@ -385,14 +385,14 @@ class CancelInterceptorBatchMethods "Cancel notification"); } - ByteBuffer* GetSendMessage() override { + ByteBuffer* GetSerializedSendMessage() override { GPR_CODEGEN_ASSERT(false && "It is illegal to call GetSendMessage on a method which " "has a Cancel notification"); return nullptr; } - const void* GetOriginalSendMessage() override { + const void* GetSendMessage() override { GPR_CODEGEN_ASSERT( false && "It is illegal to call GetOriginalSendMessage on a method which " diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 1ed1fb686dc..3db709e956e 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -68,7 +68,7 @@ class HijackingInterceptor : public experimental::Interceptor { if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { EchoRequest req; - auto* buffer = methods->GetSendMessage(); + auto* buffer = methods->GetSerializedSendMessage(); auto copied_buffer = *buffer; EXPECT_TRUE( SerializationTraits::Deserialize(&copied_buffer, &req) @@ -173,7 +173,7 @@ class HijackingInterceptorMakesAnotherCall : public experimental::Interceptor { if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { EchoRequest req; - auto* buffer = methods->GetSendMessage(); + auto* buffer = methods->GetSerializedSendMessage(); auto copied_buffer = *buffer; EXPECT_TRUE( SerializationTraits::Deserialize(&copied_buffer, &req) @@ -287,17 +287,16 @@ class LoggingInterceptor : public experimental::Interceptor { if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { EchoRequest req; - auto* buffer = methods->GetSendMessage(); + auto* buffer = methods->GetSerializedSendMessage(); auto copied_buffer = *buffer; EXPECT_TRUE( SerializationTraits::Deserialize(&copied_buffer, &req) .ok()); EXPECT_TRUE(req.message().find("Hello") == 0u); - EXPECT_EQ( - static_cast(methods->GetOriginalSendMessage()) - ->message() - .find("Hello"), - 0u); + EXPECT_EQ(static_cast(methods->GetSendMessage()) + ->message() + .find("Hello"), + 0u); } if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { diff --git a/test/cpp/end2end/server_interceptors_end2end_test.cc b/test/cpp/end2end/server_interceptors_end2end_test.cc index 28f51bb2fce..09e855b0d01 100644 --- a/test/cpp/end2end/server_interceptors_end2end_test.cc +++ b/test/cpp/end2end/server_interceptors_end2end_test.cc @@ -83,7 +83,7 @@ class LoggingInterceptor : public experimental::Interceptor { if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { EchoRequest req; - auto* buffer = methods->GetSendMessage(); + auto* buffer = methods->GetSerializedSendMessage(); auto copied_buffer = *buffer; EXPECT_TRUE( SerializationTraits::Deserialize(&copied_buffer, &req) @@ -142,30 +142,29 @@ class LoggingInterceptorFactory } }; -// Test if GetOriginalSendMessage works as expected -class GetOriginalSendMessageTester : public experimental::Interceptor { +// Test if GetSendMessage works as expected +class GetSendMessageTester : public experimental::Interceptor { public: - GetOriginalSendMessageTester(experimental::ServerRpcInfo* info) {} + GetSendMessageTester(experimental::ServerRpcInfo* info) {} void Intercept(experimental::InterceptorBatchMethods* methods) override { if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { - EXPECT_EQ( - static_cast(methods->GetOriginalSendMessage()) - ->message() - .find("Hello"), - 0u); + EXPECT_EQ(static_cast(methods->GetSendMessage()) + ->message() + .find("Hello"), + 0u); } methods->Proceed(); } }; -class GetOriginalSendMessageTesterFactory +class GetSendMessageTesterFactory : public experimental::ServerInterceptorFactoryInterface { public: virtual experimental::Interceptor* CreateServerInterceptor( experimental::ServerRpcInfo* info) override { - return new GetOriginalSendMessageTester(info); + return new GetSendMessageTester(info); } }; @@ -205,7 +204,7 @@ class ServerInterceptorsEnd2endSyncUnaryTest : public ::testing::Test { new LoggingInterceptorFactory())); creators.push_back( std::unique_ptr( - new GetOriginalSendMessageTesterFactory())); + new GetSendMessageTesterFactory())); // Add 20 dummy interceptor factories and null interceptor factories for (auto i = 0; i < 20; i++) { creators.push_back(std::unique_ptr( @@ -248,7 +247,7 @@ class ServerInterceptorsEnd2endSyncStreamingTest : public ::testing::Test { new LoggingInterceptorFactory())); creators.push_back( std::unique_ptr( - new GetOriginalSendMessageTesterFactory())); + new GetSendMessageTesterFactory())); for (auto i = 0; i < 20; i++) { creators.push_back(std::unique_ptr( new DummyInterceptorFactory())); From e894d78c35f4836567c75054fdeb044a3397385c Mon Sep 17 00:00:00 2001 From: Alex Polcyn Date: Thu, 3 Jan 2019 18:18:48 +0000 Subject: [PATCH 296/375] Fix artifact dockerfiles rvm installation; keep bundler pinned --- tools/dockerfile/grpc_artifact_linux_x64/Dockerfile | 2 +- tools/dockerfile/grpc_artifact_linux_x86/Dockerfile | 2 +- tools/run_tests/artifacts/build_artifact_ruby.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile index e3e549f9874..f247cc9ca54 100644 --- a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile @@ -49,7 +49,7 @@ RUN apt-get update && apt-get install -y \ # Ruby dependencies # Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB RUN \curl -sSL https://get.rvm.io | bash -s stable # Install Ruby 2.1 diff --git a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile index ec4fcbae368..e403f75b594 100644 --- a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile @@ -49,7 +49,7 @@ RUN apt-get update && apt-get install -y \ # Ruby dependencies # Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 +RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB RUN \curl -sSL https://get.rvm.io | bash -s stable # Install Ruby 2.1 diff --git a/tools/run_tests/artifacts/build_artifact_ruby.sh b/tools/run_tests/artifacts/build_artifact_ruby.sh index c910374376d..09423ce5391 100755 --- a/tools/run_tests/artifacts/build_artifact_ruby.sh +++ b/tools/run_tests/artifacts/build_artifact_ruby.sh @@ -38,7 +38,7 @@ fi set +ex rvm use default -gem install bundler --update +gem install bundler -v 1.17.3 tools/run_tests/helper_scripts/bundle_install_wrapper.sh From cab4774d95b9fa53f3cfe3bf58fb07dbc8f7650f Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Fri, 28 Dec 2018 15:54:43 -0800 Subject: [PATCH 297/375] Add a way to avoid if_nametoindex function for non-posix linux platforms that don't support it --- include/grpc/impl/codegen/port_platform.h | 4 ++++ src/core/lib/iomgr/grpc_if_nametoindex_posix.cc | 5 +++-- src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc | 5 +++-- src/core/lib/iomgr/port.h | 1 + 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index 031c0c36aef..bd81635f58c 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -465,6 +465,10 @@ typedef unsigned __int64 uint64_t; #define GRPC_ARES 1 #endif +#ifndef GRPC_IF_NAMETOINDEX +#define GRPC_IF_NAMETOINDEX 1 +#endif + #ifndef GRPC_MUST_USE_RESULT #if defined(__GNUC__) && !defined(__MINGW32__) #define GRPC_MUST_USE_RESULT __attribute__((warn_unused_result)) diff --git a/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc b/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc index 8f9137455d2..f1ba20dcec7 100644 --- a/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc +++ b/src/core/lib/iomgr/grpc_if_nametoindex_posix.cc @@ -20,7 +20,7 @@ #include "src/core/lib/iomgr/port.h" -#ifdef GRPC_POSIX_SOCKET +#if GRPC_IF_NAMETOINDEX == 1 && defined(GRPC_POSIX_SOCKET_IF_NAMETOINDEX) #include "src/core/lib/iomgr/grpc_if_nametoindex.h" @@ -38,4 +38,5 @@ uint32_t grpc_if_nametoindex(char* name) { return out; } -#endif /* GRPC_POSIX_SOCKET */ +#endif /* GRPC_IF_NAMETOINDEX == 1 && \ + defined(GRPC_POSIX_SOCKET_IF_NAMETOINDEX) */ diff --git a/src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc b/src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc index 1faaaa6e420..08644cccf3e 100644 --- a/src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc +++ b/src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc @@ -20,7 +20,7 @@ #include "src/core/lib/iomgr/port.h" -#ifndef GRPC_POSIX_SOCKET +#if GRPC_IF_NAMETOINDEX == 0 || !defined(GRPC_POSIX_SOCKET_IF_NAMETOINDEX) #include "src/core/lib/iomgr/grpc_if_nametoindex.h" @@ -34,4 +34,5 @@ uint32_t grpc_if_nametoindex(char* name) { return 0; } -#endif /* GRPC_POSIX_SOCKET */ +#endif /* GRPC_IF_NAMETOINDEX == 0 || \ + !defined(GRPC_POSIX_SOCKET_IF_NAMETOINDEX) */ diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index c8046b21dcd..7b6ca1bc0e1 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -184,6 +184,7 @@ #define GRPC_POSIX_SOCKET_EV_EPOLLEX 1 #define GRPC_POSIX_SOCKET_EV_POLL 1 #define GRPC_POSIX_SOCKET_EV_EPOLL1 1 +#define GRPC_POSIX_SOCKET_IF_NAMETOINDEX 1 #define GRPC_POSIX_SOCKET_IOMGR 1 #define GRPC_POSIX_SOCKET_RESOLVE_ADDRESS 1 #define GRPC_POSIX_SOCKET_SOCKADDR 1 From ec2d03d409ebb65daa252e6c280e3bec4fe96b69 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Thu, 3 Jan 2019 14:28:38 -0800 Subject: [PATCH 298/375] restore the newline --- tools/doxygen/Doxyfile.c++ | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 8c890f2ba3f..1ab3a394b96 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -2623,3 +2623,4 @@ GENERATE_LEGEND = YES # This tag requires that the tag HAVE_DOT is set to YES. DOT_CLEANUP = YES + From d99f2f03074ef978b593ec0fdbe6295cd0235500 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Thu, 3 Jan 2019 15:33:33 -0800 Subject: [PATCH 299/375] Bump version to v1.19.x --- BUILD | 4 ++-- build.yaml | 4 ++-- doc/g_stands_for.md | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/BUILD b/BUILD index e3c765198b2..cd23d9c91fa 100644 --- a/BUILD +++ b/BUILD @@ -64,11 +64,11 @@ config_setting( ) # This should be updated along with build.yaml -g_stands_for = "goose" +g_stands_for = "gold" core_version = "7.0.0-dev" -version = "1.18.0-dev" +version = "1.19.0-dev" GPR_PUBLIC_HDRS = [ "include/grpc/support/alloc.h", diff --git a/build.yaml b/build.yaml index a41decd84f7..4ccc452ed5b 100644 --- a/build.yaml +++ b/build.yaml @@ -13,8 +13,8 @@ settings: '#09': Per-language overrides are possible with (eg) ruby_version tag here '#10': See the expand_version.py for all the quirks here core_version: 7.0.0-dev - g_stands_for: goose - version: 1.18.0-dev + g_stands_for: gold + version: 1.19.0-dev filegroups: - name: alts_proto headers: diff --git a/doc/g_stands_for.md b/doc/g_stands_for.md index 1e49b4d3f17..7bc8a003b5d 100644 --- a/doc/g_stands_for.md +++ b/doc/g_stands_for.md @@ -17,4 +17,5 @@ - 1.15 'g' stands for ['glider'](https://github.com/grpc/grpc/tree/v1.15.x) - 1.16 'g' stands for ['gao'](https://github.com/grpc/grpc/tree/v1.16.x) - 1.17 'g' stands for ['gizmo'](https://github.com/grpc/grpc/tree/v1.17.x) -- 1.18 'g' stands for ['goose'](https://github.com/grpc/grpc/tree/master) +- 1.18 'g' stands for ['goose'](https://github.com/grpc/grpc/tree/v1.18.x) +- 1.19 'g' stands for ['gold'](https://github.com/grpc/grpc/tree/master) From 94d55876438a8178aae85ded57e3d04ff3f298c5 Mon Sep 17 00:00:00 2001 From: Sanjay Pujare Date: Thu, 3 Jan 2019 15:35:20 -0800 Subject: [PATCH 300/375] Regenerate projects --- CMakeLists.txt | 2 +- Makefile | 4 ++-- gRPC-C++.podspec | 4 ++-- gRPC-Core.podspec | 2 +- gRPC-ProtoRPC.podspec | 2 +- gRPC-RxLibrary.podspec | 2 +- gRPC.podspec | 2 +- package.xml | 4 ++-- src/core/lib/surface/version.cc | 2 +- src/cpp/common/version_cc.cc | 2 +- src/csharp/Grpc.Core/Version.csproj.include | 2 +- src/csharp/Grpc.Core/VersionInfo.cs | 4 ++-- src/csharp/build_packages_dotnetcli.bat | 2 +- src/csharp/build_unitypackage.bat | 2 +- src/objective-c/!ProtoCompiler-gRPCPlugin.podspec | 2 +- src/objective-c/GRPCClient/private/version.h | 2 +- src/objective-c/tests/version.h | 2 +- src/php/composer.json | 2 +- src/php/ext/grpc/version.h | 2 +- src/python/grpcio/grpc/_grpcio_metadata.py | 2 +- src/python/grpcio/grpc_version.py | 2 +- src/python/grpcio_channelz/grpc_version.py | 2 +- src/python/grpcio_health_checking/grpc_version.py | 2 +- src/python/grpcio_reflection/grpc_version.py | 2 +- src/python/grpcio_status/grpc_version.py | 2 +- src/python/grpcio_testing/grpc_version.py | 2 +- src/python/grpcio_tests/grpc_version.py | 2 +- src/ruby/lib/grpc/version.rb | 2 +- src/ruby/tools/version.rb | 2 +- tools/distrib/python/grpcio_tools/grpc_version.py | 2 +- tools/doxygen/Doxyfile.c++ | 2 +- tools/doxygen/Doxyfile.c++.internal | 2 +- 32 files changed, 36 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 48d3d11d238..7e4dddab5ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ cmake_minimum_required(VERSION 2.8) set(PACKAGE_NAME "grpc") -set(PACKAGE_VERSION "1.18.0-dev") +set(PACKAGE_VERSION "1.19.0-dev") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/") diff --git a/Makefile b/Makefile index b8a1c921862..ce56482a0df 100644 --- a/Makefile +++ b/Makefile @@ -438,8 +438,8 @@ Q = @ endif CORE_VERSION = 7.0.0-dev -CPP_VERSION = 1.18.0-dev -CSHARP_VERSION = 1.18.0-dev +CPP_VERSION = 1.19.0-dev +CSHARP_VERSION = 1.19.0-dev CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 29a79dd47ab..e830958f799 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -23,7 +23,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-C++' # TODO (mxyan): use version that match gRPC version when pod is stabilized - # version = '1.18.0-dev' + # version = '1.19.0-dev' version = '0.0.6-dev' s.version = version s.summary = 'gRPC C++ library' @@ -31,7 +31,7 @@ Pod::Spec.new do |s| s.license = 'Apache License, Version 2.0' s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } - grpc_version = '1.18.0-dev' + grpc_version = '1.19.0-dev' s.source = { :git => 'https://github.com/grpc/grpc.git', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 240afbff7e6..7ddef6aa441 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -22,7 +22,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-Core' - version = '1.18.0-dev' + version = '1.19.0-dev' s.version = version s.summary = 'Core cross-platform gRPC library, written in C' s.homepage = 'https://grpc.io' diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index 13fe3e0b9c0..7bf53799de8 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-ProtoRPC' - version = '1.18.0-dev' + version = '1.19.0-dev' s.version = version s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.homepage = 'https://grpc.io' diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec index e132ad41b40..34bec88c8b4 100644 --- a/gRPC-RxLibrary.podspec +++ b/gRPC-RxLibrary.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-RxLibrary' - version = '1.18.0-dev' + version = '1.19.0-dev' s.version = version s.summary = 'Reactive Extensions library for iOS/OSX.' s.homepage = 'https://grpc.io' diff --git a/gRPC.podspec b/gRPC.podspec index 940a1ac6217..8e284866b3d 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.name = 'gRPC' - version = '1.18.0-dev' + version = '1.19.0-dev' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'https://grpc.io' diff --git a/package.xml b/package.xml index 2632fcb276b..d86c204746c 100644 --- a/package.xml +++ b/package.xml @@ -13,8 +13,8 @@ 2018-01-19 - 1.18.0dev - 1.18.0dev + 1.19.0dev + 1.19.0dev beta diff --git a/src/core/lib/surface/version.cc b/src/core/lib/surface/version.cc index 4829cc80a53..70d7580becb 100644 --- a/src/core/lib/surface/version.cc +++ b/src/core/lib/surface/version.cc @@ -25,4 +25,4 @@ const char* grpc_version_string(void) { return "7.0.0-dev"; } -const char* grpc_g_stands_for(void) { return "goose"; } +const char* grpc_g_stands_for(void) { return "gold"; } diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc index 55da89e6c83..358131c7c4c 100644 --- a/src/cpp/common/version_cc.cc +++ b/src/cpp/common/version_cc.cc @@ -22,5 +22,5 @@ #include namespace grpc { -grpc::string Version() { return "1.18.0-dev"; } +grpc::string Version() { return "1.19.0-dev"; } } // namespace grpc diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include index 4fffe4f6448..52ab2215ebe 100755 --- a/src/csharp/Grpc.Core/Version.csproj.include +++ b/src/csharp/Grpc.Core/Version.csproj.include @@ -1,7 +1,7 @@ - 1.18.0-dev + 1.19.0-dev 3.6.1 diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index 633880189ce..8f3be310ee7 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -33,11 +33,11 @@ namespace Grpc.Core /// /// Current AssemblyFileVersion of gRPC C# assemblies /// - public const string CurrentAssemblyFileVersion = "1.18.0.0"; + public const string CurrentAssemblyFileVersion = "1.19.0.0"; /// /// Current version of gRPC C# /// - public const string CurrentVersion = "1.18.0-dev"; + public const string CurrentVersion = "1.19.0-dev"; } } diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index 76d4f143901..fef1a43bb88 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -13,7 +13,7 @@ @rem limitations under the License. @rem Current package versions -set VERSION=1.18.0-dev +set VERSION=1.19.0-dev @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/csharp/build_unitypackage.bat b/src/csharp/build_unitypackage.bat index 3334d24c115..6b66b941a8d 100644 --- a/src/csharp/build_unitypackage.bat +++ b/src/csharp/build_unitypackage.bat @@ -13,7 +13,7 @@ @rem limitations under the License. @rem Current package versions -set VERSION=1.18.0-dev +set VERSION=1.19.0-dev @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index 55ca6048bc3..659cfebbdc0 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' - v = '1.18.0-dev' + v = '1.19.0-dev' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h index 0be0e3c9a00..5e089fde316 100644 --- a/src/objective-c/GRPCClient/private/version.h +++ b/src/objective-c/GRPCClient/private/version.h @@ -22,4 +22,4 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.18.0-dev" +#define GRPC_OBJC_VERSION_STRING @"1.19.0-dev" diff --git a/src/objective-c/tests/version.h b/src/objective-c/tests/version.h index f2fd692070b..54f95ad16a8 100644 --- a/src/objective-c/tests/version.h +++ b/src/objective-c/tests/version.h @@ -22,5 +22,5 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.18.0-dev" +#define GRPC_OBJC_VERSION_STRING @"1.19.0-dev" #define GRPC_C_VERSION_STRING @"7.0.0-dev" diff --git a/src/php/composer.json b/src/php/composer.json index 9c298c0e851..75fab483f14 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc-dev", "description": "gRPC library for PHP - for Developement use only", "license": "Apache-2.0", - "version": "1.18.0", + "version": "1.19.0", "require": { "php": ">=5.5.0", "google/protobuf": "^v3.3.0" diff --git a/src/php/ext/grpc/version.h b/src/php/ext/grpc/version.h index 1ddf90a667a..c85ee4d315b 100644 --- a/src/php/ext/grpc/version.h +++ b/src/php/ext/grpc/version.h @@ -20,6 +20,6 @@ #ifndef VERSION_H #define VERSION_H -#define PHP_GRPC_VERSION "1.18.0dev" +#define PHP_GRPC_VERSION "1.19.0dev" #endif /* VERSION_H */ diff --git a/src/python/grpcio/grpc/_grpcio_metadata.py b/src/python/grpcio/grpc/_grpcio_metadata.py index 7a9f173947a..dd9d436c3fe 100644 --- a/src/python/grpcio/grpc/_grpcio_metadata.py +++ b/src/python/grpcio/grpc/_grpcio_metadata.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!! -__version__ = """1.18.0.dev0""" +__version__ = """1.19.0.dev0""" diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index 2e91818d2ca..8e2f4d30bbc 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION = '1.18.0.dev0' +VERSION = '1.19.0.dev0' diff --git a/src/python/grpcio_channelz/grpc_version.py b/src/python/grpcio_channelz/grpc_version.py index 16356ea4020..5f3a894a2ae 100644 --- a/src/python/grpcio_channelz/grpc_version.py +++ b/src/python/grpcio_channelz/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_channelz/grpc_version.py.template`!!! -VERSION = '1.18.0.dev0' +VERSION = '1.19.0.dev0' diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py index 85fa762f7e8..4c2d434066e 100644 --- a/src/python/grpcio_health_checking/grpc_version.py +++ b/src/python/grpcio_health_checking/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! -VERSION = '1.18.0.dev0' +VERSION = '1.19.0.dev0' diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py index e62ab169a2f..6b88b2dfc50 100644 --- a/src/python/grpcio_reflection/grpc_version.py +++ b/src/python/grpcio_reflection/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!! -VERSION = '1.18.0.dev0' +VERSION = '1.19.0.dev0' diff --git a/src/python/grpcio_status/grpc_version.py b/src/python/grpcio_status/grpc_version.py index e009843b94f..2e58eb3b26c 100644 --- a/src/python/grpcio_status/grpc_version.py +++ b/src/python/grpcio_status/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_status/grpc_version.py.template`!!! -VERSION = '1.18.0.dev0' +VERSION = '1.19.0.dev0' diff --git a/src/python/grpcio_testing/grpc_version.py b/src/python/grpcio_testing/grpc_version.py index 7b4c1695faa..d4c5d94ecbe 100644 --- a/src/python/grpcio_testing/grpc_version.py +++ b/src/python/grpcio_testing/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!! -VERSION = '1.18.0.dev0' +VERSION = '1.19.0.dev0' diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py index 2fcd1ad617f..e1645ab1b86 100644 --- a/src/python/grpcio_tests/grpc_version.py +++ b/src/python/grpcio_tests/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!! -VERSION = '1.18.0.dev0' +VERSION = '1.19.0.dev0' diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index a4ed052d85e..3b7f62d9f55 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -14,5 +14,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '1.18.0.dev' + VERSION = '1.19.0.dev' end diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index 389fb70684b..2ad685a7eb3 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -14,6 +14,6 @@ module GRPC module Tools - VERSION = '1.18.0.dev' + VERSION = '1.19.0.dev' end end diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py index 29b2127960a..e5d9daef38f 100644 --- a/tools/distrib/python/grpcio_tools/grpc_version.py +++ b/tools/distrib/python/grpcio_tools/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! -VERSION = '1.18.0.dev0' +VERSION = '1.19.0.dev0' diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 1ab3a394b96..b0415fd4f64 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.18.0-dev +PROJECT_NUMBER = 1.19.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 5f488d51940..6c31a467680 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.18.0-dev +PROJECT_NUMBER = 1.19.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a From 077cc271e55ddb881054ab69feaaabc6e0ef6d81 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 3 Jan 2019 15:54:21 -0800 Subject: [PATCH 301/375] Proposed Cronet fixes --- .../transport/cronet/transport/cronet_transport.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc index 349d8681d55..278ef5636e3 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.cc +++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc @@ -335,6 +335,9 @@ static void add_to_storage(struct stream_obj* s, /* add new op at the beginning of the linked list. The memory is freed in remove_from_storage */ op_and_state* new_op = grpc_core::New(s, *op); + // Pontential fix to crash on GPR_ASSERT(!curr->done) + // TODO (mxyan): check if this is indeed necessary. + new_op->done = false; gpr_mu_lock(&s->mu); storage->head = new_op; storage->num_pending_ops++; @@ -391,7 +394,7 @@ static void execute_from_storage(stream_obj* s) { gpr_mu_lock(&s->mu); for (struct op_and_state* curr = s->storage.head; curr != nullptr;) { CRONET_LOG(GPR_DEBUG, "calling op at %p. done = %d", curr, curr->done); - GPR_ASSERT(curr->done == 0); + GPR_ASSERT(!curr->done); enum e_op_result result = execute_stream_op(curr); CRONET_LOG(GPR_DEBUG, "execute_stream_op[%p] returns %s", curr, op_result_string(result)); @@ -400,13 +403,12 @@ static void execute_from_storage(stream_obj* s) { struct op_and_state* next = curr->next; remove_from_storage(s, curr); curr = next; - } - /* continue processing the same op if ACTION_TAKEN_WITHOUT_CALLBACK */ - if (result == NO_ACTION_POSSIBLE) { + } else if (result == NO_ACTION_POSSIBLE) { curr = curr->next; } else if (result == ACTION_TAKEN_WITH_CALLBACK) { + /* wait for the callback */ break; - } + } /* continue processing the same op if ACTION_TAKEN_WITHOUT_CALLBACK */ } gpr_mu_unlock(&s->mu); } From 04dfa7d7b2343fd63a2f40aea28608b5a4938a29 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 3 Jan 2019 16:02:29 -0800 Subject: [PATCH 302/375] clang-format --- src/core/ext/transport/cronet/transport/cronet_transport.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc index 278ef5636e3..ade88da4cb9 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.cc +++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc @@ -336,7 +336,7 @@ static void add_to_storage(struct stream_obj* s, in remove_from_storage */ op_and_state* new_op = grpc_core::New(s, *op); // Pontential fix to crash on GPR_ASSERT(!curr->done) - // TODO (mxyan): check if this is indeed necessary. + // TODO (mxyan): check if this is indeed necessary. new_op->done = false; gpr_mu_lock(&s->mu); storage->head = new_op; From 03431b4f696387e34d6c438069a42ce56e269f04 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Thu, 3 Jan 2019 16:18:01 -0800 Subject: [PATCH 303/375] Remove filters from subchannel args --- .../ext/filters/client_channel/subchannel.cc | 13 ------------- .../ext/filters/client_channel/subchannel.h | 5 ----- .../filters/client_channel/subchannel_index.cc | 17 ----------------- src/core/lib/surface/channel_init.h | 5 +++++ src/cpp/common/channel_filter.h | 5 +++++ 5 files changed, 10 insertions(+), 35 deletions(-) diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 9077aa97539..3abacf68aeb 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -101,9 +101,6 @@ struct grpc_subchannel { keep the subchannel open */ gpr_atm ref_pair; - /** non-transport related channel filters */ - const grpc_channel_filter** filters; - size_t num_filters; /** channel arguments */ grpc_channel_args* args; @@ -384,7 +381,6 @@ static void subchannel_destroy(void* arg, grpc_error* error) { c->channelz_subchannel->MarkSubchannelDestroyed(); c->channelz_subchannel.reset(); } - gpr_free((void*)c->filters); c->health_check_service_name.reset(); grpc_channel_args_destroy(c->args); grpc_connectivity_state_destroy(&c->state_tracker); @@ -567,15 +563,6 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS); c->connector = connector; grpc_connector_ref(c->connector); - c->num_filters = args->filter_count; - if (c->num_filters > 0) { - c->filters = static_cast( - gpr_malloc(sizeof(grpc_channel_filter*) * c->num_filters)); - memcpy((void*)c->filters, args->filters, - sizeof(grpc_channel_filter*) * c->num_filters); - } else { - c->filters = nullptr; - } c->pollset_set = grpc_pollset_set_create(); grpc_resolved_address* addr = static_cast(gpr_malloc(sizeof(*addr))); diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 14f87f2c68e..d0c0a672fa1 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -189,11 +189,6 @@ grpc_call_stack* grpc_subchannel_call_get_call_stack( struct grpc_subchannel_args { /* When updating this struct, also update subchannel_index.c */ - /** Channel filters for this channel - wrapped factories will likely - want to mutate this */ - const grpc_channel_filter** filters; - /** The number of filters in the above array */ - size_t filter_count; /** Channel arguments to be supplied to the newly created channel */ const grpc_channel_args* args; }; diff --git a/src/core/ext/filters/client_channel/subchannel_index.cc b/src/core/ext/filters/client_channel/subchannel_index.cc index aa8441f17b0..0ae7898c5a4 100644 --- a/src/core/ext/filters/client_channel/subchannel_index.cc +++ b/src/core/ext/filters/client_channel/subchannel_index.cc @@ -49,15 +49,6 @@ static grpc_subchannel_key* create_key( grpc_channel_args* (*copy_channel_args)(const grpc_channel_args* args)) { grpc_subchannel_key* k = static_cast(gpr_malloc(sizeof(*k))); - k->args.filter_count = args->filter_count; - if (k->args.filter_count > 0) { - k->args.filters = static_cast( - gpr_malloc(sizeof(*k->args.filters) * k->args.filter_count)); - memcpy(reinterpret_cast(k->args.filters), - args->filters, sizeof(*k->args.filters) * k->args.filter_count); - } else { - k->args.filters = nullptr; - } k->args.args = copy_channel_args(args->args); return k; } @@ -75,18 +66,10 @@ int grpc_subchannel_key_compare(const grpc_subchannel_key* a, const grpc_subchannel_key* b) { // To pretend the keys are different, return a non-zero value. if (GPR_UNLIKELY(g_force_creation)) return 1; - int c = GPR_ICMP(a->args.filter_count, b->args.filter_count); - if (c != 0) return c; - if (a->args.filter_count > 0) { - c = memcmp(a->args.filters, b->args.filters, - a->args.filter_count * sizeof(*a->args.filters)); - if (c != 0) return c; - } return grpc_channel_args_compare(a->args.args, b->args.args); } void grpc_subchannel_key_destroy(grpc_subchannel_key* k) { - gpr_free(reinterpret_cast(k->args.filters)); grpc_channel_args_destroy(const_cast(k->args.args)); gpr_free(k); } diff --git a/src/core/lib/surface/channel_init.h b/src/core/lib/surface/channel_init.h index f01852473ba..d17a721606d 100644 --- a/src/core/lib/surface/channel_init.h +++ b/src/core/lib/surface/channel_init.h @@ -45,6 +45,11 @@ void grpc_channel_init_init(void); /// registration order (in the case of a tie). /// Stages are registered against one of the pre-determined channel stack /// types. +/// If the channel stack type is GRPC_CLIENT_SUBCHANNEL, the caller should +/// ensure that subchannels with different filter lists will always have +/// different channel args. This requires setting a channel arg in case the +/// registration function relies on some condition other than channel args to +/// decide whether to add a filter or not. void grpc_channel_init_register_stage(grpc_channel_stack_type type, int priority, grpc_channel_init_stage stage_fn, diff --git a/src/cpp/common/channel_filter.h b/src/cpp/common/channel_filter.h index 5e569c97e68..1a3295fc80f 100644 --- a/src/cpp/common/channel_filter.h +++ b/src/cpp/common/channel_filter.h @@ -366,6 +366,11 @@ void ChannelFilterPluginShutdown(); /// The \a include_filter argument specifies a function that will be called /// to determine at run-time whether or not to add the filter. If the /// value is nullptr, the filter will be added unconditionally. +/// If the channel stack type is GRPC_CLIENT_SUBCHANNEL, the caller should +/// ensure that subchannels with different filter lists will always have +/// different channel args. This requires setting a channel arg in case the +/// registration function relies on some condition other than channel args to +/// decide whether to add a filter or not. template void RegisterChannelFilter( const char* name, grpc_channel_stack_type stack_type, int priority, From 4224384d398ee3ddd01c0b95f93f33bdd75e8fb2 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 3 Jan 2019 15:47:00 -0800 Subject: [PATCH 304/375] Modifying semantics for GetSendMessage and GetSerializedSendMessage. Also adding ModifySendMessage --- include/grpcpp/impl/codegen/call_op_set.h | 31 +++++--- include/grpcpp/impl/codegen/interceptor.h | 2 + .../grpcpp/impl/codegen/interceptor_common.h | 33 +++++++-- .../client_interceptors_end2end_test.cc | 8 +-- .../server_interceptors_end2end_test.cc | 71 +++++++++++++++---- 5 files changed, 115 insertions(+), 30 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index 310bea93ca7..b9cf0b1db04 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -317,7 +317,10 @@ class CallOpSendMessage { protected: void AddOp(grpc_op* ops, size_t* nops) { - if (!send_buf_.Valid() || hijacked_) return; + if ((msg_ == nullptr && !send_buf_.Valid()) || hijacked_) return; + if (msg_ != nullptr) { + GPR_CODEGEN_ASSERT(serializer_(msg_).ok()); + } grpc_op* op = &ops[(*nops)++]; op->op = GRPC_OP_SEND_MESSAGE; op->flags = write_options_.flags(); @@ -330,17 +333,17 @@ class CallOpSendMessage { void SetInterceptionHookPoint( InterceptorBatchMethodsImpl* interceptor_methods) { - if (!send_buf_.Valid()) return; + if (msg_ == nullptr && !send_buf_.Valid()) return; interceptor_methods->AddInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_MESSAGE); - interceptor_methods->SetSendMessage(&send_buf_, msg_); + interceptor_methods->SetSendMessage(&send_buf_, &msg_, serializer_); } void SetFinishInterceptionHookPoint( InterceptorBatchMethodsImpl* interceptor_methods) { // The contents of the SendMessage value that was previously set // has had its references stolen by core's operations - interceptor_methods->SetSendMessage(nullptr, nullptr); + interceptor_methods->SetSendMessage(nullptr, nullptr, nullptr); } void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) { @@ -352,6 +355,7 @@ class CallOpSendMessage { bool hijacked_ = false; ByteBuffer send_buf_; WriteOptions write_options_; + std::function serializer_; }; template @@ -362,12 +366,21 @@ Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) { // The void in the template parameter below should not be needed // (since it should be implicit) but is needed due to an observed // difference in behavior between clang and gcc for certain internal users - Status result = SerializationTraits::Serialize( - message, send_buf_.bbuf_ptr(), &own_buf); - if (!own_buf) { - send_buf_.Duplicate(); + serializer_ = [this](const void* message) { + bool own_buf; + send_buf_.Clear(); + Status result = SerializationTraits::Serialize( + *static_cast(message), send_buf_.bbuf_ptr(), &own_buf); + if (!own_buf) { + send_buf_.Duplicate(); + } + return result; + }; + // Serialize immediately only if we do not have access to the message pointer + if (msg_ == nullptr) { + return serializer_(&message); } - return result; + return Status::OK; } template diff --git a/include/grpcpp/impl/codegen/interceptor.h b/include/grpcpp/impl/codegen/interceptor.h index 5a9a3a44e6e..edf3ab49f16 100644 --- a/include/grpcpp/impl/codegen/interceptor.h +++ b/include/grpcpp/impl/codegen/interceptor.h @@ -117,6 +117,8 @@ class InterceptorBatchMethods { /// only supported for sync and callback APIs at the present moment. virtual const void* GetSendMessage() = 0; + virtual void ModifySendMessage(const void* message) = 0; + /// Returns a modifiable multimap of the initial metadata to be sent. Valid /// for PRE_SEND_INITIAL_METADATA interceptions. A value of nullptr indicates /// that this field is not valid. diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index 4b7eaefee1b..6fa6210dc36 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -79,9 +79,24 @@ class InterceptorBatchMethodsImpl hooks_[static_cast(type)] = true; } - ByteBuffer* GetSerializedSendMessage() override { return send_message_; } + ByteBuffer* GetSerializedSendMessage() override { + GPR_CODEGEN_ASSERT(orig_send_message_ != nullptr); + if (*orig_send_message_ != nullptr) { + GPR_CODEGEN_ASSERT(serializer_(*orig_send_message_).ok()); + *orig_send_message_ = nullptr; + } + return send_message_; + } + + const void* GetSendMessage() override { + GPR_CODEGEN_ASSERT(orig_send_message_ != nullptr); + return *orig_send_message_; + } - const void* GetSendMessage() override { return orig_send_message_; } + void ModifySendMessage(const void* message) override { + GPR_CODEGEN_ASSERT(orig_send_message_ != nullptr); + *orig_send_message_ = message; + } std::multimap* GetSendInitialMetadata() override { return send_initial_metadata_; @@ -117,9 +132,11 @@ class InterceptorBatchMethodsImpl return recv_trailing_metadata_->map(); } - void SetSendMessage(ByteBuffer* buf, const void* msg) { + void SetSendMessage(ByteBuffer* buf, const void** msg, + std::function serializer) { send_message_ = buf; orig_send_message_ = msg; + serializer_ = serializer; } void SetSendInitialMetadata( @@ -339,7 +356,8 @@ class InterceptorBatchMethodsImpl std::function callback_; ByteBuffer* send_message_ = nullptr; - const void* orig_send_message_ = nullptr; + const void** orig_send_message_ = nullptr; + std::function serializer_; std::multimap* send_initial_metadata_; @@ -400,6 +418,13 @@ class CancelInterceptorBatchMethods return nullptr; } + void ModifySendMessage(const void* message) override { + GPR_CODEGEN_ASSERT( + false && + "It is illegal to call ModifySendMessage on a method which " + "has a Cancel notification"); + } + std::multimap* GetSendInitialMetadata() override { GPR_CODEGEN_ASSERT(false && "It is illegal to call GetSendInitialMetadata on a " diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 3db709e956e..ea72c1eda88 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -287,16 +287,16 @@ class LoggingInterceptor : public experimental::Interceptor { if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { EchoRequest req; + EXPECT_EQ(static_cast(methods->GetSendMessage()) + ->message() + .find("Hello"), + 0u); auto* buffer = methods->GetSerializedSendMessage(); auto copied_buffer = *buffer; EXPECT_TRUE( SerializationTraits::Deserialize(&copied_buffer, &req) .ok()); EXPECT_TRUE(req.message().find("Hello") == 0u); - EXPECT_EQ(static_cast(methods->GetSendMessage()) - ->message() - .find("Hello"), - 0u); } if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { diff --git a/test/cpp/end2end/server_interceptors_end2end_test.cc b/test/cpp/end2end/server_interceptors_end2end_test.cc index 09e855b0d01..82f142ba913 100644 --- a/test/cpp/end2end/server_interceptors_end2end_test.cc +++ b/test/cpp/end2end/server_interceptors_end2end_test.cc @@ -142,29 +142,68 @@ class LoggingInterceptorFactory } }; -// Test if GetSendMessage works as expected -class GetSendMessageTester : public experimental::Interceptor { +// Test if SendMessage function family works as expected for sync/callback apis +class SyncSendMessageTester : public experimental::Interceptor { public: - GetSendMessageTester(experimental::ServerRpcInfo* info) {} + SyncSendMessageTester(experimental::ServerRpcInfo* info) {} void Intercept(experimental::InterceptorBatchMethods* methods) override { if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { - EXPECT_EQ(static_cast(methods->GetSendMessage()) - ->message() - .find("Hello"), - 0u); + string old_msg = + static_cast(methods->GetSendMessage())->message(); + EXPECT_EQ(old_msg.find("Hello"), 0u); + new_msg_.set_message("World" + old_msg); + methods->ModifySendMessage(&new_msg_); } methods->Proceed(); } + + private: + EchoRequest new_msg_; }; -class GetSendMessageTesterFactory +class SyncSendMessageTesterFactory : public experimental::ServerInterceptorFactoryInterface { public: virtual experimental::Interceptor* CreateServerInterceptor( experimental::ServerRpcInfo* info) override { - return new GetSendMessageTester(info); + return new SyncSendMessageTester(info); + } +}; + +// Test if SendMessage function family works as expected for sync/callback apis +class SyncSendMessageVerifier : public experimental::Interceptor { + public: + SyncSendMessageVerifier(experimental::ServerRpcInfo* info) {} + + void Intercept(experimental::InterceptorBatchMethods* methods) override { + if (methods->QueryInterceptionHookPoint( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) { + // Make sure that the changes made in SyncSendMessageTester persisted + string old_msg = + static_cast(methods->GetSendMessage())->message(); + EXPECT_EQ(old_msg.find("World"), 0u); + + // Remove the "World" part of the string that we added earlier + new_msg_.set_message(old_msg.erase(0, 5)); + methods->ModifySendMessage(&new_msg_); + + // LoggingInterceptor verifies that changes got reverted + } + methods->Proceed(); + } + + private: + EchoRequest new_msg_; +}; + +class SyncSendMessageVerifierFactory + : public experimental::ServerInterceptorFactoryInterface { + public: + virtual experimental::Interceptor* CreateServerInterceptor( + experimental::ServerRpcInfo* info) override { + return new SyncSendMessageVerifier(info); } }; @@ -201,10 +240,13 @@ class ServerInterceptorsEnd2endSyncUnaryTest : public ::testing::Test { creators; creators.push_back( std::unique_ptr( - new LoggingInterceptorFactory())); + new SyncSendMessageTesterFactory())); creators.push_back( std::unique_ptr( - new GetSendMessageTesterFactory())); + new SyncSendMessageVerifierFactory())); + creators.push_back( + std::unique_ptr( + new LoggingInterceptorFactory())); // Add 20 dummy interceptor factories and null interceptor factories for (auto i = 0; i < 20; i++) { creators.push_back(std::unique_ptr( @@ -244,10 +286,13 @@ class ServerInterceptorsEnd2endSyncStreamingTest : public ::testing::Test { creators; creators.push_back( std::unique_ptr( - new LoggingInterceptorFactory())); + new SyncSendMessageTesterFactory())); creators.push_back( std::unique_ptr( - new GetSendMessageTesterFactory())); + new SyncSendMessageVerifierFactory())); + creators.push_back( + std::unique_ptr( + new LoggingInterceptorFactory())); for (auto i = 0; i < 20; i++) { creators.push_back(std::unique_ptr( new DummyInterceptorFactory())); From df49204b975b898392655a4af5a0597d7b2ec850 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 3 Jan 2019 18:10:21 -0800 Subject: [PATCH 305/375] Remove unused variable --- include/grpcpp/impl/codegen/call_op_set.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index b9cf0b1db04..88c744a3fcf 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -361,7 +361,6 @@ class CallOpSendMessage { template Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) { write_options_ = options; - bool own_buf; // TODO(vjpai): Remove the void below when possible // The void in the template parameter below should not be needed // (since it should be implicit) but is needed due to an observed From 7eeda22d9ed2f9936ec5a2ad61076274dfb5282b Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 3 Jan 2019 18:23:15 -0800 Subject: [PATCH 306/375] s/two/three --- include/grpcpp/impl/codegen/interceptor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grpcpp/impl/codegen/interceptor.h b/include/grpcpp/impl/codegen/interceptor.h index 0ad257bcd6d..519c65c7178 100644 --- a/include/grpcpp/impl/codegen/interceptor.h +++ b/include/grpcpp/impl/codegen/interceptor.h @@ -46,7 +46,7 @@ namespace experimental { /// operation has been requested and it is available. POST_RECV means that a /// result is available but has not yet been passed back to the application. enum class InterceptionHookPoints { - /// The first two in this list are for clients and servers + /// The first three in this list are for clients and servers PRE_SEND_INITIAL_METADATA, PRE_SEND_MESSAGE, POST_SEND_MESSAGE, From 2b4781ca526b0823fbea263a5c7b07fdf8abe41d Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 3 Jan 2019 18:32:10 -0800 Subject: [PATCH 307/375] Use Status() instead of Status::OK to avoid issues with codegen_test_minimal --- include/grpcpp/impl/codegen/call_op_set.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index 88c744a3fcf..e8a4d389f17 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -379,7 +379,7 @@ Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) { if (msg_ == nullptr) { return serializer_(&message); } - return Status::OK; + return Status(); } template From c4ed5b33c4de7d239f9ee26e128e4ee26e677465 Mon Sep 17 00:00:00 2001 From: Alex Polcyn Date: Fri, 4 Jan 2019 09:21:17 +0000 Subject: [PATCH 308/375] Pin bundler in ruby interop build --- tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh index 67f66090ae9..e71ad91499a 100755 --- a/tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh +++ b/tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh @@ -30,4 +30,4 @@ cd /var/local/git/grpc rvm --default use ruby-2.5 # build Ruby interop client and server -(cd src/ruby && gem update bundler && bundle && rake compile) +(cd src/ruby && gem install bundler -v 1.17.3 && bundle && rake compile) From 4cbdf08e61b2f168a42a8984b58126aebdb9097e Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 4 Jan 2019 10:33:18 +0100 Subject: [PATCH 309/375] debug out of disk space in run_interop_matrix_tests.py --- tools/internal_ci/linux/grpc_interop_matrix.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/internal_ci/linux/grpc_interop_matrix.sh b/tools/internal_ci/linux/grpc_interop_matrix.sh index a5220ea087f..5f1f69db952 100755 --- a/tools/internal_ci/linux/grpc_interop_matrix.sh +++ b/tools/internal_ci/linux/grpc_interop_matrix.sh @@ -22,4 +22,15 @@ cd $(dirname $0)/../../.. source tools/internal_ci/helper_scripts/prepare_build_linux_rc -tools/interop_matrix/run_interop_matrix_tests.py $RUN_TESTS_FLAGS +# TODO(jtattermusch): Diagnose out of disk space problems. Remove once not needed. +df -h + +tools/interop_matrix/run_interop_matrix_tests.py $RUN_TESTS_FLAGS || FAILED="true" + +# TODO(jtattermusch): Diagnose out of disk space problems. Remove once not needed. +df -h + +if [ "$FAILED" != "" ] +then + exit 1 +fi From b0663e7e1ebb164982fc3ca95c453c4b4dad5964 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 4 Jan 2019 12:31:34 +0100 Subject: [PATCH 310/375] interop_matrix: reliable cleanup of interop docker images --- .../run_interop_matrix_tests.py | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tools/interop_matrix/run_interop_matrix_tests.py b/tools/interop_matrix/run_interop_matrix_tests.py index 6cf2a9b0365..d47b0ee0f7b 100755 --- a/tools/interop_matrix/run_interop_matrix_tests.py +++ b/tools/interop_matrix/run_interop_matrix_tests.py @@ -232,10 +232,13 @@ def _run_tests_for_lang(lang, runtime, images, xml_report_tree): images is a list of (, ) tuple. """ + skip_tests = False if not _pull_images_for_lang(lang, images): jobset.message( - 'FAILED', 'Image download failed. Exiting.', do_newline=True) - return 1 + 'FAILED', + 'Image download failed. Skipping tests for language "%s"' % lang, + do_newline=True) + skip_tests = True total_num_failures = 0 for release, image in images: @@ -246,17 +249,22 @@ def _run_tests_for_lang(lang, runtime, images, xml_report_tree): if not job_spec_list: jobset.message( 'FAILED', 'No test cases were found.', do_newline=True) - return 1 + total_num_failures += 1 + continue num_failures, resultset = jobset.run( job_spec_list, newline_on_success=True, add_env={'docker_image': image}, - maxjobs=args.jobs) + maxjobs=args.jobs, + skip_jobs=skip_tests) if args.bq_result_table and resultset: upload_test_results.upload_interop_results_to_bq( resultset, args.bq_result_table) - if num_failures: + if skip_tests: + jobset.message('FAILED', 'Tests were skipped', do_newline=True) + total_num_failures += 1 + elif num_failures: jobset.message('FAILED', 'Some tests failed', do_newline=True) total_num_failures += num_failures else: @@ -266,6 +274,8 @@ def _run_tests_for_lang(lang, runtime, images, xml_report_tree): 'grpc_interop_matrix', suite_name, str(uuid.uuid4())) + # cleanup all downloaded docker images + for _, image in images: if not args.keep: _cleanup_docker_image(image) From b4a926961abc9e29016b2ba30093f3925de10514 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 4 Jan 2019 09:40:18 -0800 Subject: [PATCH 311/375] Fix static analizer errors --- src/objective-c/GRPCClient/GRPCCallOptions.m | 11 ++++++++--- src/objective-c/GRPCClient/private/GRPCChannelPool.h | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCallOptions.m b/src/objective-c/GRPCClient/GRPCCallOptions.m index d3440ee6c07..e59a812bd85 100644 --- a/src/objective-c/GRPCClient/GRPCCallOptions.m +++ b/src/objective-c/GRPCClient/GRPCCallOptions.m @@ -160,7 +160,10 @@ static BOOL areObjectsEqual(id obj1, id obj2) { _timeout = timeout < 0 ? 0 : timeout; _oauth2AccessToken = [oauth2AccessToken copy]; _authTokenProvider = authTokenProvider; - _initialMetadata = [[NSDictionary alloc] initWithDictionary:initialMetadata copyItems:YES]; + _initialMetadata = + initialMetadata == nil + ? nil + : [[NSDictionary alloc] initWithDictionary:initialMetadata copyItems:YES]; _userAgentPrefix = [userAgentPrefix copy]; _responseSizeLimit = responseSizeLimit; _compressionAlgorithm = compressionAlgorithm; @@ -171,7 +174,9 @@ static BOOL areObjectsEqual(id obj1, id obj2) { _connectInitialBackoff = connectInitialBackoff < 0 ? 0 : connectInitialBackoff; _connectMaxBackoff = connectMaxBackoff < 0 ? 0 : connectMaxBackoff; _additionalChannelArgs = - [[NSDictionary alloc] initWithDictionary:additionalChannelArgs copyItems:YES]; + additionalChannelArgs == nil + ? nil + : [[NSDictionary alloc] initWithDictionary:additionalChannelArgs copyItems:YES]; _PEMRootCertificates = [PEMRootCertificates copy]; _PEMPrivateKey = [PEMPrivateKey copy]; _PEMCertificateChain = [PEMCertificateChain copy]; @@ -458,7 +463,7 @@ static BOOL areObjectsEqual(id obj1, id obj2) { - (void)setConnectMinTimeout:(NSTimeInterval)connectMinTimeout { if (connectMinTimeout < 0) { - connectMinTimeout = 0; + _connectMinTimeout = 0; } else { _connectMinTimeout = connectMinTimeout; } diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.h b/src/objective-c/GRPCClient/private/GRPCChannelPool.h index d3a99ca8263..e00ee69e63a 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.h +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.h @@ -88,7 +88,8 @@ NS_ASSUME_NONNULL_BEGIN /** * Return a channel with a particular configuration. The channel may be a cached channel. */ -- (GRPCPooledChannel *)channelWithHost:(NSString *)host callOptions:(GRPCCallOptions *)callOptions; +- (nullable GRPCPooledChannel *)channelWithHost:(NSString *)host + callOptions:(GRPCCallOptions *)callOptions; /** * Disconnect all channels in this pool. From a5ed3d245e448c1e0e0e28b93e5821aaa7a3e439 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 4 Jan 2019 11:17:35 -0800 Subject: [PATCH 312/375] Avoid unsigned signed comparison issues --- test/cpp/end2end/client_interceptors_end2end_test.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index ab387aa9144..fc75fdb290b 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -291,7 +291,7 @@ class BidiStreamingRpcHijackingInterceptor : public experimental::Interceptor { EXPECT_TRUE( SerializationTraits::Deserialize(&copied_buffer, &req) .ok()); - EXPECT_EQ(req.message().find("Hello"), 0); + EXPECT_EQ(req.message().find("Hello"), 0u); msg = req.message(); } if (methods->QueryInterceptionHookPoint( @@ -316,7 +316,7 @@ class BidiStreamingRpcHijackingInterceptor : public experimental::Interceptor { EXPECT_EQ(static_cast(methods->GetRecvMessage()) ->message() .find("Hello"), - 0); + 0u); } if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_RECV_STATUS)) { @@ -370,7 +370,7 @@ class LoggingInterceptor : public experimental::Interceptor { EXPECT_TRUE( SerializationTraits::Deserialize(&copied_buffer, &req) .ok()); - EXPECT_TRUE(req.message().find("Hello") == 0); + EXPECT_TRUE(req.message().find("Hello") == 0u); } if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) { @@ -386,7 +386,7 @@ class LoggingInterceptor : public experimental::Interceptor { experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) { EchoResponse* resp = static_cast(methods->GetRecvMessage()); - EXPECT_TRUE(resp->message().find("Hello") == 0); + EXPECT_TRUE(resp->message().find("Hello") == 0u); } if (methods->QueryInterceptionHookPoint( experimental::InterceptionHookPoints::POST_RECV_STATUS)) { From 9b9ef640278fd5d0c9a64c1b0c7182277bc35f53 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 4 Jan 2019 11:29:57 -0800 Subject: [PATCH 313/375] Add more information on the usage of FailHijackedRecvMessage --- include/grpcpp/impl/codegen/interceptor.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/grpcpp/impl/codegen/interceptor.h b/include/grpcpp/impl/codegen/interceptor.h index a1cb80013da..cf92ce46b43 100644 --- a/include/grpcpp/impl/codegen/interceptor.h +++ b/include/grpcpp/impl/codegen/interceptor.h @@ -157,7 +157,9 @@ class InterceptorBatchMethods { /// list. virtual std::unique_ptr GetInterceptedChannel() = 0; - // On a hijacked RPC, an interceptor can decide to fail a RECV MESSAGE op. + /// On a hijacked RPC, an interceptor can decide to fail a PRE_RECV_MESSAGE + /// op. This would be a signal to the reader that there will be no more + /// messages, or the stream has failed or been cancelled. virtual void FailHijackedRecvMessage() = 0; }; From d79d2f1ca763d758b2d83a39a27c3e7e698e94a9 Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Fri, 4 Jan 2019 13:59:19 -0800 Subject: [PATCH 314/375] Do not reload grpc in unit tests This can break subsequently run tests, including any which have already stored references to gRPC enums (such as grpc.StatusCode.OK). The subsequent tests will compare now be comparing the old enums to the reloaded enums, and they will not match. This causes errors in _metadata_code_details_test and a hang in _metadata_flags_test, when run in sequence locally after _logging_test. It's unclear why this has been working on Kokoro, but it is reproducible locally and is behavior that should be avoided. --- .../grpcio_tests/tests/unit/_logging_test.py | 104 +++++++++++------- 1 file changed, 62 insertions(+), 42 deletions(-) diff --git a/src/python/grpcio_tests/tests/unit/_logging_test.py b/src/python/grpcio_tests/tests/unit/_logging_test.py index 631b9de9db5..8ff127f5062 100644 --- a/src/python/grpcio_tests/tests/unit/_logging_test.py +++ b/src/python/grpcio_tests/tests/unit/_logging_test.py @@ -14,66 +14,86 @@ """Test of gRPC Python's interaction with the python logging module""" import unittest -import six -from six.moves import reload_module import logging import grpc -import functools +import subprocess import sys +INTERPRETER = sys.executable -def patch_stderr(f): - @functools.wraps(f) - def _impl(*args, **kwargs): - old_stderr = sys.stderr - sys.stderr = six.StringIO() - try: - f(*args, **kwargs) - finally: - sys.stderr = old_stderr +class LoggingTest(unittest.TestCase): - return _impl + def test_logger_not_occupied(self): + script = """if True: + import logging + import grpc -def isolated_logging(f): + if len(logging.getLogger().handlers) != 0: + raise Exception('expected 0 logging handlers') - @functools.wraps(f) - def _impl(*args, **kwargs): - reload_module(logging) - reload_module(grpc) - try: - f(*args, **kwargs) - finally: - reload_module(logging) + """ + self._verifyScriptSucceeds(script) - return _impl + def test_handler_found(self): + script = """if True: + import logging + import grpc + """ + out, err = self._verifyScriptSucceeds(script) + self.assertEqual(0, len(err), 'unexpected output to stderr') -class LoggingTest(unittest.TestCase): + def test_can_configure_logger(self): + script = """if True: + import logging + import six - @isolated_logging - def test_logger_not_occupied(self): - self.assertEqual(0, len(logging.getLogger().handlers)) + import grpc - @patch_stderr - @isolated_logging - def test_handler_found(self): - self.assertEqual(0, len(sys.stderr.getvalue())) - @isolated_logging - def test_can_configure_logger(self): - intended_stream = six.StringIO() - logging.basicConfig(stream=intended_stream) - self.assertEqual(1, len(logging.getLogger().handlers)) - self.assertIs(logging.getLogger().handlers[0].stream, intended_stream) + intended_stream = six.StringIO() + logging.basicConfig(stream=intended_stream) + + if len(logging.getLogger().handlers) != 1: + raise Exception('expected 1 logging handler') + + if logging.getLogger().handlers[0].stream is not intended_stream: + raise Exception('wrong handler stream') + + """ + self._verifyScriptSucceeds(script) - @isolated_logging def test_grpc_logger(self): - self.assertIn("grpc", logging.Logger.manager.loggerDict) - root_logger = logging.getLogger("grpc") - self.assertEqual(1, len(root_logger.handlers)) - self.assertIsInstance(root_logger.handlers[0], logging.NullHandler) + script = """if True: + import logging + + import grpc + + if "grpc" not in logging.Logger.manager.loggerDict: + raise Exception('grpc logger not found') + + root_logger = logging.getLogger("grpc") + if len(root_logger.handlers) != 1: + raise Exception('expected 1 root logger handler') + if not isinstance(root_logger.handlers[0], logging.NullHandler): + raise Exception('expected logging.NullHandler') + + """ + self._verifyScriptSucceeds(script) + + def _verifyScriptSucceeds(self, script): + process = subprocess.Popen( + [INTERPRETER, '-c', script], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = process.communicate() + self.assertEqual( + 0, process.returncode, + 'process failed with exit code %d (stdout: %s, stderr: %s)' % + (process.returncode, out, err)) + return out, err if __name__ == '__main__': From 4b2086eecdb6fb97c1fa791c58f23c22acea74be Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Fri, 4 Jan 2019 14:12:11 -0800 Subject: [PATCH 315/375] restore cython flag value to default after test --- src/python/grpcio_tests/tests/unit/_cython/_fork_test.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/python/grpcio_tests/tests/unit/_cython/_fork_test.py b/src/python/grpcio_tests/tests/unit/_cython/_fork_test.py index aeb02458a7e..5a5dedd5f26 100644 --- a/src/python/grpcio_tests/tests/unit/_cython/_fork_test.py +++ b/src/python/grpcio_tests/tests/unit/_cython/_fork_test.py @@ -27,6 +27,7 @@ def _get_number_active_threads(): class ForkPosixTester(unittest.TestCase): def setUp(self): + self._saved_fork_support_flag = cygrpc._GRPC_ENABLE_FORK_SUPPORT cygrpc._GRPC_ENABLE_FORK_SUPPORT = True def testForkManagedThread(self): @@ -50,6 +51,9 @@ class ForkPosixTester(unittest.TestCase): thread.join() self.assertEqual(0, _get_number_active_threads()) + def tearDown(self): + cygrpc._GRPC_ENABLE_FORK_SUPPORT = self._saved_fork_support_flag + @unittest.skipUnless(os.name == 'nt', 'Windows-specific tests') class ForkWindowsTester(unittest.TestCase): From 0d6e10e795e9c627368afebf7d877bc392cd78dd Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Mon, 7 Jan 2019 10:15:07 -0500 Subject: [PATCH 316/375] clang-format all the files. Whenever we run clang-format, gen_build_yaml.py and ServerServiceDefinitionExtensions.cs get modified by the script. Let's commit those changes so that these file remain unmodified after running the formatting script. --- .../Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs | 2 +- test/cpp/qps/gen_build_yaml.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs b/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs index 8987544f7f4..56ead8a6a15 100644 --- a/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs +++ b/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs @@ -76,4 +76,4 @@ namespace Grpc.Core.Interceptors return serverServiceDefinition; } } -} \ No newline at end of file +} diff --git a/test/cpp/qps/gen_build_yaml.py b/test/cpp/qps/gen_build_yaml.py index fb2caf5486a..8ca0dc6a620 100755 --- a/test/cpp/qps/gen_build_yaml.py +++ b/test/cpp/qps/gen_build_yaml.py @@ -131,4 +131,4 @@ def generate_yaml(): } -print(yaml.dump(generate_yaml())) \ No newline at end of file +print(yaml.dump(generate_yaml())) From 747608df379e0a06ccc5cea469455d80591ea430 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 6 Dec 2018 17:16:04 +0100 Subject: [PATCH 317/375] add go1.11 interop image templates --- .../grpc_interop_go1.11/Dockerfile.template | 23 +++++++++++++++++++ .../build_interop.sh.template | 3 +++ 2 files changed, 26 insertions(+) create mode 100644 templates/tools/dockerfile/interoptest/grpc_interop_go1.11/Dockerfile.template create mode 100644 templates/tools/dockerfile/interoptest/grpc_interop_go1.11/build_interop.sh.template diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_go1.11/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_go1.11/Dockerfile.template new file mode 100644 index 00000000000..4921d93f499 --- /dev/null +++ b/templates/tools/dockerfile/interoptest/grpc_interop_go1.11/Dockerfile.template @@ -0,0 +1,23 @@ +%YAML 1.2 +--- | + # Copyright 2018 The gRPC Authors + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + + FROM golang:1.11 + + <%include file="../../go_path.include"/> + <%include file="../../python_deps.include"/> + # Define the default command. + CMD ["bash"] + diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_go1.11/build_interop.sh.template b/templates/tools/dockerfile/interoptest/grpc_interop_go1.11/build_interop.sh.template new file mode 100644 index 00000000000..a08798b1d6b --- /dev/null +++ b/templates/tools/dockerfile/interoptest/grpc_interop_go1.11/build_interop.sh.template @@ -0,0 +1,3 @@ +%YAML 1.2 +--- | + <%include file="../../go_build_interop.sh.include"/> From bdee6308312376d28e762e49b3d7834c1e925d06 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 6 Dec 2018 17:16:39 +0100 Subject: [PATCH 318/375] regenerate dockerimages --- .../grpc_interop_go1.11/Dockerfile | 36 +++++++++++++++++++ .../grpc_interop_go1.11/build_interop.sh | 33 +++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 tools/dockerfile/interoptest/grpc_interop_go1.11/Dockerfile create mode 100644 tools/dockerfile/interoptest/grpc_interop_go1.11/build_interop.sh diff --git a/tools/dockerfile/interoptest/grpc_interop_go1.11/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_go1.11/Dockerfile new file mode 100644 index 00000000000..0892bc34599 --- /dev/null +++ b/tools/dockerfile/interoptest/grpc_interop_go1.11/Dockerfile @@ -0,0 +1,36 @@ +# Copyright 2018 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM golang:1.11 + +# Using login shell removes Go from path, so we add it. +RUN ln -s /usr/local/go/bin/go /usr/local/bin + +#==================== +# Python dependencies + +# Install dependencies + +RUN apt-get update && apt-get install -y \ + python-all-dev \ + python3-all-dev \ + python-pip + +# Install Python packages from PyPI +RUN pip install --upgrade pip==10.0.1 +RUN pip install virtualenv +RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0 + +# Define the default command. +CMD ["bash"] diff --git a/tools/dockerfile/interoptest/grpc_interop_go1.11/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_go1.11/build_interop.sh new file mode 100644 index 00000000000..b11ace3a4e7 --- /dev/null +++ b/tools/dockerfile/interoptest/grpc_interop_go1.11/build_interop.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# Copyright 2015 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Builds Go interop server and client in a base image. +set -e + +# Clone just the grpc-go source code without any dependencies. +# We are cloning from a local git repo that contains the right revision +# to test instead of using "go get" to download from Github directly. +git clone --recursive /var/local/jenkins/grpc-go src/google.golang.org/grpc + +# Get all gRPC Go dependencies +(cd src/google.golang.org/grpc && make deps && make testdeps) + +# copy service account keys if available +cp -r /var/local/jenkins/service_account $HOME || true + +# Build the interop client and server +(cd src/google.golang.org/grpc/interop/client && go install) +(cd src/google.golang.org/grpc/interop/server && go install) + From a13e77e14db90fd2b0a87ca151b4db0786f34ff6 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 7 Jan 2019 11:47:33 -0500 Subject: [PATCH 319/375] interop_matrix: support skipping runtimes --- tools/interop_matrix/client_matrix.py | 83 +++++++++++++++---- tools/interop_matrix/create_matrix_images.py | 2 +- .../run_interop_matrix_tests.py | 15 ++-- 3 files changed, 76 insertions(+), 24 deletions(-) diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py index c0b08a59b26..3546d59c313 100644 --- a/tools/interop_matrix/client_matrix.py +++ b/tools/interop_matrix/client_matrix.py @@ -35,6 +35,18 @@ def get_release_tag_name(release_info): return release_info.keys()[0] +def get_runtimes_for_lang_release(lang, release): + """Get list of valid runtimes for given release of lang.""" + runtimes_to_skip = [] + # see if any the lang release has "skip_runtime" annotation. + for release_info in LANG_RELEASE_MATRIX[lang]: + if get_release_tag_name(release_info) == release: + if release_info[release] is not None: + runtimes_to_skip = release_info[release].get('skip_runtime', []) + break + return [runtime for runtime in LANG_RUNTIME_MATRIX[lang] if runtime not in runtimes_to_skip] + + def should_build_docker_interop_image_from_release_tag(lang): if lang in ['go', 'java', 'node']: return False @@ -44,7 +56,7 @@ def should_build_docker_interop_image_from_release_tag(lang): # Dictionary of runtimes per language LANG_RUNTIME_MATRIX = { 'cxx': ['cxx'], # This is actually debian8. - 'go': ['go1.7', 'go1.8'], + 'go': ['go1.7', 'go1.8', 'go1.11'], 'java': ['java_oracle8'], 'python': ['python'], 'node': ['node'], @@ -110,52 +122,89 @@ LANG_RELEASE_MATRIX = { ], 'go': [ { - 'v1.0.5': None + 'v1.0.5': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.2.1': None + 'v1.2.1': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.3.0': None + 'v1.3.0': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.4.2': None + 'v1.4.2': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.5.2': None + 'v1.5.2': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.6.0': None + 'v1.6.0': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.7.4': None + 'v1.7.4': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.8.2': None + 'v1.8.2': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.9.2': None + 'v1.9.2': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.10.1': None + 'v1.10.1': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.11.3': None + 'v1.11.3': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.12.2': None + 'v1.12.2': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.13.0': None + 'v1.13.0': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.14.0': None + 'v1.14.0': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.15.0': None + 'v1.15.0': { + 'skip_runtime': ['go1.11'] + } }, { - 'v1.16.0': None + 'v1.16.0': { + 'skip_runtime': ['go1.11'] + } + }, + { + 'v1.17.0': { + 'skip_runtime': ['go1.7', 'go1.8'] + } }, ], 'java': [ diff --git a/tools/interop_matrix/create_matrix_images.py b/tools/interop_matrix/create_matrix_images.py index c2568efba0f..cf61d462482 100755 --- a/tools/interop_matrix/create_matrix_images.py +++ b/tools/interop_matrix/create_matrix_images.py @@ -217,7 +217,7 @@ def build_all_images_for_release(lang, release): }.get(lang, 'GRPC_ROOT') env[var] = stack_base - for runtime in client_matrix.LANG_RUNTIME_MATRIX[lang]: + for runtime in client_matrix.get_runtimes_for_lang_release(lang, release): job = build_image_jobspec(runtime, env, release, stack_base) docker_images.append(job.tag) build_jobs.append(job) diff --git a/tools/interop_matrix/run_interop_matrix_tests.py b/tools/interop_matrix/run_interop_matrix_tests.py index 6cf2a9b0365..693996031e3 100755 --- a/tools/interop_matrix/run_interop_matrix_tests.py +++ b/tools/interop_matrix/run_interop_matrix_tests.py @@ -113,13 +113,16 @@ def _get_test_images_for_lang(lang, release_arg, image_path_prefix): return {} releases = [release_arg] - # Images tuples keyed by runtime. + # Image tuples keyed by runtime. images = {} - for runtime in client_matrix.LANG_RUNTIME_MATRIX[lang]: - image_path = '%s/grpc_interop_%s' % (image_path_prefix, runtime) - images[runtime] = [ - (tag, '%s:%s' % (image_path, tag)) for tag in releases - ] + for tag in releases: + for runtime in client_matrix.get_runtimes_for_lang_release(lang, tag): + image_name = '%s/grpc_interop_%s:%s' % (image_path_prefix, runtime, tag) + image_tuple = (tag, image_name) + + if not images.has_key(runtime): + images[runtime] = [] + images[runtime].append(image_tuple) return images From 7d1491d64c9b6279233c780d290c514a7040c1c7 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 7 Jan 2019 09:23:35 -0800 Subject: [PATCH 320/375] Address reviewer comments --- include/grpcpp/impl/codegen/call_op_set.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index e8a4d389f17..ced0b2ff3e6 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -321,6 +321,7 @@ class CallOpSendMessage { if (msg_ != nullptr) { GPR_CODEGEN_ASSERT(serializer_(msg_).ok()); } + serializer_ = nullptr; grpc_op* op = &ops[(*nops)++]; op->op = GRPC_OP_SEND_MESSAGE; op->flags = write_options_.flags(); @@ -361,13 +362,13 @@ class CallOpSendMessage { template Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) { write_options_ = options; - // TODO(vjpai): Remove the void below when possible - // The void in the template parameter below should not be needed - // (since it should be implicit) but is needed due to an observed - // difference in behavior between clang and gcc for certain internal users serializer_ = [this](const void* message) { bool own_buf; send_buf_.Clear(); + // TODO(vjpai): Remove the void below when possible + // The void in the template parameter below should not be needed + // (since it should be implicit) but is needed due to an observed + // difference in behavior between clang and gcc for certain internal users Status result = SerializationTraits::Serialize( *static_cast(message), send_buf_.bbuf_ptr(), &own_buf); if (!own_buf) { From 2dc63f3d02efd2cb0ccea45248dd305e442c70d9 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 7 Jan 2019 19:08:02 +0100 Subject: [PATCH 321/375] yapf code --- tools/interop_matrix/client_matrix.py | 5 ++++- tools/interop_matrix/run_interop_matrix_tests.py | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py index 3546d59c313..4964fd61674 100644 --- a/tools/interop_matrix/client_matrix.py +++ b/tools/interop_matrix/client_matrix.py @@ -44,7 +44,10 @@ def get_runtimes_for_lang_release(lang, release): if release_info[release] is not None: runtimes_to_skip = release_info[release].get('skip_runtime', []) break - return [runtime for runtime in LANG_RUNTIME_MATRIX[lang] if runtime not in runtimes_to_skip] + return [ + runtime for runtime in LANG_RUNTIME_MATRIX[lang] + if runtime not in runtimes_to_skip + ] def should_build_docker_interop_image_from_release_tag(lang): diff --git a/tools/interop_matrix/run_interop_matrix_tests.py b/tools/interop_matrix/run_interop_matrix_tests.py index 693996031e3..d75cab90c25 100755 --- a/tools/interop_matrix/run_interop_matrix_tests.py +++ b/tools/interop_matrix/run_interop_matrix_tests.py @@ -117,7 +117,8 @@ def _get_test_images_for_lang(lang, release_arg, image_path_prefix): images = {} for tag in releases: for runtime in client_matrix.get_runtimes_for_lang_release(lang, tag): - image_name = '%s/grpc_interop_%s:%s' % (image_path_prefix, runtime, tag) + image_name = '%s/grpc_interop_%s:%s' % (image_path_prefix, runtime, + tag) image_tuple = (tag, image_name) if not images.has_key(runtime): From 5e10a3b037bcd20ab17428ccb765ba9464eb3644 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 21 Dec 2018 13:39:21 -0800 Subject: [PATCH 322/375] Make gRPC ObjC thread safety right --- src/objective-c/GRPCClient/GRPCCall.m | 360 ++++++++++-------- src/objective-c/RxLibrary/GRXBufferedPipe.m | 21 +- .../RxLibrary/GRXConcurrentWriteable.h | 4 +- .../RxLibrary/GRXConcurrentWriteable.m | 76 +--- .../RxLibrary/GRXForwardingWriter.m | 48 ++- .../RxLibrary/GRXImmediateSingleWriter.m | 30 +- src/objective-c/RxLibrary/GRXWriter.h | 4 +- 7 files changed, 275 insertions(+), 268 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 83c6edc6e3f..5ea1755c589 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -448,24 +448,30 @@ const char *kCFStreamVarName = "grpc_cfstream"; return; } NSString *hostAndPath = [NSString stringWithFormat:@"%@/%@", host, path]; - switch (callSafety) { - case GRPCCallSafetyDefault: - callFlags[hostAndPath] = @0; - break; - case GRPCCallSafetyIdempotentRequest: - callFlags[hostAndPath] = @GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; - break; - case GRPCCallSafetyCacheableRequest: - callFlags[hostAndPath] = @GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; - break; - default: - break; + @synchronized (callFlags) { + switch (callSafety) { + case GRPCCallSafetyDefault: + callFlags[hostAndPath] = @0; + break; + case GRPCCallSafetyIdempotentRequest: + callFlags[hostAndPath] = @GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; + break; + case GRPCCallSafetyCacheableRequest: + callFlags[hostAndPath] = @GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; + break; + default: + break; + } } } + (uint32_t)callFlagsForHost:(NSString *)host path:(NSString *)path { NSString *hostAndPath = [NSString stringWithFormat:@"%@/%@", host, path]; - return [callFlags[hostAndPath] intValue]; + uint32_t flags = 0; + @synchronized (callFlags) { + flags = [callFlags[hostAndPath] intValue]; + } + return flags; } // Designated initializer @@ -506,7 +512,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; _callOptions = [callOptions copy]; // Serial queue to invoke the non-reentrant methods of the grpc_call object. - _callQueue = dispatch_queue_create("io.grpc.call", NULL); + _callQueue = dispatch_queue_create("io.grpc.call", DISPATCH_QUEUE_SERIAL); _requestWriter = requestWriter; @@ -523,53 +529,49 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)setResponseDispatchQueue:(dispatch_queue_t)queue { - if (_state != GRXWriterStateNotStarted) { - return; + @synchronized (self) { + if (_state != GRXWriterStateNotStarted) { + return; + } + _responseQueue = queue; } - _responseQueue = queue; } #pragma mark Finish - (void)finishWithError:(NSError *)errorOrNil { + GRXConcurrentWriteable *copiedResponseWriteable = nil; + @synchronized(self) { + if (_state == GRXWriterStateFinished) { + return; + } _state = GRXWriterStateFinished; - } + copiedResponseWriteable = _responseWriteable; - // If there were still request messages coming, stop them. - @synchronized(_requestWriter) { - _requestWriter.state = GRXWriterStateFinished; + // If the call isn't retained anywhere else, it can be deallocated now. + _retainSelf = nil; } if (errorOrNil) { - [_responseWriteable cancelWithError:errorOrNil]; + [copiedResponseWriteable cancelWithError:errorOrNil]; } else { - [_responseWriteable enqueueSuccessfulCompletion]; - } - - [GRPCConnectivityMonitor unregisterObserver:self]; - - // If the call isn't retained anywhere else, it can be deallocated now. - _retainSelf = nil; -} - -- (void)cancelCall { - // Can be called from any thread, any number of times. - @synchronized(self) { - [_wrappedCall cancel]; + [copiedResponseWriteable enqueueSuccessfulCompletion]; } + _requestWriter.state = GRXWriterStateFinished; } - (void)cancel { - @synchronized(self) { - [self cancelCall]; - self.isWaitingForToken = NO; + @synchronized (self) { + if (_state == GRXWriterStateFinished) { + return; + } + [self finishWithError:[NSError + errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeCancelled + userInfo:@{NSLocalizedDescriptionKey : @"Canceled by app"}]]; + [_wrappedCall cancel]; } - [self - maybeFinishWithError:[NSError - errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeCancelled - userInfo:@{NSLocalizedDescriptionKey : @"Canceled by app"}]]; } - (void)maybeFinishWithError:(NSError *)errorOrNil { @@ -609,21 +611,24 @@ const char *kCFStreamVarName = "grpc_cfstream"; // TODO(jcanizales): Rename to readResponseIfNotPaused. - (void)startNextRead { @synchronized(self) { - if (self.state == GRXWriterStatePaused) { + if (_state != GRXWriterStateStarted) { return; } } dispatch_async(_callQueue, ^{ __weak GRPCCall *weakSelf = self; - __weak GRXConcurrentWriteable *weakWriteable = self->_responseWriteable; [self startReadWithHandler:^(grpc_byte_buffer *message) { - __strong GRPCCall *strongSelf = weakSelf; - __strong GRXConcurrentWriteable *strongWriteable = weakWriteable; + NSLog(@"message received"); if (message == NULL) { // No more messages from the server return; } + __strong GRPCCall *strongSelf = weakSelf; + if (strongSelf == nil) { + grpc_byte_buffer_destroy(message); + return; + } NSData *data = [NSData grpc_dataWithByteBuffer:message]; grpc_byte_buffer_destroy(message); if (!data) { @@ -631,21 +636,25 @@ const char *kCFStreamVarName = "grpc_cfstream"; // 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. - [strongSelf cancelCall]; - [strongSelf - maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeResourceExhausted - userInfo:@{ - NSLocalizedDescriptionKey : - @"Client does not have enough memory to " - @"hold the server response." - }]]; - return; + @synchronized (strongSelf) { + [strongSelf + finishWithError:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeResourceExhausted + userInfo:@{ + NSLocalizedDescriptionKey : + @"Client does not have enough memory to " + @"hold the server response." + }]]; + [strongSelf->_wrappedCall cancel]; + } + } else { + @synchronized (strongSelf) { + [strongSelf->_responseWriteable enqueueValue:data + completionHandler:^{ + [strongSelf startNextRead]; + }]; + } } - [strongWriteable enqueueValue:data - completionHandler:^{ - [strongSelf startNextRead]; - }]; }]; }); } @@ -680,15 +689,16 @@ const char *kCFStreamVarName = "grpc_cfstream"; } // TODO(jcanizales): Add error handlers for async failures - GRPCOpSendMetadata *op = [[GRPCOpSendMetadata alloc] - initWithMetadata:headers - flags:callSafetyFlags - handler:nil]; // No clean-up needed after SEND_INITIAL_METADATA - if (!_unaryCall) { - [_wrappedCall startBatchWithOperations:@[ op ]]; - } else { - [_unaryOpBatch addObject:op]; - } + GRPCOpSendMetadata *op = [[GRPCOpSendMetadata alloc] initWithMetadata:headers + flags:callSafetyFlags + handler:nil]; // No clean-up needed after SEND_INITIAL_METADATA + dispatch_async(_callQueue, ^{ + if (!self->_unaryCall) { + [self->_wrappedCall startBatchWithOperations:@[ op ]]; + } else { + [self->_unaryOpBatch addObject:op]; + } + }); } #pragma mark GRXWriteable implementation @@ -703,9 +713,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Resume the request writer. GRPCCall *strongSelf = weakSelf; if (strongSelf) { - @synchronized(strongSelf->_requestWriter) { - strongSelf->_requestWriter.state = GRXWriterStateStarted; - } + strongSelf->_requestWriter.state = GRXWriterStateStarted; } }; @@ -721,13 +729,17 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)writeValue:(id)value { - // TODO(jcanizales): Throw/assert if value isn't NSData. + NSAssert([value isKindOfClass:[NSData class]], @"value must be of type NSData"); + + @synchronized (self) { + if (_state == GRXWriterStateFinished) { + return; + } + } // Pause the input and only resume it when the C layer notifies us that writes // can proceed. - @synchronized(_requestWriter) { - _requestWriter.state = GRXWriterStatePaused; - } + _requestWriter.state = GRXWriterStatePaused; dispatch_async(_callQueue, ^{ // Write error is not processed here. It is handled by op batch of GRPC_OP_RECV_STATUS_ON_CLIENT @@ -752,6 +764,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; [self cancel]; } else { dispatch_async(_callQueue, ^{ + // EOS error is not processed here. It is handled by op batch of GRPC_OP_RECV_STATUS_ON_CLIENT [self finishRequestWithErrorHandler:nil]; }); @@ -766,17 +779,20 @@ const char *kCFStreamVarName = "grpc_cfstream"; // The second one (completionHandler), whenever the RPC finishes for any reason. - (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] ]]; + dispatch_async(_callQueue, ^{ + // TODO(jcanizales): Add error handlers for async failures + [self->_wrappedCall + startBatchWithOperations:@[ [[GRPCOpRecvMetadata alloc] initWithHandler:headersHandler] ]]; + [self->_wrappedCall + startBatchWithOperations:@[ [[GRPCOpRecvStatus alloc] initWithHandler:completionHandler] ]]; + }); } - (void)invokeCall { __weak GRPCCall *weakSelf = self; [self invokeCallWithHeadersHandler:^(NSDictionary *headers) { // Response headers received. + NSLog(@"response received"); __strong GRPCCall *strongSelf = weakSelf; if (strongSelf) { strongSelf.responseHeaders = headers; @@ -784,6 +800,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } } completionHandler:^(NSError *error, NSDictionary *trailers) { + NSLog(@"completion received"); __strong GRPCCall *strongSelf = weakSelf; if (strongSelf) { strongSelf.responseTrailers = trailers; @@ -794,112 +811,113 @@ const char *kCFStreamVarName = "grpc_cfstream"; [userInfo addEntriesFromDictionary:error.userInfo]; } userInfo[kGRPCTrailersKey] = strongSelf.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 (strongSelf.responseHeaders) { - userInfo[kGRPCHeadersKey] = strongSelf.responseHeaders; - } + // Since gRPC core does not guarantee the headers block being called before this block, + // responseHeaders might be nil. + userInfo[kGRPCHeadersKey] = strongSelf.responseHeaders; error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo]; } - [strongSelf maybeFinishWithError:error]; + [strongSelf finishWithError:error]; } }]; - // Now that the RPC has been initiated, request writes can start. - @synchronized(_requestWriter) { - [_requestWriter startWithWriteable:self]; - } } #pragma mark GRXWriter implementation +// Lock acquired inside startWithWriteable: - (void)startCallWithWriteable:(id)writeable { - _responseWriteable = - [[GRXConcurrentWriteable alloc] initWithWriteable:writeable dispatchQueue:_responseQueue]; - - GRPCPooledChannel *channel = - [[GRPCChannelPool sharedInstance] channelWithHost:_host callOptions:_callOptions]; - GRPCWrappedCall *wrappedCall = [channel wrappedCallWithPath:_path - completionQueue:[GRPCCompletionQueue completionQueue] - callOptions:_callOptions]; - - if (wrappedCall == nil) { - [self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeUnavailable - userInfo:@{ - NSLocalizedDescriptionKey : - @"Failed to create call or channel." - }]]; - return; - } + @synchronized (self) { + if (_state == GRXWriterStateFinished) { + return; + } - @synchronized(self) { - _wrappedCall = wrappedCall; - } + _responseWriteable = + [[GRXConcurrentWriteable alloc] initWithWriteable:writeable dispatchQueue:_responseQueue]; + + GRPCPooledChannel *channel = + [[GRPCChannelPool sharedInstance] channelWithHost:_host callOptions:_callOptions]; + _wrappedCall = [channel wrappedCallWithPath:_path + completionQueue:[GRPCCompletionQueue completionQueue] + callOptions:_callOptions]; - [self sendHeaders]; - [self invokeCall]; + if (_wrappedCall == nil) { + [self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeUnavailable + userInfo:@{ + NSLocalizedDescriptionKey : + @"Failed to create call or channel." + }]]; + return; + } - // Connectivity monitor is not required for CFStream - char *enableCFStream = getenv(kCFStreamVarName); - if (enableCFStream == nil || enableCFStream[0] != '1') { - [GRPCConnectivityMonitor registerObserver:self selector:@selector(connectivityChanged:)]; + [self sendHeaders]; + [self invokeCall]; + + // Connectivity monitor is not required for CFStream + char *enableCFStream = getenv(kCFStreamVarName); + if (enableCFStream == nil || enableCFStream[0] != '1') { + [GRPCConnectivityMonitor registerObserver:self selector:@selector(connectivityChanged:)]; + } } + + // Now that the RPC has been initiated, request writes can start. + [_requestWriter startWithWriteable:self]; } - (void)startWithWriteable:(id)writeable { + id tokenProvider = nil; @synchronized(self) { _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. - _retainSelf = self; + // 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; + + if (_callOptions == nil) { + GRPCMutableCallOptions *callOptions = [[GRPCHost callOptionsForHost:_host] mutableCopy]; + if (_serverName.length != 0) { + callOptions.serverAuthority = _serverName; + } + if (_timeout > 0) { + callOptions.timeout = _timeout; + } + uint32_t callFlags = [GRPCCall callFlagsForHost:_host path:_path]; + if (callFlags != 0) { + if (callFlags == GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) { + _callSafety = GRPCCallSafetyIdempotentRequest; + } else if (callFlags == GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) { + _callSafety = GRPCCallSafetyCacheableRequest; + } + } - if (_callOptions == nil) { - GRPCMutableCallOptions *callOptions = [[GRPCHost callOptionsForHost:_host] mutableCopy]; - if (_serverName.length != 0) { - callOptions.serverAuthority = _serverName; - } - if (_timeout > 0) { - callOptions.timeout = _timeout; - } - uint32_t callFlags = [GRPCCall callFlagsForHost:_host path:_path]; - if (callFlags != 0) { - if (callFlags == GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) { - _callSafety = GRPCCallSafetyIdempotentRequest; - } else if (callFlags == GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) { - _callSafety = GRPCCallSafetyCacheableRequest; + id tokenProvider = self.tokenProvider; + if (tokenProvider != nil) { + callOptions.authTokenProvider = tokenProvider; } + _callOptions = callOptions; } - id tokenProvider = self.tokenProvider; - if (tokenProvider != nil) { - callOptions.authTokenProvider = tokenProvider; - } - _callOptions = callOptions; + NSAssert(_callOptions.authTokenProvider == nil || _callOptions.oauth2AccessToken == nil, + @"authTokenProvider and oauth2AccessToken cannot be set at the same time"); + + tokenProvider = _callOptions.authTokenProvider; } - NSAssert(_callOptions.authTokenProvider == nil || _callOptions.oauth2AccessToken == nil, - @"authTokenProvider and oauth2AccessToken cannot be set at the same time"); - if (_callOptions.authTokenProvider != nil) { - @synchronized(self) { - self.isWaitingForToken = YES; - } - [_callOptions.authTokenProvider getTokenWithHandler:^(NSString *token) { - @synchronized(self) { - if (self.isWaitingForToken) { - if (token) { - self->_fetchedOauth2AccessToken = [token copy]; + if (tokenProvider != nil) { + __weak typeof(self) weakSelf = self; + [tokenProvider getTokenWithHandler:^(NSString *token) { + __strong typeof(self) strongSelf = weakSelf; + if (strongSelf) { + @synchronized(strongSelf) { + if (strongSelf->_state == GRXWriterStateNotStarted) { + if (token) { + strongSelf->_fetchedOauth2AccessToken = [token copy]; + } } - [self startCallWithWriteable:writeable]; - self.isWaitingForToken = NO; } + [strongSelf startCallWithWriteable:writeable]; } }]; } else { @@ -938,16 +956,20 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)connectivityChanged:(NSNotification *)note { - // Cancel underlying call upon this notification + // Cancel underlying call upon this notification. + + // Retain because connectivity manager only keeps weak reference to GRPCCall. __strong GRPCCall *strongSelf = self; if (strongSelf) { - [self cancelCall]; - [self - maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeUnavailable - userInfo:@{ - NSLocalizedDescriptionKey : @"Connectivity lost." - }]]; + @synchronized (strongSelf) { + [_wrappedCall cancel]; + [strongSelf + finishWithError:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeUnavailable + userInfo:@{ + NSLocalizedDescriptionKey : @"Connectivity lost." + }]]; + } } } diff --git a/src/objective-c/RxLibrary/GRXBufferedPipe.m b/src/objective-c/RxLibrary/GRXBufferedPipe.m index 546d46cba32..d0064a5cfaf 100644 --- a/src/objective-c/RxLibrary/GRXBufferedPipe.m +++ b/src/objective-c/RxLibrary/GRXBufferedPipe.m @@ -51,16 +51,22 @@ // We need a copy, so that it doesn't mutate before it's written at the other end of the pipe. value = [value copy]; } - __weak GRXBufferedPipe *weakSelf = self; dispatch_async(_writeQueue, ^(void) { - [weakSelf.writeable writeValue:value]; + @synchronized (self) { + if (self->_state == GRXWriterStateFinished) { + return; + } + [self.writeable writeValue:value]; + } }); } - (void)writesFinishedWithError:(NSError *)errorOrNil { - __weak GRXBufferedPipe *weakSelf = self; dispatch_async(_writeQueue, ^{ - [weakSelf finishWithError:errorOrNil]; + if (self->_state == GRXWriterStateFinished) { + return; + } + [self finishWithError:errorOrNil]; }); } @@ -100,14 +106,15 @@ } - (void)startWithWriteable:(id)writeable { - self.writeable = writeable; - _state = GRXWriterStateStarted; + @synchronized (self) { + self.writeable = writeable; + _state = GRXWriterStateStarted; + } dispatch_resume(_writeQueue); } - (void)finishWithError:(NSError *)errorOrNil { [self.writeable writesFinishedWithError:errorOrNil]; - self.state = GRXWriterStateFinished; } - (void)dealloc { diff --git a/src/objective-c/RxLibrary/GRXConcurrentWriteable.h b/src/objective-c/RxLibrary/GRXConcurrentWriteable.h index abb831e6fb4..606f5dea954 100644 --- a/src/objective-c/RxLibrary/GRXConcurrentWriteable.h +++ b/src/objective-c/RxLibrary/GRXConcurrentWriteable.h @@ -23,9 +23,9 @@ /** * This is a thread-safe wrapper over a GRXWriteable instance. It lets one enqueue calls to a - * GRXWriteable instance for the main thread, guaranteeing that writesFinishedWithError: is the last + * GRXWriteable instance for the thread user provided, guaranteeing that writesFinishedWithError: is the last * message sent to it (no matter what messages are sent to the wrapper, in what order, nor from - * which thread). It also guarantees that, if cancelWithError: is called from the main thread (e.g. + * which thread). It also guarantees that, if cancelWithError: is called (e.g. * by the app cancelling the writes), no further messages are sent to the writeable except * writesFinishedWithError:. * diff --git a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m index 81ccc3fbcea..229d592f484 100644 --- a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m +++ b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m @@ -41,6 +41,7 @@ if (self = [super init]) { _writeableQueue = queue; _writeable = writeable; + _alreadyFinished = NO; } return self; } @@ -51,78 +52,43 @@ - (void)enqueueValue:(id)value completionHandler:(void (^)(void))handler { dispatch_async(_writeableQueue, ^{ - // We're racing a possible cancellation performed by another thread. To turn all already- - // enqueued messages into noops, cancellation nillifies the writeable property. If we get it - // before it's nil, we won the race. - id writeable = self.writeable; - if (writeable) { - [writeable writeValue:value]; - handler(); + if (self->_alreadyFinished) { + return; } + + [self.writeable writeValue:value]; + handler(); }); } - (void)enqueueSuccessfulCompletion { - __weak typeof(self) weakSelf = self; dispatch_async(_writeableQueue, ^{ - typeof(self) strongSelf = weakSelf; - if (strongSelf) { - BOOL finished = NO; - @synchronized(strongSelf) { - if (!strongSelf->_alreadyFinished) { - strongSelf->_alreadyFinished = YES; - } else { - finished = YES; - } - } - if (!finished) { - // Cancellation is now impossible. None of the other three blocks can run concurrently with - // this one. - [strongSelf.writeable writesFinishedWithError:nil]; - // Skip any possible message to the wrapped writeable enqueued after this one. - strongSelf.writeable = nil; - } + if (self->_alreadyFinished) { + return; } + [self.writeable writesFinishedWithError:nil]; + // Skip any possible message to the wrapped writeable enqueued after this one. + self.writeable = nil; }); } - (void)cancelWithError:(NSError *)error { - NSAssert(error, @"For a successful completion, use enqueueSuccessfulCompletion."); - BOOL finished = NO; - @synchronized(self) { - if (!_alreadyFinished) { - _alreadyFinished = YES; - } else { - finished = YES; + NSAssert(error != nil, @"For a successful completion, use enqueueSuccessfulCompletion."); + dispatch_async(_writeableQueue, ^{ + if (self->_alreadyFinished) { + return; } - } - if (!finished) { - // Skip any of the still-enqueued messages to the wrapped writeable. We use the atomic setter to - // nillify writeable because we might be running concurrently with the blocks in - // _writeableQueue, and assignment with ARC isn't atomic. - id writeable = self.writeable; + [self.writeable writesFinishedWithError:error]; self.writeable = nil; - - dispatch_async(_writeableQueue, ^{ - [writeable writesFinishedWithError:error]; - }); - } + }); } - (void)cancelSilently { - BOOL finished = NO; - @synchronized(self) { - if (!_alreadyFinished) { - _alreadyFinished = YES; - } else { - finished = YES; + dispatch_async(_writeableQueue, ^{ + if (self->_alreadyFinished) { + return; } - } - if (!finished) { - // Skip any of the still-enqueued messages to the wrapped writeable. We use the atomic setter to - // nillify writeable because we might be running concurrently with the blocks in - // _writeableQueue, and assignment with ARC isn't atomic. self.writeable = nil; - } + }); } @end diff --git a/src/objective-c/RxLibrary/GRXForwardingWriter.m b/src/objective-c/RxLibrary/GRXForwardingWriter.m index 3e522ef24e0..376c196b4f3 100644 --- a/src/objective-c/RxLibrary/GRXForwardingWriter.m +++ b/src/objective-c/RxLibrary/GRXForwardingWriter.m @@ -54,23 +54,19 @@ [writeable writesFinishedWithError:errorOrNil]; } -// This is used to stop the input writer. It nillifies our reference to it -// to release it. -- (void)finishInput { - GRXWriter *writer = _writer; - _writer = nil; - writer.state = GRXWriterStateFinished; -} - #pragma mark GRXWriteable implementation - (void)writeValue:(id)value { - [_writeable writeValue:value]; + @synchronized (self) { + [_writeable writeValue:value]; + } } - (void)writesFinishedWithError:(NSError *)errorOrNil { - _writer = nil; - [self finishOutputWithError:errorOrNil]; + @synchronized (self) { + _writer = nil; + [self finishOutputWithError:errorOrNil]; + } } #pragma mark GRXWriter implementation @@ -80,22 +76,38 @@ } - (void)setState:(GRXWriterState)state { + GRXWriter *copiedWriter = nil; if (state == GRXWriterStateFinished) { - _writeable = nil; - [self finishInput]; + @synchronized (self) { + _writeable = nil; + copiedWriter = _writer; + _writer = nil; + } + copiedWriter.state = GRXWriterStateFinished; } else { - _writer.state = state; + @synchronized (self) { + copiedWriter = _writer; + } + copiedWriter.state = state; } } - (void)startWithWriteable:(id)writeable { - _writeable = writeable; - [_writer startWithWriteable:self]; + GRXWriter *copiedWriter = nil; + @synchronized (self) { + _writeable = writeable; + copiedWriter = _writer; + } + [copiedWriter startWithWriteable:self]; } - (void)finishWithError:(NSError *)errorOrNil { - [self finishOutputWithError:errorOrNil]; - [self finishInput]; + GRXWriter *copiedWriter = nil; + @synchronized (self) { + [self finishOutputWithError:errorOrNil]; + copiedWriter = _writer; + } + copiedWriter.state = GRXWriterStateFinished; } @end diff --git a/src/objective-c/RxLibrary/GRXImmediateSingleWriter.m b/src/objective-c/RxLibrary/GRXImmediateSingleWriter.m index 3126ae4bd16..eadad6c3b65 100644 --- a/src/objective-c/RxLibrary/GRXImmediateSingleWriter.m +++ b/src/objective-c/RxLibrary/GRXImmediateSingleWriter.m @@ -20,7 +20,6 @@ @implementation GRXImmediateSingleWriter { id _value; - id _writeable; } @synthesize state = _state; @@ -38,17 +37,16 @@ } - (void)startWithWriteable:(id)writeable { - _state = GRXWriterStateStarted; - _writeable = writeable; - [writeable writeValue:_value]; - [self finish]; -} - -- (void)finish { - _state = GRXWriterStateFinished; - _value = nil; - id writeable = _writeable; - _writeable = nil; + id copiedValue = nil; + @synchronized (self) { + if (_state != GRXWriterStateNotStarted) { + return; + } + copiedValue = _value; + _value = nil; + _state = GRXWriterStateFinished; + } + [writeable writeValue:copiedValue]; [writeable writesFinishedWithError:nil]; } @@ -65,9 +63,11 @@ // the original \a map function returns a new Writer of another type. So we // need to override this function here. - (GRXWriter *)map:(id (^)(id))map { - // Since _value is available when creating the object, we can simply - // apply the map and store the output. - _value = map(_value); + @synchronized (self) { + // Since _value is available when creating the object, we can simply + // apply the map and store the output. + _value = map(_value); + } return self; } diff --git a/src/objective-c/RxLibrary/GRXWriter.h b/src/objective-c/RxLibrary/GRXWriter.h index 5d99583a928..ac1f7b9c4cf 100644 --- a/src/objective-c/RxLibrary/GRXWriter.h +++ b/src/objective-c/RxLibrary/GRXWriter.h @@ -80,9 +80,9 @@ typedef NS_ENUM(NSInteger, GRXWriterState) { * This property can be used to query the current state of the writer, which determines how it might * currently use its writeable. Some state transitions can be triggered by setting this property to * the corresponding value, and that's useful for advanced use cases like pausing an writer. For - * more details, see the documentation of the enum further down. + * more details, see the documentation of the enum further down. The property is thread safe. */ -@property(nonatomic) GRXWriterState state; +@property(atomic) GRXWriterState state; /** * Transition to the Started state, and start sending messages to the writeable (a reference to it From 03232ba46fba25465341b5e9632344f102f9df83 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 21 Dec 2018 16:21:18 -0800 Subject: [PATCH 323/375] Polish comments and correct concurrent writeable behavior --- src/objective-c/RxLibrary/GRXBufferedPipe.h | 3 +-- .../RxLibrary/GRXConcurrentWriteable.h | 13 +++++++------ .../RxLibrary/GRXConcurrentWriteable.m | 18 +++++++++++++----- .../RxLibrary/GRXForwardingWriter.h | 6 +----- .../RxLibrary/GRXImmediateSingleWriter.h | 2 ++ 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/objective-c/RxLibrary/GRXBufferedPipe.h b/src/objective-c/RxLibrary/GRXBufferedPipe.h index a871ea895aa..ae08cc315bb 100644 --- a/src/objective-c/RxLibrary/GRXBufferedPipe.h +++ b/src/objective-c/RxLibrary/GRXBufferedPipe.h @@ -36,8 +36,7 @@ * crash. If you want to react to flow control signals to prevent that, instead of using this class * you can implement an object that conforms to GRXWriter. * - * Thread-safety: - * The methods of an object of this class should not be called concurrently from different threads. + * Thread-safety: the methods of this class are thread-safe. */ @interface GRXBufferedPipe : GRXWriter diff --git a/src/objective-c/RxLibrary/GRXConcurrentWriteable.h b/src/objective-c/RxLibrary/GRXConcurrentWriteable.h index 606f5dea954..55468b3c07a 100644 --- a/src/objective-c/RxLibrary/GRXConcurrentWriteable.h +++ b/src/objective-c/RxLibrary/GRXConcurrentWriteable.h @@ -43,21 +43,22 @@ - (instancetype)initWithWriteable:(id)writeable; /** - * Enqueues writeValue: to be sent to the writeable in the main thread. - * The passed handler is invoked from the main thread after writeValue: returns. + * Enqueues writeValue: to be sent to the writeable from the designated dispatch queue. + * The passed handler is invoked from designated dispatch queue after writeValue: returns. */ - (void)enqueueValue:(id)value completionHandler:(void (^)(void))handler; /** - * Enqueues writesFinishedWithError:nil to be sent to the writeable in the main thread. After that - * message is sent to the writeable, all other methods of this object are effectively noops. + * Enqueues writesFinishedWithError:nil to be sent to the writeable in the designated dispatch + * queue. After that message is sent to the writeable, all other methods of this object are + * effectively noops. */ - (void)enqueueSuccessfulCompletion; /** * If the writeable has not yet received a writesFinishedWithError: message, this will enqueue one - * to be sent to it in the main thread, and cancel all other pending messages to the writeable - * enqueued by this object (both past and future). + * to be sent to it in the designated dispatch queue, and cancel all other pending messages to the + * writeable enqueued by this object (both past and future). * The error argument cannot be nil. */ - (void)cancelWithError:(NSError *)error; diff --git a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m index 229d592f484..d9d0e8c31e4 100644 --- a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m +++ b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m @@ -63,8 +63,10 @@ - (void)enqueueSuccessfulCompletion { dispatch_async(_writeableQueue, ^{ - if (self->_alreadyFinished) { - return; + @synchronized (self) { + if (self->_alreadyFinished) { + return; + } } [self.writeable writesFinishedWithError:nil]; // Skip any possible message to the wrapped writeable enqueued after this one. @@ -74,10 +76,14 @@ - (void)cancelWithError:(NSError *)error { NSAssert(error != nil, @"For a successful completion, use enqueueSuccessfulCompletion."); - dispatch_async(_writeableQueue, ^{ + @synchronized (self) { if (self->_alreadyFinished) { return; } + } + dispatch_async(_writeableQueue, ^{ + // If enqueueSuccessfulCompletion is already issued, self.writeable is nil and the following + // line is no-op. [self.writeable writesFinishedWithError:error]; self.writeable = nil; }); @@ -85,8 +91,10 @@ - (void)cancelSilently { dispatch_async(_writeableQueue, ^{ - if (self->_alreadyFinished) { - return; + @synchronized (self) { + if (self->_alreadyFinished) { + return; + } } self.writeable = nil; }); diff --git a/src/objective-c/RxLibrary/GRXForwardingWriter.h b/src/objective-c/RxLibrary/GRXForwardingWriter.h index 3814ff8831c..00366b64162 100644 --- a/src/objective-c/RxLibrary/GRXForwardingWriter.h +++ b/src/objective-c/RxLibrary/GRXForwardingWriter.h @@ -25,11 +25,7 @@ * input writer, and for classes that represent objects with input and * output sequences of values, like an RPC. * - * Thread-safety: - * All messages sent to this object need to be serialized. When it is started, the writer it wraps - * is started in the same thread. Manual state changes are propagated to the wrapped writer in the - * same thread too. Importantly, all messages the wrapped writer sends to its writeable need to be - * serialized with any message sent to this object. + * Thread-safety: the methods of this class are thread safe. */ @interface GRXForwardingWriter : GRXWriter - (instancetype)initWithWriter:(GRXWriter *)writer NS_DESIGNATED_INITIALIZER; diff --git a/src/objective-c/RxLibrary/GRXImmediateSingleWriter.h b/src/objective-c/RxLibrary/GRXImmediateSingleWriter.h index 601abdc6b90..2fa38b3dcea 100644 --- a/src/objective-c/RxLibrary/GRXImmediateSingleWriter.h +++ b/src/objective-c/RxLibrary/GRXImmediateSingleWriter.h @@ -23,6 +23,8 @@ /** * Utility to construct GRXWriter instances from values that are immediately available when * required. + * + * Thread safety: the methods of this class are thread safe. */ @interface GRXImmediateSingleWriter : GRXImmediateWriter From 3cdc0db838626ab1d186a4980125bc3e6219c0e0 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 2 Jan 2019 15:59:19 -0800 Subject: [PATCH 324/375] clang-format --- src/objective-c/GRPCClient/GRPCCall.m | 77 ++++++++++--------- src/objective-c/RxLibrary/GRXBufferedPipe.m | 4 +- .../RxLibrary/GRXConcurrentWriteable.h | 8 +- .../RxLibrary/GRXConcurrentWriteable.m | 6 +- .../RxLibrary/GRXForwardingWriter.m | 12 +-- .../RxLibrary/GRXImmediateSingleWriter.m | 4 +- 6 files changed, 56 insertions(+), 55 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 5ea1755c589..c18dfae6351 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -448,7 +448,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; return; } NSString *hostAndPath = [NSString stringWithFormat:@"%@/%@", host, path]; - @synchronized (callFlags) { + @synchronized(callFlags) { switch (callSafety) { case GRPCCallSafetyDefault: callFlags[hostAndPath] = @0; @@ -468,7 +468,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; + (uint32_t)callFlagsForHost:(NSString *)host path:(NSString *)path { NSString *hostAndPath = [NSString stringWithFormat:@"%@/%@", host, path]; uint32_t flags = 0; - @synchronized (callFlags) { + @synchronized(callFlags) { flags = [callFlags[hostAndPath] intValue]; } return flags; @@ -529,7 +529,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)setResponseDispatchQueue:(dispatch_queue_t)queue { - @synchronized (self) { + @synchronized(self) { if (_state != GRXWriterStateNotStarted) { return; } @@ -562,14 +562,14 @@ const char *kCFStreamVarName = "grpc_cfstream"; } - (void)cancel { - @synchronized (self) { + @synchronized(self) { if (_state == GRXWriterStateFinished) { return; } [self finishWithError:[NSError - errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeCancelled - userInfo:@{NSLocalizedDescriptionKey : @"Canceled by app"}]]; + errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeCancelled + userInfo:@{NSLocalizedDescriptionKey : @"Canceled by app"}]]; [_wrappedCall cancel]; } } @@ -636,19 +636,19 @@ const char *kCFStreamVarName = "grpc_cfstream"; // 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. - @synchronized (strongSelf) { + @synchronized(strongSelf) { [strongSelf - finishWithError:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeResourceExhausted - userInfo:@{ - NSLocalizedDescriptionKey : - @"Client does not have enough memory to " - @"hold the server response." - }]]; + finishWithError:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeResourceExhausted + userInfo:@{ + NSLocalizedDescriptionKey : + @"Client does not have enough memory to " + @"hold the server response." + }]]; [strongSelf->_wrappedCall cancel]; } } else { - @synchronized (strongSelf) { + @synchronized(strongSelf) { [strongSelf->_responseWriteable enqueueValue:data completionHandler:^{ [strongSelf startNextRead]; @@ -689,9 +689,10 @@ const char *kCFStreamVarName = "grpc_cfstream"; } // TODO(jcanizales): Add error handlers for async failures - GRPCOpSendMetadata *op = [[GRPCOpSendMetadata alloc] initWithMetadata:headers - flags:callSafetyFlags - handler:nil]; // No clean-up needed after SEND_INITIAL_METADATA + GRPCOpSendMetadata *op = [[GRPCOpSendMetadata alloc] + initWithMetadata:headers + flags:callSafetyFlags + handler:nil]; // No clean-up needed after SEND_INITIAL_METADATA dispatch_async(_callQueue, ^{ if (!self->_unaryCall) { [self->_wrappedCall startBatchWithOperations:@[ op ]]; @@ -731,7 +732,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; - (void)writeValue:(id)value { NSAssert([value isKindOfClass:[NSData class]], @"value must be of type NSData"); - @synchronized (self) { + @synchronized(self) { if (_state == GRXWriterStateFinished) { return; } @@ -782,9 +783,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; dispatch_async(_callQueue, ^{ // TODO(jcanizales): Add error handlers for async failures [self->_wrappedCall - startBatchWithOperations:@[ [[GRPCOpRecvMetadata alloc] initWithHandler:headersHandler] ]]; + startBatchWithOperations:@[ [[GRPCOpRecvMetadata alloc] initWithHandler:headersHandler] ]]; [self->_wrappedCall - startBatchWithOperations:@[ [[GRPCOpRecvStatus alloc] initWithHandler:completionHandler] ]]; + startBatchWithOperations:@[ [[GRPCOpRecvStatus alloc] initWithHandler:completionHandler] ]]; }); } @@ -825,16 +826,16 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Lock acquired inside startWithWriteable: - (void)startCallWithWriteable:(id)writeable { - @synchronized (self) { + @synchronized(self) { if (_state == GRXWriterStateFinished) { return; } _responseWriteable = - [[GRXConcurrentWriteable alloc] initWithWriteable:writeable dispatchQueue:_responseQueue]; + [[GRXConcurrentWriteable alloc] initWithWriteable:writeable dispatchQueue:_responseQueue]; GRPCPooledChannel *channel = - [[GRPCChannelPool sharedInstance] channelWithHost:_host callOptions:_callOptions]; + [[GRPCChannelPool sharedInstance] channelWithHost:_host callOptions:_callOptions]; _wrappedCall = [channel wrappedCallWithPath:_path completionQueue:[GRPCCompletionQueue completionQueue] callOptions:_callOptions]; @@ -843,9 +844,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; [self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeUnavailable userInfo:@{ - NSLocalizedDescriptionKey : - @"Failed to create call or channel." - }]]; + NSLocalizedDescriptionKey : + @"Failed to create call or channel." + }]]; return; } @@ -869,10 +870,10 @@ const char *kCFStreamVarName = "grpc_cfstream"; _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. + // 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; if (_callOptions == nil) { @@ -961,14 +962,14 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Retain because connectivity manager only keeps weak reference to GRPCCall. __strong GRPCCall *strongSelf = self; if (strongSelf) { - @synchronized (strongSelf) { + @synchronized(strongSelf) { [_wrappedCall cancel]; [strongSelf - finishWithError:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeUnavailable - userInfo:@{ - NSLocalizedDescriptionKey : @"Connectivity lost." - }]]; + finishWithError:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeUnavailable + userInfo:@{ + NSLocalizedDescriptionKey : @"Connectivity lost." + }]]; } } } diff --git a/src/objective-c/RxLibrary/GRXBufferedPipe.m b/src/objective-c/RxLibrary/GRXBufferedPipe.m index d0064a5cfaf..74e2f03da6c 100644 --- a/src/objective-c/RxLibrary/GRXBufferedPipe.m +++ b/src/objective-c/RxLibrary/GRXBufferedPipe.m @@ -52,7 +52,7 @@ value = [value copy]; } dispatch_async(_writeQueue, ^(void) { - @synchronized (self) { + @synchronized(self) { if (self->_state == GRXWriterStateFinished) { return; } @@ -106,7 +106,7 @@ } - (void)startWithWriteable:(id)writeable { - @synchronized (self) { + @synchronized(self) { self.writeable = writeable; _state = GRXWriterStateStarted; } diff --git a/src/objective-c/RxLibrary/GRXConcurrentWriteable.h b/src/objective-c/RxLibrary/GRXConcurrentWriteable.h index 55468b3c07a..5beca9d41e3 100644 --- a/src/objective-c/RxLibrary/GRXConcurrentWriteable.h +++ b/src/objective-c/RxLibrary/GRXConcurrentWriteable.h @@ -23,10 +23,10 @@ /** * This is a thread-safe wrapper over a GRXWriteable instance. It lets one enqueue calls to a - * GRXWriteable instance for the thread user provided, guaranteeing that writesFinishedWithError: is the last - * message sent to it (no matter what messages are sent to the wrapper, in what order, nor from - * which thread). It also guarantees that, if cancelWithError: is called (e.g. - * by the app cancelling the writes), no further messages are sent to the writeable except + * GRXWriteable instance for the thread user provided, guaranteeing that writesFinishedWithError: is + * the last message sent to it (no matter what messages are sent to the wrapper, in what order, nor + * from which thread). It also guarantees that, if cancelWithError: is called (e.g. by the app + * cancelling the writes), no further messages are sent to the writeable except * writesFinishedWithError:. * * TODO(jcanizales): Let the user specify another queue for the writeable callbacks. diff --git a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m index d9d0e8c31e4..e50cdf240d1 100644 --- a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m +++ b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m @@ -63,7 +63,7 @@ - (void)enqueueSuccessfulCompletion { dispatch_async(_writeableQueue, ^{ - @synchronized (self) { + @synchronized(self) { if (self->_alreadyFinished) { return; } @@ -76,7 +76,7 @@ - (void)cancelWithError:(NSError *)error { NSAssert(error != nil, @"For a successful completion, use enqueueSuccessfulCompletion."); - @synchronized (self) { + @synchronized(self) { if (self->_alreadyFinished) { return; } @@ -91,7 +91,7 @@ - (void)cancelSilently { dispatch_async(_writeableQueue, ^{ - @synchronized (self) { + @synchronized(self) { if (self->_alreadyFinished) { return; } diff --git a/src/objective-c/RxLibrary/GRXForwardingWriter.m b/src/objective-c/RxLibrary/GRXForwardingWriter.m index 376c196b4f3..f5ed603698d 100644 --- a/src/objective-c/RxLibrary/GRXForwardingWriter.m +++ b/src/objective-c/RxLibrary/GRXForwardingWriter.m @@ -57,13 +57,13 @@ #pragma mark GRXWriteable implementation - (void)writeValue:(id)value { - @synchronized (self) { + @synchronized(self) { [_writeable writeValue:value]; } } - (void)writesFinishedWithError:(NSError *)errorOrNil { - @synchronized (self) { + @synchronized(self) { _writer = nil; [self finishOutputWithError:errorOrNil]; } @@ -78,14 +78,14 @@ - (void)setState:(GRXWriterState)state { GRXWriter *copiedWriter = nil; if (state == GRXWriterStateFinished) { - @synchronized (self) { + @synchronized(self) { _writeable = nil; copiedWriter = _writer; _writer = nil; } copiedWriter.state = GRXWriterStateFinished; } else { - @synchronized (self) { + @synchronized(self) { copiedWriter = _writer; } copiedWriter.state = state; @@ -94,7 +94,7 @@ - (void)startWithWriteable:(id)writeable { GRXWriter *copiedWriter = nil; - @synchronized (self) { + @synchronized(self) { _writeable = writeable; copiedWriter = _writer; } @@ -103,7 +103,7 @@ - (void)finishWithError:(NSError *)errorOrNil { GRXWriter *copiedWriter = nil; - @synchronized (self) { + @synchronized(self) { [self finishOutputWithError:errorOrNil]; copiedWriter = _writer; } diff --git a/src/objective-c/RxLibrary/GRXImmediateSingleWriter.m b/src/objective-c/RxLibrary/GRXImmediateSingleWriter.m index eadad6c3b65..079c11b94fb 100644 --- a/src/objective-c/RxLibrary/GRXImmediateSingleWriter.m +++ b/src/objective-c/RxLibrary/GRXImmediateSingleWriter.m @@ -38,7 +38,7 @@ - (void)startWithWriteable:(id)writeable { id copiedValue = nil; - @synchronized (self) { + @synchronized(self) { if (_state != GRXWriterStateNotStarted) { return; } @@ -63,7 +63,7 @@ // the original \a map function returns a new Writer of another type. So we // need to override this function here. - (GRXWriter *)map:(id (^)(id))map { - @synchronized (self) { + @synchronized(self) { // Since _value is available when creating the object, we can simply // apply the map and store the output. _value = map(_value); From 34d77aae5ec26063e2eb5dc4b47ba4dce90c7136 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 7 Jan 2019 14:12:03 -0800 Subject: [PATCH 325/375] Always nullify serializer to free memory --- include/grpcpp/impl/codegen/call_op_set.h | 2 +- include/grpcpp/impl/codegen/interceptor_common.h | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index 2c34082ebb1..880c62344b8 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -324,8 +324,8 @@ class CallOpSendMessage { } if (msg_ != nullptr) { GPR_CODEGEN_ASSERT(serializer_(msg_).ok()); - serializer_ = nullptr; } + serializer_ = nullptr; grpc_op* op = &ops[(*nops)++]; op->op = GRPC_OP_SEND_MESSAGE; op->flags = write_options_.flags(); diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index 33e46389b3d..09721343ffa 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -98,9 +98,7 @@ class InterceptorBatchMethodsImpl *orig_send_message_ = message; } - bool GetSendMessageStatus() override { - return !*fail_send_message_; - } + bool GetSendMessageStatus() override { return !*fail_send_message_; } std::multimap* GetSendInitialMetadata() override { return send_initial_metadata_; From d7650a841b8acac747b5a8d12502a46ec0e4a54c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 7 Jan 2019 16:51:08 -0800 Subject: [PATCH 326/375] Bug fix for GRXConcurrentWriter --- .../RxLibrary/GRXConcurrentWriteable.m | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m index e50cdf240d1..7cc2101a55f 100644 --- a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m +++ b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m @@ -27,8 +27,15 @@ @implementation GRXConcurrentWriteable { dispatch_queue_t _writeableQueue; - // This ensures that writesFinishedWithError: is only sent once to the writeable. + + // This ivar ensures that writesFinishedWithError: is only sent once to the writeable. Protected + // by _writeableQueue. BOOL _alreadyFinished; + + // This ivar ensures that a cancelWithError: call prevents further values to be sent to + // self.writeable. It must support manipulation outside of _writeableQueue and thus needs to be + // protected by self lock. + BOOL _cancelled; } - (instancetype)init { @@ -42,6 +49,7 @@ _writeableQueue = queue; _writeable = writeable; _alreadyFinished = NO; + _cancelled = NO; } return self; } @@ -56,6 +64,12 @@ return; } + @synchronized (self) { + if (self->_cancelled) { + return; + } + } + [self.writeable writeValue:value]; handler(); }); @@ -63,13 +77,18 @@ - (void)enqueueSuccessfulCompletion { dispatch_async(_writeableQueue, ^{ - @synchronized(self) { - if (self->_alreadyFinished) { + if (self->_alreadyFinished) { + return; + } + @synchronized (self) { + if (self->_cancelled) { return; } } [self.writeable writesFinishedWithError:nil]; + // Skip any possible message to the wrapped writeable enqueued after this one. + self->_alreadyFinished = YES; self.writeable = nil; }); } @@ -77,14 +96,17 @@ - (void)cancelWithError:(NSError *)error { NSAssert(error != nil, @"For a successful completion, use enqueueSuccessfulCompletion."); @synchronized(self) { + self->_cancelled = YES; + } + dispatch_async(_writeableQueue, ^{ if (self->_alreadyFinished) { + // a cancel or a successful completion is already issued return; } - } - dispatch_async(_writeableQueue, ^{ - // If enqueueSuccessfulCompletion is already issued, self.writeable is nil and the following - // line is no-op. [self.writeable writesFinishedWithError:error]; + + // Skip any possible message to the wrapped writeable enqueued after this one. + self->_alreadyFinished = YES; self.writeable = nil; }); } From cf303c3ee7d4b4364650ca6fdecbaafdca117497 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 7 Jan 2019 16:51:23 -0800 Subject: [PATCH 327/375] Deadlock fix for GRPCCall --- src/objective-c/GRPCClient/GRPCCall.m | 47 ++++++++++----------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index c18dfae6351..714c7dbbc26 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -539,26 +539,24 @@ const char *kCFStreamVarName = "grpc_cfstream"; #pragma mark Finish +// This function should support being called within a @synchronized(self) block in another function +// Should not manipulate _requestWriter for deadlock prevention. - (void)finishWithError:(NSError *)errorOrNil { - GRXConcurrentWriteable *copiedResponseWriteable = nil; - @synchronized(self) { if (_state == GRXWriterStateFinished) { return; } _state = GRXWriterStateFinished; - copiedResponseWriteable = _responseWriteable; + + if (errorOrNil) { + [_responseWriteable cancelWithError:errorOrNil]; + } else { + [_responseWriteable enqueueSuccessfulCompletion]; + } // If the call isn't retained anywhere else, it can be deallocated now. _retainSelf = nil; } - - if (errorOrNil) { - [copiedResponseWriteable cancelWithError:errorOrNil]; - } else { - [copiedResponseWriteable enqueueSuccessfulCompletion]; - } - _requestWriter.state = GRXWriterStateFinished; } - (void)cancel { @@ -572,19 +570,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; userInfo:@{NSLocalizedDescriptionKey : @"Canceled by app"}]]; [_wrappedCall cancel]; } -} - -- (void)maybeFinishWithError:(NSError *)errorOrNil { - BOOL toFinish = NO; - @synchronized(self) { - if (_finished == NO) { - _finished = YES; - toFinish = YES; - } - } - if (toFinish == YES) { - [self finishWithError:errorOrNil]; - } + _requestWriter.state = GRXWriterStateFinished; } - (void)dealloc { @@ -647,6 +633,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; }]]; [strongSelf->_wrappedCall cancel]; } + strongSelf->_requestWriter.state = GRXWriterStateFinished; } else { @synchronized(strongSelf) { [strongSelf->_responseWriteable enqueueValue:data @@ -818,6 +805,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo]; } [strongSelf finishWithError:error]; + strongSelf->_requestWriter.state = GRXWriterStateFinished; } }]; } @@ -841,12 +829,12 @@ const char *kCFStreamVarName = "grpc_cfstream"; callOptions:_callOptions]; if (_wrappedCall == nil) { - [self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain - code:GRPCErrorCodeUnavailable - userInfo:@{ - NSLocalizedDescriptionKey : - @"Failed to create call or channel." - }]]; + [self finishWithError:[NSError errorWithDomain:kGRPCErrorDomain + code:GRPCErrorCodeUnavailable + userInfo:@{ + NSLocalizedDescriptionKey : + @"Failed to create call or channel." + }]]; return; } @@ -971,6 +959,7 @@ const char *kCFStreamVarName = "grpc_cfstream"; NSLocalizedDescriptionKey : @"Connectivity lost." }]]; } + strongSelf->_requestWriter.state = GRXWriterStateFinished; } } From 8b55c6a8714e7c4422adc8e7e105588397b707ba Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 7 Jan 2019 16:54:37 -0800 Subject: [PATCH 328/375] clang-format --- src/objective-c/GRPCClient/GRPCCall.m | 6 +++--- src/objective-c/RxLibrary/GRXConcurrentWriteable.m | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 714c7dbbc26..20703f548e4 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -832,9 +832,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; [self finishWithError:[NSError errorWithDomain:kGRPCErrorDomain code:GRPCErrorCodeUnavailable userInfo:@{ - NSLocalizedDescriptionKey : - @"Failed to create call or channel." - }]]; + NSLocalizedDescriptionKey : + @"Failed to create call or channel." + }]]; return; } diff --git a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m index 7cc2101a55f..d8491d2aed5 100644 --- a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m +++ b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m @@ -64,10 +64,10 @@ return; } - @synchronized (self) { - if (self->_cancelled) { - return; - } + @synchronized(self) { + if (self->_cancelled) { + return; + } } [self.writeable writeValue:value]; @@ -80,7 +80,7 @@ if (self->_alreadyFinished) { return; } - @synchronized (self) { + @synchronized(self) { if (self->_cancelled) { return; } From b35b449166e1c18c180701725b8ba97ab98994e0 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 7 Jan 2019 17:17:01 -0800 Subject: [PATCH 329/375] Update docs according to #17630 --- include/grpcpp/impl/codegen/call_op_set.h | 3 ++- include/grpcpp/impl/codegen/interceptor.h | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index 880c62344b8..c0de5ed6025 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -400,8 +400,9 @@ Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) { }; // Serialize immediately only if we do not have access to the message pointer if (msg_ == nullptr) { - return serializer_(&message); + Status result = serializer_(&message); serializer_ = nullptr; + return result; } return Status(); } diff --git a/include/grpcpp/impl/codegen/interceptor.h b/include/grpcpp/impl/codegen/interceptor.h index d749d8578ae..5dea796a3b7 100644 --- a/include/grpcpp/impl/codegen/interceptor.h +++ b/include/grpcpp/impl/codegen/interceptor.h @@ -112,12 +112,17 @@ class InterceptorBatchMethods { /// A return value of nullptr indicates that this ByteBuffer is not valid. virtual ByteBuffer* GetSerializedSendMessage() = 0; - /// Returns a non-modifiable pointer to the original non-serialized form of - /// the message. Valid for PRE_SEND_MESSAGE interceptions. A return value of + /// Returns a non-modifiable pointer to the non-serialized form of the message + /// to be sent. Valid for PRE_SEND_MESSAGE interceptions. A return value of /// nullptr indicates that this field is not valid. Also note that this is /// only supported for sync and callback APIs at the present moment. virtual const void* GetSendMessage() = 0; + /// Overwrites the message to be sent with \a message. \a message should be in + /// the non-serialized form expected by the method. Valid for PRE_SEND_MESSAGE + /// interceptions. Note that the interceptor is responsible for maintaining + /// the life of the message for the duration on the send operation, i.e., till + /// POST_SEND_MESSAGE. virtual void ModifySendMessage(const void* message) = 0; /// Checks whether the SEND MESSAGE op succeeded. Valid for POST_SEND_MESSAGE From 361acdbed1805dd9f313deb4bc92dbd5e8612a7b Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 7 Jan 2019 17:33:16 -0800 Subject: [PATCH 330/375] Use the WriteOptions in Client Callback API --- include/grpcpp/impl/codegen/client_callback.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/grpcpp/impl/codegen/client_callback.h b/include/grpcpp/impl/codegen/client_callback.h index c20e8458106..52bcea99706 100644 --- a/include/grpcpp/impl/codegen/client_callback.h +++ b/include/grpcpp/impl/codegen/client_callback.h @@ -340,13 +340,13 @@ class ClientCallbackReaderWriterImpl context_->initial_metadata_flags()); start_corked_ = false; } - // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg).ok()); if (options.is_last_message()) { options.set_buffer_hint(); write_ops_.ClientSendClose(); } + // TODO(vjpai): don't assert + GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg, options).ok()); callbacks_outstanding_++; if (started_) { call_.PerformOps(&write_ops_); @@ -649,13 +649,13 @@ class ClientCallbackWriterImpl context_->initial_metadata_flags()); start_corked_ = false; } - // TODO(vjpai): don't assert - GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg).ok()); if (options.is_last_message()) { options.set_buffer_hint(); write_ops_.ClientSendClose(); } + // TODO(vjpai): don't assert + GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg, options).ok()); callbacks_outstanding_++; if (started_) { call_.PerformOps(&write_ops_); From 832e5f06c305b88d3ac662fd19f2c1985e664403 Mon Sep 17 00:00:00 2001 From: Christopher Warrington Date: Mon, 7 Jan 2019 17:30:46 -0800 Subject: [PATCH 331/375] Fix typos in comments --- include/grpc/impl/codegen/grpc_types.h | 2 +- src/ruby/ext/grpc/rb_channel.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index 610548b5f36..5d577eb8557 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -163,7 +163,7 @@ typedef struct { /** Maximum time that a channel may exist. Int valued, milliseconds. * INT_MAX means unlimited. */ #define GRPC_ARG_MAX_CONNECTION_AGE_MS "grpc.max_connection_age_ms" -/** Grace period after the chennel reaches its max age. Int valued, +/** Grace period after the channel reaches its max age. Int valued, milliseconds. INT_MAX means unlimited. */ #define GRPC_ARG_MAX_CONNECTION_AGE_GRACE_MS "grpc.max_connection_age_grace_ms" /** Enable/disable support for per-message compression. Defaults to 1, unless diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 6d4b2293a24..2e570b8e87c 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -153,7 +153,7 @@ static void grpc_rb_channel_free(void* p) { if (ch->bg_wrapped != NULL) { /* assumption made here: it's ok to directly gpr_mu_lock the global - * connection polling mutex becuse we're in a finalizer, + * connection polling mutex because we're in a finalizer, * and we can count on this thread to not be interrupted or * yield the gil. */ grpc_rb_channel_safe_destroy(ch->bg_wrapped); @@ -292,7 +292,7 @@ static void* get_state_without_gil(void* arg) { Indicates the current state of the channel, whose value is one of the constants defined in GRPC::Core::ConnectivityStates. - It also tries to connect if the chennel is idle in the second form. */ + It also tries to connect if the channel is idle in the second form. */ static VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE* argv, VALUE self) { VALUE try_to_connect_param = Qfalse; @@ -327,7 +327,7 @@ static void* wait_for_watch_state_op_complete_without_gvl(void* arg) { void* success = (void*)0; gpr_mu_lock(&global_connection_polling_mu); - // its unsafe to do a "watch" after "channel polling abort" because the cq has + // it's unsafe to do a "watch" after "channel polling abort" because the cq has // been shut down. if (abort_channel_polling || stack->bg_wrapped->channel_destroyed) { gpr_mu_unlock(&global_connection_polling_mu); From 11eff929e24cae59ed21c2f3a0bde22a6dbe0d91 Mon Sep 17 00:00:00 2001 From: Guantao Liu Date: Mon, 7 Jan 2019 18:22:50 -0800 Subject: [PATCH 332/375] Avoid the thread jump in server callback APIs. Add a utility function in iomgr to check whether the caller thread is a worker for any background poller, and keep grpc combiner from offloading closures to the default executor if the current thread is a worker for any background poller. --- src/core/lib/iomgr/combiner.cc | 9 ++++++++- src/core/lib/iomgr/ev_epoll1_linux.cc | 3 +++ src/core/lib/iomgr/ev_epollex_linux.cc | 3 +++ src/core/lib/iomgr/ev_poll_posix.cc | 3 +++ src/core/lib/iomgr/ev_posix.cc | 4 ++++ src/core/lib/iomgr/ev_posix.h | 4 ++++ src/core/lib/iomgr/iomgr.cc | 4 ++++ src/core/lib/iomgr/iomgr.h | 3 +++ src/core/lib/iomgr/iomgr_custom.cc | 6 +++++- src/core/lib/iomgr/iomgr_internal.cc | 4 ++++ src/core/lib/iomgr/iomgr_internal.h | 4 ++++ src/core/lib/iomgr/iomgr_posix.cc | 7 ++++++- src/core/lib/iomgr/iomgr_posix_cfstream.cc | 7 ++++++- src/core/lib/iomgr/iomgr_windows.cc | 7 ++++++- test/cpp/microbenchmarks/bm_cq_multiple_threads.cc | 1 + 15 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/core/lib/iomgr/combiner.cc b/src/core/lib/iomgr/combiner.cc index 7c0062eb4ec..402f8904eae 100644 --- a/src/core/lib/iomgr/combiner.cc +++ b/src/core/lib/iomgr/combiner.cc @@ -29,6 +29,7 @@ #include "src/core/lib/debug/stats.h" #include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/profiling/timers.h" grpc_core::DebugOnlyTraceFlag grpc_combiner_trace(false, "combiner"); @@ -228,8 +229,14 @@ bool grpc_combiner_continue_exec_ctx() { grpc_core::ExecCtx::Get()->IsReadyToFinish(), lock->time_to_execute_final_list)); + // offload only if all the following conditions are true: + // 1. the combiner is contended and has more than one closure to execute + // 2. the current execution context needs to finish as soon as possible + // 3. the DEFAULT executor is threaded + // 4. the current thread is not a worker for any background poller if (contended && grpc_core::ExecCtx::Get()->IsReadyToFinish() && - grpc_executor_is_threaded()) { + grpc_executor_is_threaded() && + !grpc_iomgr_is_any_background_poller_thread()) { GPR_TIMER_MARK("offload_from_finished_exec_ctx", 0); // this execution context wants to move on: schedule remaining work to be // picked up on the executor diff --git a/src/core/lib/iomgr/ev_epoll1_linux.cc b/src/core/lib/iomgr/ev_epoll1_linux.cc index 4b8c891e9b0..9eb4c089d86 100644 --- a/src/core/lib/iomgr/ev_epoll1_linux.cc +++ b/src/core/lib/iomgr/ev_epoll1_linux.cc @@ -1242,6 +1242,8 @@ static void pollset_set_del_pollset_set(grpc_pollset_set* bag, * Event engine binding */ +static bool is_any_background_poller_thread(void) { return false; } + static void shutdown_background_closure(void) {} static void shutdown_engine(void) { @@ -1287,6 +1289,7 @@ static const grpc_event_engine_vtable vtable = { pollset_set_add_fd, pollset_set_del_fd, + is_any_background_poller_thread, shutdown_background_closure, shutdown_engine, }; diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index 7a4870db785..0a0891013af 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -1604,6 +1604,8 @@ static void pollset_set_del_pollset_set(grpc_pollset_set* bag, * Event engine binding */ +static bool is_any_background_poller_thread(void) { return false; } + static void shutdown_background_closure(void) {} static void shutdown_engine(void) { @@ -1644,6 +1646,7 @@ static const grpc_event_engine_vtable vtable = { pollset_set_add_fd, pollset_set_del_fd, + is_any_background_poller_thread, shutdown_background_closure, shutdown_engine, }; diff --git a/src/core/lib/iomgr/ev_poll_posix.cc b/src/core/lib/iomgr/ev_poll_posix.cc index 67cbfbbd021..c479206410b 100644 --- a/src/core/lib/iomgr/ev_poll_posix.cc +++ b/src/core/lib/iomgr/ev_poll_posix.cc @@ -1782,6 +1782,8 @@ static void global_cv_fd_table_shutdown() { * event engine binding */ +static bool is_any_background_poller_thread(void) { return false; } + static void shutdown_background_closure(void) {} static void shutdown_engine(void) { @@ -1828,6 +1830,7 @@ static const grpc_event_engine_vtable vtable = { pollset_set_add_fd, pollset_set_del_fd, + is_any_background_poller_thread, shutdown_background_closure, shutdown_engine, }; diff --git a/src/core/lib/iomgr/ev_posix.cc b/src/core/lib/iomgr/ev_posix.cc index 32d1b6c43ef..fb2e70eee49 100644 --- a/src/core/lib/iomgr/ev_posix.cc +++ b/src/core/lib/iomgr/ev_posix.cc @@ -399,6 +399,10 @@ void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd) { g_event_engine->pollset_set_del_fd(pollset_set, fd); } +bool grpc_is_any_background_poller_thread(void) { + return g_event_engine->is_any_background_poller_thread(); +} + void grpc_shutdown_background_closure(void) { g_event_engine->shutdown_background_closure(); } diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h index 812c7a0f0f8..94ac9fdba6f 100644 --- a/src/core/lib/iomgr/ev_posix.h +++ b/src/core/lib/iomgr/ev_posix.h @@ -80,6 +80,7 @@ typedef struct grpc_event_engine_vtable { void (*pollset_set_add_fd)(grpc_pollset_set* pollset_set, grpc_fd* fd); void (*pollset_set_del_fd)(grpc_pollset_set* pollset_set, grpc_fd* fd); + bool (*is_any_background_poller_thread)(void); void (*shutdown_background_closure)(void); void (*shutdown_engine)(void); } grpc_event_engine_vtable; @@ -181,6 +182,9 @@ void grpc_pollset_add_fd(grpc_pollset* pollset, struct grpc_fd* fd); void grpc_pollset_set_add_fd(grpc_pollset_set* pollset_set, grpc_fd* fd); void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd); +/* Returns true if the caller is a worker thread for any background poller. */ +bool grpc_is_any_background_poller_thread(); + /* Shut down all the closures registered in the background poller. */ void grpc_shutdown_background_closure(); diff --git a/src/core/lib/iomgr/iomgr.cc b/src/core/lib/iomgr/iomgr.cc index eb29973514f..a4921468578 100644 --- a/src/core/lib/iomgr/iomgr.cc +++ b/src/core/lib/iomgr/iomgr.cc @@ -161,6 +161,10 @@ void grpc_iomgr_shutdown_background_closure() { grpc_iomgr_platform_shutdown_background_closure(); } +bool grpc_iomgr_is_any_background_poller_thread() { + return grpc_iomgr_platform_is_any_background_poller_thread(); +} + void grpc_iomgr_register_object(grpc_iomgr_object* obj, const char* name) { obj->name = gpr_strdup(name); gpr_mu_lock(&g_mu); diff --git a/src/core/lib/iomgr/iomgr.h b/src/core/lib/iomgr/iomgr.h index 8ea9289e068..6261aa550c3 100644 --- a/src/core/lib/iomgr/iomgr.h +++ b/src/core/lib/iomgr/iomgr.h @@ -39,6 +39,9 @@ void grpc_iomgr_shutdown(); * background poller. */ void grpc_iomgr_shutdown_background_closure(); +/** Returns true if the caller is a worker thread for any background poller. */ +bool grpc_iomgr_is_any_background_poller_thread(); + /* Exposed only for testing */ size_t grpc_iomgr_count_objects_for_testing(); diff --git a/src/core/lib/iomgr/iomgr_custom.cc b/src/core/lib/iomgr/iomgr_custom.cc index 4b112c9097f..e1cd8f73104 100644 --- a/src/core/lib/iomgr/iomgr_custom.cc +++ b/src/core/lib/iomgr/iomgr_custom.cc @@ -41,10 +41,14 @@ static void iomgr_platform_init(void) { static void iomgr_platform_flush(void) {} static void iomgr_platform_shutdown(void) { grpc_pollset_global_shutdown(); } static void iomgr_platform_shutdown_background_closure(void) {} +static bool iomgr_platform_is_any_background_poller_thread(void) { + return false; +} static grpc_iomgr_platform_vtable vtable = { iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, - iomgr_platform_shutdown_background_closure}; + iomgr_platform_shutdown_background_closure, + iomgr_platform_is_any_background_poller_thread}; void grpc_custom_iomgr_init(grpc_socket_vtable* socket, grpc_custom_resolver_vtable* resolver, diff --git a/src/core/lib/iomgr/iomgr_internal.cc b/src/core/lib/iomgr/iomgr_internal.cc index b6c9211865d..e68b1cf5812 100644 --- a/src/core/lib/iomgr/iomgr_internal.cc +++ b/src/core/lib/iomgr/iomgr_internal.cc @@ -45,3 +45,7 @@ void grpc_iomgr_platform_shutdown() { iomgr_platform_vtable->shutdown(); } void grpc_iomgr_platform_shutdown_background_closure() { iomgr_platform_vtable->shutdown_background_closure(); } + +bool grpc_iomgr_platform_is_any_background_poller_thread() { + return iomgr_platform_vtable->is_any_background_poller_thread(); +} diff --git a/src/core/lib/iomgr/iomgr_internal.h b/src/core/lib/iomgr/iomgr_internal.h index bca7409907f..2250ad9a18c 100644 --- a/src/core/lib/iomgr/iomgr_internal.h +++ b/src/core/lib/iomgr/iomgr_internal.h @@ -36,6 +36,7 @@ typedef struct grpc_iomgr_platform_vtable { void (*flush)(void); void (*shutdown)(void); void (*shutdown_background_closure)(void); + bool (*is_any_background_poller_thread)(void); } grpc_iomgr_platform_vtable; void grpc_iomgr_register_object(grpc_iomgr_object* obj, const char* name); @@ -56,6 +57,9 @@ void grpc_iomgr_platform_shutdown(void); /** shut down all the closures registered in the background poller */ void grpc_iomgr_platform_shutdown_background_closure(void); +/** return true is the caller is a worker thread for any background poller */ +bool grpc_iomgr_platform_is_any_background_poller_thread(void); + bool grpc_iomgr_abort_on_leaks(void); #endif /* GRPC_CORE_LIB_IOMGR_IOMGR_INTERNAL_H */ diff --git a/src/core/lib/iomgr/iomgr_posix.cc b/src/core/lib/iomgr/iomgr_posix.cc index 9386adf060d..278c8de6886 100644 --- a/src/core/lib/iomgr/iomgr_posix.cc +++ b/src/core/lib/iomgr/iomgr_posix.cc @@ -55,9 +55,14 @@ static void iomgr_platform_shutdown_background_closure(void) { grpc_shutdown_background_closure(); } +static bool iomgr_platform_is_any_background_poller_thread(void) { + return grpc_is_any_background_poller_thread(); +} + static grpc_iomgr_platform_vtable vtable = { iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, - iomgr_platform_shutdown_background_closure}; + iomgr_platform_shutdown_background_closure, + iomgr_platform_is_any_background_poller_thread}; void grpc_set_default_iomgr_platform() { grpc_set_tcp_client_impl(&grpc_posix_tcp_client_vtable); diff --git a/src/core/lib/iomgr/iomgr_posix_cfstream.cc b/src/core/lib/iomgr/iomgr_posix_cfstream.cc index 552ef4309c8..462ac41fcde 100644 --- a/src/core/lib/iomgr/iomgr_posix_cfstream.cc +++ b/src/core/lib/iomgr/iomgr_posix_cfstream.cc @@ -58,9 +58,14 @@ static void iomgr_platform_shutdown_background_closure(void) { grpc_shutdown_background_closure(); } +static bool iomgr_platform_is_any_background_poller_thread(void) { + return grpc_is_any_background_poller_thread(); +} + static grpc_iomgr_platform_vtable vtable = { iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, - iomgr_platform_shutdown_background_closure}; + iomgr_platform_shutdown_background_closure, + iomgr_platform_is_any_background_poller_thread}; void grpc_set_default_iomgr_platform() { char* enable_cfstream = getenv(grpc_cfstream_env_var); diff --git a/src/core/lib/iomgr/iomgr_windows.cc b/src/core/lib/iomgr/iomgr_windows.cc index 24ef0dba7b4..0579e16aa76 100644 --- a/src/core/lib/iomgr/iomgr_windows.cc +++ b/src/core/lib/iomgr/iomgr_windows.cc @@ -73,9 +73,14 @@ static void iomgr_platform_shutdown(void) { static void iomgr_platform_shutdown_background_closure(void) {} +static bool iomgr_platform_is_any_background_poller_thread(void) { + return false; +} + static grpc_iomgr_platform_vtable vtable = { iomgr_platform_init, iomgr_platform_flush, iomgr_platform_shutdown, - iomgr_platform_shutdown_background_closure}; + iomgr_platform_shutdown_background_closure, + iomgr_platform_is_any_background_poller_thread}; void grpc_set_default_iomgr_platform() { grpc_set_tcp_client_impl(&grpc_windows_tcp_client_vtable); diff --git a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc index dca97c85b19..7aa197b5979 100644 --- a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc +++ b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc @@ -94,6 +94,7 @@ static const grpc_event_engine_vtable* init_engine_vtable(bool) { g_vtable.pollset_destroy = pollset_destroy; g_vtable.pollset_work = pollset_work; g_vtable.pollset_kick = pollset_kick; + g_vtable.is_any_background_poller_thread = [] { return false; }; g_vtable.shutdown_background_closure = [] {}; g_vtable.shutdown_engine = [] {}; From 5a6c984d3ab6084a092173a6c19eb52c5aae8414 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 8 Jan 2019 16:06:38 +0100 Subject: [PATCH 333/375] clang format code --- src/ruby/ext/grpc/rb_channel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 2e570b8e87c..5bde962f788 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -327,8 +327,8 @@ static void* wait_for_watch_state_op_complete_without_gvl(void* arg) { void* success = (void*)0; gpr_mu_lock(&global_connection_polling_mu); - // it's unsafe to do a "watch" after "channel polling abort" because the cq has - // been shut down. + // it's unsafe to do a "watch" after "channel polling abort" because the cq + // has been shut down. if (abort_channel_polling || stack->bg_wrapped->channel_destroyed) { gpr_mu_unlock(&global_connection_polling_mu); return (void*)0; From da4ab59b0d2e136ec82038cf5f0e3f2ec8fb19f5 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Tue, 8 Jan 2019 11:44:33 -0800 Subject: [PATCH 334/375] Remove state_watcher from subchannel --- src/core/ext/filters/client_channel/subchannel.cc | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 3abacf68aeb..dff213efc6b 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -64,18 +64,6 @@ #define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120 #define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2 -namespace { -struct state_watcher { - grpc_closure closure; - grpc_subchannel* subchannel; - grpc_connectivity_state connectivity_state; - grpc_connectivity_state last_connectivity_state; - grpc_core::OrphanablePtr health_check_client; - grpc_closure health_check_closure; - grpc_connectivity_state health_state; -}; -} // namespace - typedef struct external_state_watcher { grpc_subchannel* subchannel; grpc_pollset_set* pollset_set; From 0c4c2de427399fe260aeaa2140638825fa43f26b Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 8 Jan 2019 11:45:02 -0800 Subject: [PATCH 335/375] Clean up code --- src/objective-c/GRPCClient/GRPCCall.m | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 20703f548e4..bc48f1aa1b3 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -467,11 +467,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; + (uint32_t)callFlagsForHost:(NSString *)host path:(NSString *)path { NSString *hostAndPath = [NSString stringWithFormat:@"%@/%@", host, path]; - uint32_t flags = 0; @synchronized(callFlags) { - flags = [callFlags[hostAndPath] intValue]; + return [callFlags[hostAndPath] intValue]; } - return flags; } // Designated initializer From f52dd290e20ec57780255f90ed1f985ee7df63b8 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 8 Jan 2019 13:41:08 +0100 Subject: [PATCH 336/375] improve readme.md --- tools/interop_matrix/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/interop_matrix/README.md b/tools/interop_matrix/README.md index db84d9b454c..6676f5d470c 100644 --- a/tools/interop_matrix/README.md +++ b/tools/interop_matrix/README.md @@ -1,6 +1,6 @@ # Overview -This directory contains scripts that facilitate building and running gRPC tests for combinations of language/runtimes (known as matrix). +This directory contains scripts that facilitate building and running gRPC interoperability tests for combinations of language/runtimes (known as matrix). The setup builds gRPC docker images for each language/runtime and upload it to Google Container Registry (GCR). These images, encapsulating gRPC stack from specific releases/tag, are used to test version compatiblity between gRPC release versions. From 5aa166eb2d8f98d83b016581abc36321b821f29f Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 8 Jan 2019 13:44:13 +0100 Subject: [PATCH 337/375] interop_matrix: refactor LANG_RELEASE_MATRIX --- tools/interop_matrix/client_matrix.py | 654 +++++------------- tools/interop_matrix/create_matrix_images.py | 16 +- .../run_interop_matrix_tests.py | 7 +- 3 files changed, 196 insertions(+), 481 deletions(-) diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py index 4964fd61674..12051e70a0b 100644 --- a/tools/interop_matrix/client_matrix.py +++ b/tools/interop_matrix/client_matrix.py @@ -15,6 +15,8 @@ # Defines languages, runtimes and releases for backward compatibility testing +from collections import OrderedDict + def get_github_repo(lang): return { @@ -27,23 +29,16 @@ def get_github_repo(lang): def get_release_tags(lang): - return map(lambda r: get_release_tag_name(r), LANG_RELEASE_MATRIX[lang]) - - -def get_release_tag_name(release_info): - assert len(release_info.keys()) == 1 - return release_info.keys()[0] + """Returns list of known releases for given language.""" + return list(LANG_RELEASE_MATRIX[lang].keys()) def get_runtimes_for_lang_release(lang, release): """Get list of valid runtimes for given release of lang.""" runtimes_to_skip = [] - # see if any the lang release has "skip_runtime" annotation. - for release_info in LANG_RELEASE_MATRIX[lang]: - if get_release_tag_name(release_info) == release: - if release_info[release] is not None: - runtimes_to_skip = release_info[release].get('skip_runtime', []) - break + release_info = LANG_RELEASE_MATRIX[lang][release] + if release_info: + runtimes_to_skip = release_info.skip_runtime return [ runtime for runtime in LANG_RUNTIME_MATRIX[lang] if runtime not in runtimes_to_skip @@ -51,6 +46,9 @@ def get_runtimes_for_lang_release(lang, release): def should_build_docker_interop_image_from_release_tag(lang): + # All dockerfile definitions live in grpc/grpc repository. + # For language that have a separate repo, we need to use + # dockerfile definitions from head of grpc/grpc. if lang in ['go', 'java', 'node']: return False return True @@ -68,465 +66,183 @@ LANG_RUNTIME_MATRIX = { 'csharp': ['csharp', 'csharpcoreclr'], } + +class ReleaseInfo: + """Info about a single release of a language""" + + def __init__(self, patch=[], skip_runtime=[], testcases_file=None): + self.patch = patch + self.skip_runtime = skip_runtime + self.testcases_file = None + + # Dictionary of known releases for given language. LANG_RELEASE_MATRIX = { - 'cxx': [ - { - 'v1.0.1': None - }, - { - 'v1.1.4': None - }, - { - 'v1.2.5': None - }, - { - 'v1.3.9': None - }, - { - 'v1.4.2': None - }, - { - 'v1.6.6': None - }, - { - 'v1.7.2': None - }, - { - 'v1.8.0': None - }, - { - 'v1.9.1': None - }, - { - 'v1.10.1': None - }, - { - 'v1.11.1': None - }, - { - 'v1.12.0': None - }, - { - 'v1.13.0': None - }, - { - 'v1.14.1': None - }, - { - 'v1.15.0': None - }, - { - 'v1.16.0': None - }, - { - 'v1.17.1': None - }, - ], - 'go': [ - { - 'v1.0.5': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.2.1': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.3.0': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.4.2': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.5.2': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.6.0': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.7.4': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.8.2': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.9.2': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.10.1': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.11.3': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.12.2': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.13.0': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.14.0': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.15.0': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.16.0': { - 'skip_runtime': ['go1.11'] - } - }, - { - 'v1.17.0': { - 'skip_runtime': ['go1.7', 'go1.8'] - } - }, - ], - 'java': [ - { - 'v1.0.3': None - }, - { - 'v1.1.2': None - }, - { - 'v1.2.0': None - }, - { - 'v1.3.1': None - }, - { - 'v1.4.0': None - }, - { - 'v1.5.0': None - }, - { - 'v1.6.1': None - }, - { - 'v1.7.0': None - }, - { - 'v1.8.0': None - }, - { - 'v1.9.1': None - }, - { - 'v1.10.1': None - }, - { - 'v1.11.0': None - }, - { - 'v1.12.0': None - }, - { - 'v1.13.1': None - }, - { - 'v1.14.0': None - }, - { - 'v1.15.0': None - }, - { - 'v1.16.1': None - }, - { - 'v1.17.1': None - }, - ], - 'python': [ - { - 'v1.0.x': None - }, - { - 'v1.1.4': None - }, - { - 'v1.2.5': None - }, - { - 'v1.3.9': None - }, - { - 'v1.4.2': None - }, - { - 'v1.6.6': None - }, - { - 'v1.7.2': None - }, - { - 'v1.8.1': None # first python 1.8 release is 1.8.1 - }, - { - 'v1.9.1': None - }, - { - 'v1.10.1': None - }, - { - 'v1.11.1': None - }, - { - 'v1.12.0': None - }, - { - 'v1.13.0': None - }, - { - 'v1.14.1': None - }, - { - 'v1.15.0': None - }, - { - 'v1.16.0': None - }, - { - 'v1.17.1': None - }, - ], - 'node': [ - { - 'v1.0.1': None - }, - { - 'v1.1.4': None - }, - { - 'v1.2.5': None - }, - { - 'v1.3.9': None - }, - { - 'v1.4.2': None - }, - { - 'v1.6.6': None - }, + 'cxx': + OrderedDict([ + ('v1.0.1', ReleaseInfo()), + ('v1.1.4', ReleaseInfo()), + ('v1.2.5', ReleaseInfo()), + ('v1.3.9', ReleaseInfo()), + ('v1.4.2', ReleaseInfo()), + ('v1.6.6', ReleaseInfo()), + ('v1.7.2', ReleaseInfo()), + ('v1.8.0', ReleaseInfo()), + ('v1.9.1', ReleaseInfo()), + ('v1.10.1', ReleaseInfo()), + ('v1.11.1', ReleaseInfo()), + ('v1.12.0', ReleaseInfo()), + ('v1.13.0', ReleaseInfo()), + ('v1.14.1', ReleaseInfo()), + ('v1.15.0', ReleaseInfo()), + ('v1.16.0', ReleaseInfo()), + ('v1.17.1', ReleaseInfo()), + ]), + 'go': + OrderedDict([ + ('v1.0.5', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.2.1', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.3.0', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.4.2', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.5.2', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.6.0', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.7.4', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.8.2', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.9.2', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.10.1', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.11.3', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.12.2', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.13.0', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.14.0', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.15.0', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.16.0', ReleaseInfo(skip_runtime=['go1.11'])), + ('v1.17.0', ReleaseInfo(skip_runtime=['go1.7', 'go1.8'])), + ]), + 'java': + OrderedDict([ + ('v1.0.3', ReleaseInfo()), + ('v1.1.2', ReleaseInfo()), + ('v1.2.0', ReleaseInfo()), + ('v1.3.1', ReleaseInfo()), + ('v1.4.0', ReleaseInfo()), + ('v1.5.0', ReleaseInfo()), + ('v1.6.1', ReleaseInfo()), + ('v1.7.0', ReleaseInfo()), + ('v1.8.0', ReleaseInfo()), + ('v1.9.1', ReleaseInfo()), + ('v1.10.1', ReleaseInfo()), + ('v1.11.0', ReleaseInfo()), + ('v1.12.0', ReleaseInfo()), + ('v1.13.1', ReleaseInfo()), + ('v1.14.0', ReleaseInfo()), + ('v1.15.0', ReleaseInfo()), + ('v1.16.1', ReleaseInfo()), + ('v1.17.1', ReleaseInfo()), + ]), + 'python': + OrderedDict([ + ('v1.0.x', ReleaseInfo()), + ('v1.1.4', ReleaseInfo()), + ('v1.2.5', ReleaseInfo()), + ('v1.3.9', ReleaseInfo()), + ('v1.4.2', ReleaseInfo()), + ('v1.6.6', ReleaseInfo()), + ('v1.7.2', ReleaseInfo()), + ('v1.8.1', ReleaseInfo()), + ('v1.9.1', ReleaseInfo()), + ('v1.10.1', ReleaseInfo()), + ('v1.11.1', ReleaseInfo()), + ('v1.12.0', ReleaseInfo()), + ('v1.13.0', ReleaseInfo()), + ('v1.14.1', ReleaseInfo()), + ('v1.15.0', ReleaseInfo()), + ('v1.16.0', ReleaseInfo()), + ('v1.17.1', ReleaseInfo()), + ]), + 'node': + OrderedDict([ + ('v1.0.1', ReleaseInfo()), + ('v1.1.4', ReleaseInfo()), + ('v1.2.5', ReleaseInfo()), + ('v1.3.9', ReleaseInfo()), + ('v1.4.2', ReleaseInfo()), + ('v1.6.6', ReleaseInfo()), # TODO: https://github.com/grpc/grpc-node/issues/235. - #{ - # 'v1.7.2': None - #}, - { - 'v1.8.4': None - }, - { - 'v1.9.1': None - }, - { - 'v1.10.0': None - }, - { - 'v1.11.3': None - }, - { - 'v1.12.4': None - }, - ], - 'ruby': [ - { - 'v1.0.1': { - 'patch': [ - 'tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile', - 'tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh', - ] - } - }, - { - 'v1.1.4': None - }, - { - 'v1.2.5': None - }, - { - 'v1.3.9': None - }, - { - 'v1.4.2': None - }, - { - 'v1.6.6': None - }, - { - 'v1.7.2': None - }, - { - 'v1.8.0': None - }, - { - 'v1.9.1': None - }, - { - 'v1.10.1': None - }, - { - 'v1.11.1': None - }, - { - 'v1.12.0': None - }, - { - 'v1.13.0': None - }, - { - 'v1.14.1': None - }, - { - 'v1.15.0': None - }, - { - 'v1.16.0': None - }, - { - 'v1.17.1': None - }, - ], - 'php': [ - { - 'v1.0.1': None - }, - { - 'v1.1.4': None - }, - { - 'v1.2.5': None - }, - { - 'v1.3.9': None - }, - { - 'v1.4.2': None - }, - { - 'v1.6.6': None - }, - { - 'v1.7.2': None - }, - { - 'v1.8.0': None - }, - { - 'v1.9.1': None - }, - { - 'v1.10.1': None - }, - { - 'v1.11.1': None - }, - { - 'v1.12.0': None - }, - { - 'v1.13.0': None - }, - { - 'v1.14.1': None - }, - { - 'v1.15.0': None - }, - { - 'v1.16.0': None - }, - { - 'v1.17.1': None - }, - ], - 'csharp': [ - { - 'v1.0.1': { - 'patch': [ - 'tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile', - 'tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile', - ] - } - }, - { - 'v1.1.4': None - }, - { - 'v1.2.5': None - }, - { - 'v1.3.9': None - }, - { - 'v1.4.2': None - }, - { - 'v1.6.6': None - }, - { - 'v1.7.2': None - }, - { - 'v1.8.0': None - }, - { - 'v1.9.1': None - }, - { - 'v1.10.1': None - }, - { - 'v1.11.1': None - }, - { - 'v1.12.0': None - }, - { - 'v1.13.0': None - }, - { - 'v1.14.1': None - }, - { - 'v1.15.0': None - }, - { - 'v1.16.0': None - }, - { - 'v1.17.1': None - }, - ], + # ('v1.7.2', ReleaseInfo()), + ('v1.8.4', ReleaseInfo()), + ('v1.9.1', ReleaseInfo()), + ('v1.10.0', ReleaseInfo()), + ('v1.11.3', ReleaseInfo()), + ('v1.12.4', ReleaseInfo()), + ]), + 'ruby': + OrderedDict([ + ('v1.0.1', + ReleaseInfo(patch=[ + 'tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile', + 'tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh', + ])), + ('v1.1.4', ReleaseInfo()), + ('v1.2.5', ReleaseInfo()), + ('v1.3.9', ReleaseInfo()), + ('v1.4.2', ReleaseInfo()), + ('v1.6.6', ReleaseInfo()), + ('v1.7.2', ReleaseInfo()), + ('v1.8.0', ReleaseInfo()), + ('v1.9.1', ReleaseInfo()), + ('v1.10.1', ReleaseInfo()), + ('v1.11.1', ReleaseInfo()), + ('v1.12.0', ReleaseInfo()), + ('v1.13.0', ReleaseInfo()), + ('v1.14.1', ReleaseInfo()), + ('v1.15.0', ReleaseInfo()), + ('v1.16.0', ReleaseInfo()), + ('v1.17.1', ReleaseInfo()), + ]), + 'php': + OrderedDict([ + ('v1.0.1', ReleaseInfo()), + ('v1.1.4', ReleaseInfo()), + ('v1.2.5', ReleaseInfo()), + ('v1.3.9', ReleaseInfo()), + ('v1.4.2', ReleaseInfo()), + ('v1.6.6', ReleaseInfo()), + ('v1.7.2', ReleaseInfo()), + ('v1.8.0', ReleaseInfo()), + ('v1.9.1', ReleaseInfo()), + ('v1.10.1', ReleaseInfo()), + ('v1.11.1', ReleaseInfo()), + ('v1.12.0', ReleaseInfo()), + ('v1.13.0', ReleaseInfo()), + ('v1.14.1', ReleaseInfo()), + ('v1.15.0', ReleaseInfo()), + ('v1.16.0', ReleaseInfo()), + ('v1.17.1', ReleaseInfo()), + ]), + 'csharp': + OrderedDict([ + ('v1.0.1', + ReleaseInfo(patch=[ + 'tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile', + 'tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile', + ])), + ('v1.1.4', ReleaseInfo()), + ('v1.2.5', ReleaseInfo()), + ('v1.3.9', ReleaseInfo()), + ('v1.4.2', ReleaseInfo()), + ('v1.6.6', ReleaseInfo()), + ('v1.7.2', ReleaseInfo()), + ('v1.8.0', ReleaseInfo()), + ('v1.9.1', ReleaseInfo()), + ('v1.10.1', ReleaseInfo()), + ('v1.11.1', ReleaseInfo()), + ('v1.12.0', ReleaseInfo()), + ('v1.13.0', ReleaseInfo()), + ('v1.14.1', ReleaseInfo()), + ('v1.15.0', ReleaseInfo()), + ('v1.16.0', ReleaseInfo()), + ('v1.17.1', ReleaseInfo()), + ]), } # This matrix lists the version of testcases to use for a release. As new @@ -535,6 +251,8 @@ LANG_RELEASE_MATRIX = { # particular version in some cases. If not specified, xxx__master file will be # used. For example, all java versions will run the commands in java__master. # The testcases files exist under the testcases directory. +# TODO(jtattermusch): make this data part of LANG_RELEASE_MATRIX, +# there is no reason for this to be a separate data structure. TESTCASES_VERSION_MATRIX = { 'node_v1.0.1': 'node__v1.0.1', 'node_v1.1.4': 'node__v1.1.4', diff --git a/tools/interop_matrix/create_matrix_images.py b/tools/interop_matrix/create_matrix_images.py index cf61d462482..31a0e1c7ba6 100755 --- a/tools/interop_matrix/create_matrix_images.py +++ b/tools/interop_matrix/create_matrix_images.py @@ -39,10 +39,9 @@ _LANGUAGES = client_matrix.LANG_RUNTIME_MATRIX.keys() # All gRPC release tags, flattened, deduped and sorted. _RELEASES = sorted( list( - set( - client_matrix.get_release_tag_name(info) - for lang in client_matrix.LANG_RELEASE_MATRIX.values() - for info in lang))) + set(release + for release_dict in client_matrix.LANG_RELEASE_MATRIX.values() + for release in release_dict.keys()))) # Destination directory inside docker image to keep extra info from build time. _BUILD_INFO = '/var/local/build_info' @@ -260,11 +259,10 @@ atexit.register(cleanup) def maybe_apply_patches_on_git_tag(stack_base, lang, release): files_to_patch = [] - for release_info in client_matrix.LANG_RELEASE_MATRIX[lang]: - if client_matrix.get_release_tag_name(release_info) == release: - if release_info[release] is not None: - files_to_patch = release_info[release].get('patch') - break + + release_info = client_matrix.LANG_RELEASE_MATRIX[lang][release] + if release_info: + files_to_patch = release_info.patch if not files_to_patch: return patch_file_relative_path = 'patches/%s_%s/git_repo.patch' % (lang, release) diff --git a/tools/interop_matrix/run_interop_matrix_tests.py b/tools/interop_matrix/run_interop_matrix_tests.py index dabb4865237..c855de3b1e8 100755 --- a/tools/interop_matrix/run_interop_matrix_tests.py +++ b/tools/interop_matrix/run_interop_matrix_tests.py @@ -44,10 +44,9 @@ _LANGUAGES = client_matrix.LANG_RUNTIME_MATRIX.keys() # All gRPC release tags, flattened, deduped and sorted. _RELEASES = sorted( list( - set( - client_matrix.get_release_tag_name(info) - for lang in client_matrix.LANG_RELEASE_MATRIX.values() - for info in lang))) + set(release + for release_dict in client_matrix.LANG_RELEASE_MATRIX.values() + for release in release_dict.keys()))) argp = argparse.ArgumentParser(description='Run interop tests.') argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int) From 1287cd34eacbc5597bb6c2cdbf7f8d1e8a426509 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 8 Jan 2019 21:10:34 +0100 Subject: [PATCH 338/375] make tcp_server_posix_test pass on foundry --- test/core/iomgr/tcp_server_posix_test.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/core/iomgr/tcp_server_posix_test.cc b/test/core/iomgr/tcp_server_posix_test.cc index 2c66cdec77f..81e26b20cd8 100644 --- a/test/core/iomgr/tcp_server_posix_test.cc +++ b/test/core/iomgr/tcp_server_posix_test.cc @@ -439,6 +439,11 @@ int main(int argc, char** argv) { static_cast(gpr_zalloc(sizeof(*dst_addrs))); grpc::testing::TestEnvironment env(argc, argv); grpc_init(); + // wait a few seconds to make sure IPv6 link-local addresses can be bound + // if we are running under docker container that has just started. + // See https://github.com/moby/moby/issues/38491 + // See https://github.com/grpc/grpc/issues/15610 + gpr_sleep_until(grpc_timeout_seconds_to_deadline(4)); { grpc_core::ExecCtx exec_ctx; g_pollset = static_cast(gpr_zalloc(grpc_pollset_size())); From 7850704d644e41c03ee41a7b6a7aad24b75e4a1d Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 8 Jan 2019 21:14:00 +0100 Subject: [PATCH 339/375] reenable tcp_server_posix_test on Foundry --- test/core/iomgr/BUILD | 1 - 1 file changed, 1 deletion(-) diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index e920ceacf00..fa59f215887 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -237,7 +237,6 @@ grpc_cc_test( name = "tcp_server_posix_test", srcs = ["tcp_server_posix_test.cc"], language = "C++", - tags = ["manual"], # TODO(adelez): Remove once this works on Foundry. deps = [ "//:gpr", "//:grpc", From 46a872864cfa3b3e81bbb650d6fd01e8a775c1b5 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Fri, 12 Oct 2018 11:56:29 -0700 Subject: [PATCH 340/375] Turn on c-ares as the default resolver --- .../resolver/dns/c_ares/dns_resolver_ares.cc | 2 +- .../cpp/naming/resolver_component_tests_defs.include | 1 - .../client_channel/resolvers/dns_resolver_test.cc | 11 +++++++---- test/cpp/naming/resolver_component_tests_runner.py | 1 - 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index abacd0c960d..fba20000ef6 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -472,7 +472,7 @@ static grpc_address_resolver_vtable ares_resolver = { grpc_resolve_address_ares, blocking_resolve_address_ares}; static bool should_use_ares(const char* resolver_env) { - return resolver_env != nullptr && gpr_stricmp(resolver_env, "ares") == 0; + return resolver_env == nullptr || gpr_stricmp(resolver_env, "ares") == 0; } void grpc_resolver_dns_ares_init() { diff --git a/templates/test/cpp/naming/resolver_component_tests_defs.include b/templates/test/cpp/naming/resolver_component_tests_defs.include index b34845e01a3..d38316cbe68 100644 --- a/templates/test/cpp/naming/resolver_component_tests_defs.include +++ b/templates/test/cpp/naming/resolver_component_tests_defs.include @@ -55,7 +55,6 @@ if cur_resolver and cur_resolver != 'ares': 'needs to use GRPC_DNS_RESOLVER=ares.')) test_runner_log('Exit 1 without running tests.') sys.exit(1) -os.environ.update({'GRPC_DNS_RESOLVER': 'ares'}) os.environ.update({'GRPC_TRACE': 'cares_resolver'}) def wait_until_dns_server_is_up(args, diff --git a/test/core/client_channel/resolvers/dns_resolver_test.cc b/test/core/client_channel/resolvers/dns_resolver_test.cc index 571746abe86..6f153cc9bf6 100644 --- a/test/core/client_channel/resolvers/dns_resolver_test.cc +++ b/test/core/client_channel/resolvers/dns_resolver_test.cc @@ -22,6 +22,8 @@ #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/combiner.h" #include "test/core/util/test_config.h" @@ -72,12 +74,13 @@ int main(int argc, char** argv) { test_succeeds(dns, "dns:10.2.1.1:1234"); test_succeeds(dns, "dns:www.google.com"); test_succeeds(dns, "dns:///www.google.com"); - if (grpc_resolve_address == grpc_resolve_address_ares) { - test_succeeds(dns, "dns://8.8.8.8/8.8.8.8:8888"); - } else { + char* resolver_env = gpr_getenv("GRPC_DNS_RESOLVER"); + if (resolver_env != nullptr && gpr_stricmp(resolver_env, "native") == 0) { test_fails(dns, "dns://8.8.8.8/8.8.8.8:8888"); + } else { + test_succeeds(dns, "dns://8.8.8.8/8.8.8.8:8888"); } - + gpr_free(resolver_env); { grpc_core::ExecCtx exec_ctx; GRPC_COMBINER_UNREF(g_combiner, "test"); diff --git a/test/cpp/naming/resolver_component_tests_runner.py b/test/cpp/naming/resolver_component_tests_runner.py index 1873eec35bd..950a9d4897e 100755 --- a/test/cpp/naming/resolver_component_tests_runner.py +++ b/test/cpp/naming/resolver_component_tests_runner.py @@ -55,7 +55,6 @@ if cur_resolver and cur_resolver != 'ares': 'needs to use GRPC_DNS_RESOLVER=ares.')) test_runner_log('Exit 1 without running tests.') sys.exit(1) -os.environ.update({'GRPC_DNS_RESOLVER': 'ares'}) os.environ.update({'GRPC_TRACE': 'cares_resolver'}) def wait_until_dns_server_is_up(args, From 0ec937207431a8512e3820d2da808693e2a21a48 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Mon, 17 Dec 2018 13:32:57 -0800 Subject: [PATCH 341/375] Multiple test timeout 5x --- test/core/surface/concurrent_connectivity_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core/surface/concurrent_connectivity_test.cc b/test/core/surface/concurrent_connectivity_test.cc index f606e89ac8d..b201568f482 100644 --- a/test/core/surface/concurrent_connectivity_test.cc +++ b/test/core/surface/concurrent_connectivity_test.cc @@ -44,7 +44,7 @@ #define NUM_OUTER_LOOPS 10 #define NUM_INNER_LOOPS 10 #define DELAY_MILLIS 10 -#define POLL_MILLIS 3000 +#define POLL_MILLIS 15000 #define NUM_OUTER_LOOPS_SHORT_TIMEOUTS 10 #define NUM_INNER_LOOPS_SHORT_TIMEOUTS 100 From 23677bd827f6e749b4a3e2bec73eea40dece565e Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Tue, 8 Jan 2019 17:41:23 -0800 Subject: [PATCH 342/375] Remove subchannel args --- .../client_channel/client_channel_factory.cc | 2 +- .../client_channel/client_channel_factory.h | 4 +- .../lb_policy/subchannel_list.h | 5 +-- .../ext/filters/client_channel/subchannel.cc | 11 +++-- .../ext/filters/client_channel/subchannel.h | 10 +---- .../client_channel/subchannel_index.cc | 15 +++---- .../filters/client_channel/subchannel_index.h | 3 +- .../chttp2/client/insecure/channel_create.cc | 10 ++--- .../client/secure/secure_channel_create.cc | 44 +++++++------------ test/cpp/microbenchmarks/bm_call_create.cc | 2 +- 10 files changed, 40 insertions(+), 66 deletions(-) diff --git a/src/core/ext/filters/client_channel/client_channel_factory.cc b/src/core/ext/filters/client_channel/client_channel_factory.cc index 172e9f03c73..130bbe04180 100644 --- a/src/core/ext/filters/client_channel/client_channel_factory.cc +++ b/src/core/ext/filters/client_channel/client_channel_factory.cc @@ -30,7 +30,7 @@ void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory) { } grpc_subchannel* grpc_client_channel_factory_create_subchannel( - grpc_client_channel_factory* factory, const grpc_subchannel_args* args) { + grpc_client_channel_factory* factory, const grpc_channel_args* args) { return factory->vtable->create_subchannel(factory, args); } diff --git a/src/core/ext/filters/client_channel/client_channel_factory.h b/src/core/ext/filters/client_channel/client_channel_factory.h index 601ec46b2a5..91dec12282f 100644 --- a/src/core/ext/filters/client_channel/client_channel_factory.h +++ b/src/core/ext/filters/client_channel/client_channel_factory.h @@ -49,7 +49,7 @@ struct grpc_client_channel_factory_vtable { void (*ref)(grpc_client_channel_factory* factory); void (*unref)(grpc_client_channel_factory* factory); grpc_subchannel* (*create_subchannel)(grpc_client_channel_factory* factory, - const grpc_subchannel_args* args); + const grpc_channel_args* args); grpc_channel* (*create_client_channel)(grpc_client_channel_factory* factory, const char* target, grpc_client_channel_type type, @@ -61,7 +61,7 @@ void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory); /** Create a new grpc_subchannel */ grpc_subchannel* grpc_client_channel_factory_create_subchannel( - grpc_client_channel_factory* factory, const grpc_subchannel_args* args); + grpc_client_channel_factory* factory, const grpc_channel_args* args); /** Create a new grpc_channel */ grpc_channel* grpc_client_channel_factory_create_channel( diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h index 6f31a643c1d..1d0ecbe3f64 100644 --- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h @@ -509,12 +509,10 @@ SubchannelList::SubchannelList( GRPC_ARG_SERVER_ADDRESS_LIST, GRPC_ARG_INHIBIT_HEALTH_CHECKING}; // Create a subchannel for each address. - grpc_subchannel_args sc_args; for (size_t i = 0; i < addresses.size(); i++) { // If there were any balancer addresses, we would have chosen grpclb // policy, which does not use a SubchannelList. GPR_ASSERT(!addresses[i].IsBalancer()); - memset(&sc_args, 0, sizeof(grpc_subchannel_args)); InlinedVector args_to_add; args_to_add.emplace_back( grpc_create_subchannel_address_arg(&addresses[i].address())); @@ -527,9 +525,8 @@ SubchannelList::SubchannelList( &args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add.data(), args_to_add.size()); gpr_free(args_to_add[0].value.string); - sc_args.args = new_args; grpc_subchannel* subchannel = grpc_client_channel_factory_create_subchannel( - client_channel_factory, &sc_args); + client_channel_factory, new_args); grpc_channel_args_destroy(new_args); if (subchannel == nullptr) { // Subchannel could not be created. diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index dff213efc6b..640a052e91e 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -537,7 +537,7 @@ struct HealthCheckParams { } // namespace grpc_core grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, - const grpc_subchannel_args* args) { + const grpc_channel_args* args) { grpc_subchannel_key* key = grpc_subchannel_key_create(args); grpc_subchannel* c = grpc_subchannel_index_find(key); if (c) { @@ -554,11 +554,10 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, c->pollset_set = grpc_pollset_set_create(); grpc_resolved_address* addr = static_cast(gpr_malloc(sizeof(*addr))); - grpc_get_subchannel_address_arg(args->args, addr); + grpc_get_subchannel_address_arg(args, addr); grpc_resolved_address* new_address = nullptr; grpc_channel_args* new_args = nullptr; - if (grpc_proxy_mappers_map_address(addr, args->args, &new_address, - &new_args)) { + if (grpc_proxy_mappers_map_address(addr, args, &new_address, &new_args)) { GPR_ASSERT(new_address != nullptr); gpr_free(addr); addr = new_address; @@ -567,7 +566,7 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, grpc_arg new_arg = grpc_create_subchannel_address_arg(addr); gpr_free(addr); c->args = grpc_channel_args_copy_and_add_and_remove( - new_args != nullptr ? new_args : args->args, keys_to_remove, + new_args != nullptr ? new_args : args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1); gpr_free(new_arg.value.string); if (new_args != nullptr) grpc_channel_args_destroy(new_args); @@ -580,7 +579,7 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, grpc_connectivity_state_init(&c->state_and_health_tracker, GRPC_CHANNEL_IDLE, "subchannel"); grpc_core::BackOff::Options backoff_options; - parse_args_for_backoff_values(args->args, &backoff_options, + parse_args_for_backoff_values(args, &backoff_options, &c->min_connect_timeout_ms); c->backoff.Init(backoff_options); gpr_mu_init(&c->mu); diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index d0c0a672fa1..8c994c64f50 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -38,7 +38,6 @@ address. Provides a target for load balancing. */ typedef struct grpc_subchannel grpc_subchannel; typedef struct grpc_subchannel_call grpc_subchannel_call; -typedef struct grpc_subchannel_args grpc_subchannel_args; typedef struct grpc_subchannel_key grpc_subchannel_key; #ifndef NDEBUG @@ -186,16 +185,9 @@ void grpc_subchannel_call_set_cleanup_closure( grpc_call_stack* grpc_subchannel_call_get_call_stack( grpc_subchannel_call* subchannel_call); -struct grpc_subchannel_args { - /* When updating this struct, also update subchannel_index.c */ - - /** Channel arguments to be supplied to the newly created channel */ - const grpc_channel_args* args; -}; - /** create a subchannel given a connector */ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, - const grpc_subchannel_args* args); + const grpc_channel_args* args); /// Sets \a addr from \a args. void grpc_get_subchannel_address_arg(const grpc_channel_args* args, diff --git a/src/core/ext/filters/client_channel/subchannel_index.cc b/src/core/ext/filters/client_channel/subchannel_index.cc index 0ae7898c5a4..d0ceda8312c 100644 --- a/src/core/ext/filters/client_channel/subchannel_index.cc +++ b/src/core/ext/filters/client_channel/subchannel_index.cc @@ -39,38 +39,37 @@ static gpr_mu g_mu; static gpr_refcount g_refcount; struct grpc_subchannel_key { - grpc_subchannel_args args; + grpc_channel_args* args; }; static bool g_force_creation = false; static grpc_subchannel_key* create_key( - const grpc_subchannel_args* args, + const grpc_channel_args* args, grpc_channel_args* (*copy_channel_args)(const grpc_channel_args* args)) { grpc_subchannel_key* k = static_cast(gpr_malloc(sizeof(*k))); - k->args.args = copy_channel_args(args->args); + k->args = copy_channel_args(args); return k; } -grpc_subchannel_key* grpc_subchannel_key_create( - const grpc_subchannel_args* args) { +grpc_subchannel_key* grpc_subchannel_key_create(const grpc_channel_args* args) { return create_key(args, grpc_channel_args_normalize); } static grpc_subchannel_key* subchannel_key_copy(grpc_subchannel_key* k) { - return create_key(&k->args, grpc_channel_args_copy); + return create_key(k->args, grpc_channel_args_copy); } int grpc_subchannel_key_compare(const grpc_subchannel_key* a, const grpc_subchannel_key* b) { // To pretend the keys are different, return a non-zero value. if (GPR_UNLIKELY(g_force_creation)) return 1; - return grpc_channel_args_compare(a->args.args, b->args.args); + return grpc_channel_args_compare(a->args, b->args); } void grpc_subchannel_key_destroy(grpc_subchannel_key* k) { - grpc_channel_args_destroy(const_cast(k->args.args)); + grpc_channel_args_destroy(k->args); gpr_free(k); } diff --git a/src/core/ext/filters/client_channel/subchannel_index.h b/src/core/ext/filters/client_channel/subchannel_index.h index c135613d26b..429634bd54c 100644 --- a/src/core/ext/filters/client_channel/subchannel_index.h +++ b/src/core/ext/filters/client_channel/subchannel_index.h @@ -27,8 +27,7 @@ shared amongst channels */ /** Create a key that can be used to uniquely identify a subchannel */ -grpc_subchannel_key* grpc_subchannel_key_create( - const grpc_subchannel_args* args); +grpc_subchannel_key* grpc_subchannel_key_create(const grpc_channel_args* args); /** Destroy a subchannel key */ void grpc_subchannel_key_destroy(grpc_subchannel_key* key); diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.cc b/src/core/ext/transport/chttp2/client/insecure/channel_create.cc index e6c8c382607..a5bf1bf21d4 100644 --- a/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.cc @@ -40,14 +40,12 @@ static void client_channel_factory_unref( grpc_client_channel_factory* cc_factory) {} static grpc_subchannel* client_channel_factory_create_subchannel( - grpc_client_channel_factory* cc_factory, const grpc_subchannel_args* args) { - grpc_subchannel_args final_sc_args; - memcpy(&final_sc_args, args, sizeof(*args)); - final_sc_args.args = grpc_default_authority_add_if_not_present(args->args); + grpc_client_channel_factory* cc_factory, const grpc_channel_args* args) { + grpc_channel_args* new_args = grpc_default_authority_add_if_not_present(args); grpc_connector* connector = grpc_chttp2_connector_create(); - grpc_subchannel* s = grpc_subchannel_create(connector, &final_sc_args); + grpc_subchannel* s = grpc_subchannel_create(connector, new_args); grpc_connector_unref(connector); - grpc_channel_args_destroy(const_cast(final_sc_args.args)); + grpc_channel_args_destroy(new_args); return s; } diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc index 9612698e967..ddd538faa80 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc @@ -46,10 +46,10 @@ static void client_channel_factory_ref( static void client_channel_factory_unref( grpc_client_channel_factory* cc_factory) {} -static grpc_subchannel_args* get_secure_naming_subchannel_args( - const grpc_subchannel_args* args) { +static grpc_channel_args* get_secure_naming_channel_args( + const grpc_channel_args* args) { grpc_channel_credentials* channel_credentials = - grpc_channel_credentials_find_in_args(args->args); + grpc_channel_credentials_find_in_args(args); if (channel_credentials == nullptr) { gpr_log(GPR_ERROR, "Can't create subchannel: channel credentials missing for secure " @@ -57,7 +57,7 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args( return nullptr; } // Make sure security connector does not already exist in args. - if (grpc_security_connector_find_in_args(args->args) != nullptr) { + if (grpc_security_connector_find_in_args(args) != nullptr) { gpr_log(GPR_ERROR, "Can't create subchannel: security connector already present in " "channel args."); @@ -65,19 +65,18 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args( } // To which address are we connecting? By default, use the server URI. const grpc_arg* server_uri_arg = - grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI); + grpc_channel_args_find(args, GRPC_ARG_SERVER_URI); const char* server_uri_str = grpc_channel_arg_get_string(server_uri_arg); GPR_ASSERT(server_uri_str != nullptr); grpc_uri* server_uri = grpc_uri_parse(server_uri_str, true /* supress errors */); GPR_ASSERT(server_uri != nullptr); const grpc_core::TargetAuthorityTable* target_authority_table = - grpc_core::FindTargetAuthorityTableInArgs(args->args); + grpc_core::FindTargetAuthorityTableInArgs(args); grpc_core::UniquePtr authority; if (target_authority_table != nullptr) { // Find the authority for the target. - const char* target_uri_str = - grpc_get_subchannel_address_uri_arg(args->args); + const char* target_uri_str = grpc_get_subchannel_address_uri_arg(args); grpc_uri* target_uri = grpc_uri_parse(target_uri_str, false /* suppress errors */); GPR_ASSERT(target_uri != nullptr); @@ -100,15 +99,14 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args( } grpc_arg args_to_add[2]; size_t num_args_to_add = 0; - if (grpc_channel_args_find(args->args, GRPC_ARG_DEFAULT_AUTHORITY) == - nullptr) { + if (grpc_channel_args_find(args, GRPC_ARG_DEFAULT_AUTHORITY) == nullptr) { // If the channel args don't already contain GRPC_ARG_DEFAULT_AUTHORITY, add // the arg, setting it to the value just obtained. args_to_add[num_args_to_add++] = grpc_channel_arg_string_create( const_cast(GRPC_ARG_DEFAULT_AUTHORITY), authority.get()); } grpc_channel_args* args_with_authority = - grpc_channel_args_copy_and_add(args->args, args_to_add, num_args_to_add); + grpc_channel_args_copy_and_add(args, args_to_add, num_args_to_add); grpc_uri_destroy(server_uri); // Create the security connector using the credentials and target name. grpc_channel_args* new_args_from_connector = nullptr; @@ -137,29 +135,21 @@ static grpc_subchannel_args* get_secure_naming_subchannel_args( grpc_channel_args_destroy(new_args_from_connector); } grpc_channel_args_destroy(args_with_authority); - grpc_subchannel_args* final_sc_args = - static_cast(gpr_malloc(sizeof(*final_sc_args))); - memcpy(final_sc_args, args, sizeof(*args)); - final_sc_args->args = new_args; - return final_sc_args; + return new_args; } static grpc_subchannel* client_channel_factory_create_subchannel( - grpc_client_channel_factory* cc_factory, const grpc_subchannel_args* args) { - grpc_subchannel_args* subchannel_args = - get_secure_naming_subchannel_args(args); - if (subchannel_args == nullptr) { - gpr_log( - GPR_ERROR, - "Failed to create subchannel arguments during subchannel creation."); + grpc_client_channel_factory* cc_factory, const grpc_channel_args* args) { + grpc_channel_args* new_args = get_secure_naming_channel_args(args); + if (new_args == nullptr) { + gpr_log(GPR_ERROR, + "Failed to create channel args during subchannel creation."); return nullptr; } grpc_connector* connector = grpc_chttp2_connector_create(); - grpc_subchannel* s = grpc_subchannel_create(connector, subchannel_args); + grpc_subchannel* s = grpc_subchannel_create(connector, new_args); grpc_connector_unref(connector); - grpc_channel_args_destroy( - const_cast(subchannel_args->args)); - gpr_free(subchannel_args); + grpc_channel_args_destroy(new_args); return s; } diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc index 8d12606434b..125b1ce5c4e 100644 --- a/test/cpp/microbenchmarks/bm_call_create.cc +++ b/test/cpp/microbenchmarks/bm_call_create.cc @@ -326,7 +326,7 @@ class FakeClientChannelFactory : public grpc_client_channel_factory { static void NoRef(grpc_client_channel_factory* factory) {} static void NoUnref(grpc_client_channel_factory* factory) {} static grpc_subchannel* CreateSubchannel(grpc_client_channel_factory* factory, - const grpc_subchannel_args* args) { + const grpc_channel_args* args) { return nullptr; } static grpc_channel* CreateClientChannel(grpc_client_channel_factory* factory, From d4fa274bf2994276341e47920aa46e7a009b4d10 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 9 Jan 2019 09:38:47 -0800 Subject: [PATCH 343/375] address comments --- src/objective-c/GRPCClient/GRPCCall.m | 4 ---- src/objective-c/RxLibrary/GRXConcurrentWriteable.m | 6 ++---- src/objective-c/RxLibrary/GRXWriter.h | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index bc48f1aa1b3..c0d10cacc14 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -425,9 +425,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; // queue dispatch_queue_t _responseQueue; - // Whether the call is finished. If it is, should not call finishWithError again. - BOOL _finished; - // The OAuth2 token fetched from a token provider. NSString *_fetchedOauth2AccessToken; } @@ -750,7 +747,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; [self cancel]; } else { dispatch_async(_callQueue, ^{ - // EOS error is not processed here. It is handled by op batch of GRPC_OP_RECV_STATUS_ON_CLIENT [self finishRequestWithErrorHandler:nil]; }); diff --git a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m index d8491d2aed5..115195463de 100644 --- a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m +++ b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m @@ -113,10 +113,8 @@ - (void)cancelSilently { dispatch_async(_writeableQueue, ^{ - @synchronized(self) { - if (self->_alreadyFinished) { - return; - } + if (self->_alreadyFinished) { + return; } self.writeable = nil; }); diff --git a/src/objective-c/RxLibrary/GRXWriter.h b/src/objective-c/RxLibrary/GRXWriter.h index ac1f7b9c4cf..df4c80c28dd 100644 --- a/src/objective-c/RxLibrary/GRXWriter.h +++ b/src/objective-c/RxLibrary/GRXWriter.h @@ -82,7 +82,7 @@ typedef NS_ENUM(NSInteger, GRXWriterState) { * the corresponding value, and that's useful for advanced use cases like pausing an writer. For * more details, see the documentation of the enum further down. The property is thread safe. */ -@property(atomic) GRXWriterState state; +@property GRXWriterState state; /** * Transition to the Started state, and start sending messages to the writeable (a reference to it From ca5c0a83664068dc0691166c0438e664a95a58ac Mon Sep 17 00:00:00 2001 From: Richard Belleville Date: Wed, 9 Jan 2019 09:43:14 -0800 Subject: [PATCH 344/375] Switch to absolute import --- src/python/grpcio/grpc/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py index 70d7618e056..8613bc501f1 100644 --- a/src/python/grpcio/grpc/__init__.py +++ b/src/python/grpcio/grpc/__init__.py @@ -24,7 +24,7 @@ from grpc._cython import cygrpc as _cygrpc logging.getLogger(__name__).addHandler(logging.NullHandler()) try: - from ._grpcio_metadata import __version__ + from grpc._grpcio_metadata import __version__ except ImportError: __version__ = "dev0" From 025cb9b1e712ad215b9180d9a74c2c71ce870ac2 Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Wed, 9 Jan 2019 10:33:48 -0800 Subject: [PATCH 345/375] correctly name __dealloc__ method --- src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi index d72648a35d0..ef74f61e043 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi @@ -149,6 +149,6 @@ cdef class Server: grpc_server_destroy(self.c_server) self.c_server = NULL - def __dealloc(self): + def __dealloc__(self): if self.c_server == NULL: grpc_shutdown() From b4818682be9be27398142996e8b02c23624b1184 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 9 Jan 2019 19:41:22 +0100 Subject: [PATCH 346/375] fix #17625 --- tools/run_tests/dockerize/build_interop_image.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/run_tests/dockerize/build_interop_image.sh b/tools/run_tests/dockerize/build_interop_image.sh index 0f88787639a..025c532d976 100755 --- a/tools/run_tests/dockerize/build_interop_image.sh +++ b/tools/run_tests/dockerize/build_interop_image.sh @@ -90,9 +90,6 @@ else docker build -t "$BASE_IMAGE" --force-rm=true "tools/dockerfile/interoptest/$BASE_NAME" || exit $? fi -# Create a local branch so the child Docker script won't complain -git branch -f jenkins-docker - CONTAINER_NAME="build_${BASE_NAME}_$(uuidgen)" # Prepare image for interop tests, commit it on success. From eda9742bbdb4899c6661509981abab729a7044e8 Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Wed, 9 Jan 2019 10:57:53 -0800 Subject: [PATCH 347/375] updated bazel and RBE instance versions --- third_party/toolchains/BUILD | 12 ++++++------ tools/remote_build/rbe_common.bazelrc | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/third_party/toolchains/BUILD b/third_party/toolchains/BUILD index e213461acc9..2499d1c788c 100644 --- a/third_party/toolchains/BUILD +++ b/third_party/toolchains/BUILD @@ -20,17 +20,17 @@ package(default_visibility = ["//visibility:public"]) # Update every time when a new container is released. alias( name = "rbe_ubuntu1604", - actual = ":rbe_ubuntu1604_r342117", + actual = ":rbe_ubuntu1604_r346485", ) alias( name = "rbe_ubuntu1604_large", - actual = ":rbe_ubuntu1604_r342117_large", + actual = ":rbe_ubuntu1604_r346485_large", ) -# RBE Ubuntu16_04 r342117 +# RBE Ubuntu16_04 r346485 platform( - name = "rbe_ubuntu1604_r342117", + name = "rbe_ubuntu1604_r346485", constraint_values = [ "@bazel_tools//platforms:x86_64", "@bazel_tools//platforms:linux", @@ -51,9 +51,9 @@ platform( """, ) -# RBE Ubuntu16_04 r342117 large +# RBE Ubuntu16_04 r346485 large platform( - name = "rbe_ubuntu1604_r342117_large", + name = "rbe_ubuntu1604_r346485_large", constraint_values = [ "@bazel_tools//platforms:x86_64", "@bazel_tools//platforms:linux", diff --git a/tools/remote_build/rbe_common.bazelrc b/tools/remote_build/rbe_common.bazelrc index aa3ddb050cd..8cf17a30860 100644 --- a/tools/remote_build/rbe_common.bazelrc +++ b/tools/remote_build/rbe_common.bazelrc @@ -18,7 +18,7 @@ startup --host_jvm_args=-Dbazel.DigestFunction=SHA256 -build --crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.1/bazel_0.16.1/default:toolchain +build --crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.1/bazel_0.20.0/default:toolchain build --extra_toolchains=//third_party/toolchains:cc-toolchain-clang-x86_64-default # Use custom execution platforms defined in third_party/toolchains build --extra_execution_platforms=//third_party/toolchains:rbe_ubuntu1604,//third_party/toolchains:rbe_ubuntu1604_large @@ -61,9 +61,9 @@ build:msan --cxxopt=--stdlib=libc++ # setting LD_LIBRARY_PATH is necessary # to avoid "libc++.so.1: cannot open shared object file" build:msan --action_env=LD_LIBRARY_PATH=/usr/local/lib -build:msan --host_crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.1/bazel_0.16.1/default:toolchain +build:msan --host_crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.1/bazel_0.20.0/default:toolchain # override the config-agnostic crosstool_top -build:msan --crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.1/bazel_0.16.1/msan:toolchain +build:msan --crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.1/bazel_0.20.0/msan:toolchain # thread sanitizer: most settings are already in %workspace%/.bazelrc # we only need a few additional ones that are Foundry specific @@ -79,7 +79,7 @@ build:ubsan --copt=-gmlt # TODO(jtattermusch): use more reasonable test timeout build:ubsan --test_timeout=3600 # override the config-agnostic crosstool_top ---crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/experimental/ubuntu16_04_clang/1.1/bazel_0.16.1/ubsan:toolchain +--crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/experimental/ubuntu16_04_clang/1.1/bazel_0.20.0/ubsan:toolchain # TODO(jtattermusch): remove this once Foundry adds the env to the docker image. # ubsan needs symbolizer to work properly, otherwise the suppression file doesn't work # and we get test failures. From 95dc9c1110d83c42dea668d6d8729b920caa400c Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Wed, 9 Jan 2019 11:21:29 -0800 Subject: [PATCH 348/375] updated repo for bazel --- bazel/grpc_deps.bzl | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/bazel/grpc_deps.bzl b/bazel/grpc_deps.bzl index 3eacd2b0475..ea66fa80999 100644 --- a/bazel/grpc_deps.bzl +++ b/bazel/grpc_deps.bzl @@ -93,17 +93,17 @@ def grpc_deps(): native.bind( name = "opencensus-trace", - actual = "@io_opencensus_cpp//opencensus/trace:trace" + actual = "@io_opencensus_cpp//opencensus/trace:trace", ) native.bind( name = "opencensus-stats", - actual = "@io_opencensus_cpp//opencensus/stats:stats" + actual = "@io_opencensus_cpp//opencensus/stats:stats", ) native.bind( name = "opencensus-stats-test", - actual = "@io_opencensus_cpp//opencensus/stats:test_utils" + actual = "@io_opencensus_cpp//opencensus/stats:test_utils", ) if "boringssl" not in native.existing_rules(): @@ -177,16 +177,16 @@ def grpc_deps(): if "com_github_bazelbuild_bazeltoolchains" not in native.existing_rules(): http_archive( name = "com_github_bazelbuild_bazeltoolchains", - strip_prefix = "bazel-toolchains-280edaa6f93623074513d2b426068de42e62ea4d", + strip_prefix = "bazel-toolchains-35bfb70728dedc936a370e551294f2fc9c02b7d5", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/280edaa6f93623074513d2b426068de42e62ea4d.tar.gz", - "https://github.com/bazelbuild/bazel-toolchains/archive/280edaa6f93623074513d2b426068de42e62ea4d.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/35bfb70728dedc936a370e551294f2fc9c02b7d5.tar.gz", + "https://github.com/bazelbuild/bazel-toolchains/archive/35bfb70728dedc936a370e551294f2fc9c02b7d5.tar.gz", ], sha256 = "50c9df51f80cdf9ff8f2bc27620c155526b9ba67be95e8a686f32ff8898a06e2", ) if "io_opencensus_cpp" not in native.existing_rules(): - http_archive( + http_archive( name = "io_opencensus_cpp", strip_prefix = "opencensus-cpp-fdf0f308b1631bb4a942e32ba5d22536a6170274", url = "https://github.com/census-instrumentation/opencensus-cpp/archive/fdf0f308b1631bb4a942e32ba5d22536a6170274.tar.gz", @@ -199,7 +199,6 @@ def grpc_deps(): url = "https://github.com/google/upb/archive/9ce4a77f61c134bbed28bfd5be5cd7dc0e80f5e3.tar.gz", ) - # TODO: move some dependencies from "grpc_deps" here? def grpc_test_only_deps(): """Internal, not intended for use by packages that are consuming grpc. From b2ac318566bcdcdd0a8306af5030e62025d6666a Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Wed, 9 Jan 2019 11:25:05 -0800 Subject: [PATCH 349/375] updated repo for bazel to latest version --- bazel/grpc_deps.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bazel/grpc_deps.bzl b/bazel/grpc_deps.bzl index ea66fa80999..8eb60d13d4f 100644 --- a/bazel/grpc_deps.bzl +++ b/bazel/grpc_deps.bzl @@ -177,12 +177,12 @@ def grpc_deps(): if "com_github_bazelbuild_bazeltoolchains" not in native.existing_rules(): http_archive( name = "com_github_bazelbuild_bazeltoolchains", - strip_prefix = "bazel-toolchains-35bfb70728dedc936a370e551294f2fc9c02b7d5", + strip_prefix = "bazel-toolchains-37419a124bdb9af2fec5b99a973d359b6b899b61 ", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/35bfb70728dedc936a370e551294f2fc9c02b7d5.tar.gz", - "https://github.com/bazelbuild/bazel-toolchains/archive/35bfb70728dedc936a370e551294f2fc9c02b7d5.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/37419a124bdb9af2fec5b99a973d359b6b899b61 .tar.gz", + "https://github.com/bazelbuild/bazel-toolchains/archive/37419a124bdb9af2fec5b99a973d359b6b899b61 .tar.gz", ], - sha256 = "50c9df51f80cdf9ff8f2bc27620c155526b9ba67be95e8a686f32ff8898a06e2", + sha256 = "ee854b5de299138c1f4a2edb5573d22b21d975acfc7aa938f36d30b49ef97498", ) if "io_opencensus_cpp" not in native.existing_rules(): From 56268e092719860491de0d2b1da44d7a7d7fcb2c Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Wed, 9 Jan 2019 11:32:18 -0800 Subject: [PATCH 350/375] fixed typo on hash --- bazel/grpc_deps.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bazel/grpc_deps.bzl b/bazel/grpc_deps.bzl index 8eb60d13d4f..450928828c2 100644 --- a/bazel/grpc_deps.bzl +++ b/bazel/grpc_deps.bzl @@ -177,10 +177,10 @@ def grpc_deps(): if "com_github_bazelbuild_bazeltoolchains" not in native.existing_rules(): http_archive( name = "com_github_bazelbuild_bazeltoolchains", - strip_prefix = "bazel-toolchains-37419a124bdb9af2fec5b99a973d359b6b899b61 ", + strip_prefix = "bazel-toolchains-37419a124bdb9af2fec5b99a973d359b6b899b61", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/37419a124bdb9af2fec5b99a973d359b6b899b61 .tar.gz", - "https://github.com/bazelbuild/bazel-toolchains/archive/37419a124bdb9af2fec5b99a973d359b6b899b61 .tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/37419a124bdb9af2fec5b99a973d359b6b899b61.tar.gz", + "https://github.com/bazelbuild/bazel-toolchains/archive/37419a124bdb9af2fec5b99a973d359b6b899b61.tar.gz", ], sha256 = "ee854b5de299138c1f4a2edb5573d22b21d975acfc7aa938f36d30b49ef97498", ) From 3dafee1e51813beff7b5947702772f1d22a06ed5 Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Wed, 9 Jan 2019 11:55:57 -0800 Subject: [PATCH 351/375] bumped bazel version for internal CI --- tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh b/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh index 4d7d4271d61..863b43a1728 100755 --- a/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh +++ b/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh @@ -23,7 +23,7 @@ cp ${KOKORO_GFILE_DIR}/GrpcTesting-d0eeee2db331.json ${KOKORO_KEYSTORE_DIR}/4321 # Download bazel temp_dir="$(mktemp -d)" -wget -q https://github.com/bazelbuild/bazel/releases/download/0.17.1/bazel-0.17.1-linux-x86_64 -O "${temp_dir}/bazel" +wget -q https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-linux-x86_64 -O "${temp_dir}/bazel" chmod 755 "${temp_dir}/bazel" export PATH="${temp_dir}:${PATH}" # This should show ${temp_dir}/bazel From 9f85ead667121f5c74fe232e7908ab774131e1e2 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 9 Jan 2019 12:06:24 -0800 Subject: [PATCH 352/375] Add new proto in examples --- examples/BUILD | 5 +++++ examples/protos/keyvaluestore.proto | 33 +++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 examples/protos/keyvaluestore.proto diff --git a/examples/BUILD b/examples/BUILD index c4f25d0de9f..b6cb9d48d3c 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -38,6 +38,11 @@ grpc_proto_library( srcs = ["protos/route_guide.proto"], ) +grpc_proto_library( + name = "keyvaluestore", + srcs = ["protos/keyvaluestore.proto"], +) + cc_binary( name = "greeter_client", srcs = ["cpp/helloworld/greeter_client.cc"], diff --git a/examples/protos/keyvaluestore.proto b/examples/protos/keyvaluestore.proto new file mode 100644 index 00000000000..06b516a1501 --- /dev/null +++ b/examples/protos/keyvaluestore.proto @@ -0,0 +1,33 @@ +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package keyvaluestore; + +// Key value store service definition. +service KeyValueStore { + // Provides a value for each key reques + rpc GetValues (stream Key) returns (stream Value) {} +} + +// The request message containing the key +message Key { + string key = 1; +} + +// The response message containing the greetings +message Value { + string value = 1; +} From 4f11b9650099212b9bb3c01b6b73e977a20c2c8e Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 9 Jan 2019 16:35:35 +0100 Subject: [PATCH 353/375] stop testing older releases with go1.7: 1.8 should be enough --- tools/interop_matrix/README.md | 4 ++-- tools/interop_matrix/client_matrix.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/interop_matrix/README.md b/tools/interop_matrix/README.md index 6676f5d470c..531bef82b8e 100644 --- a/tools/interop_matrix/README.md +++ b/tools/interop_matrix/README.md @@ -42,10 +42,10 @@ For more details on each step, refer to sections below. - The output for all the test cases is recorded in a junit style xml file (default to 'report.xml'). ## Instructions for running test cases against a GCR image manually -- Download docker image from GCR. For example: `gcloud docker -- pull gcr.io/grpc-testing/grpc_interop_go1.7:master`. +- Download docker image from GCR. For example: `gcloud docker -- pull gcr.io/grpc-testing/grpc_interop_go1.8:master`. - Run test cases by specifying `docker_image` variable inline with the test case script created above. For example: - - `docker_image=gcr.io/grpc-testing/grpc_interop_go1.7:master ./testcases/go__master` will run go__master test cases against `go1.7` with gRPC release `master` docker image in GCR. + - `docker_image=gcr.io/grpc-testing/grpc_interop_go1.8:master ./testcases/go__master` will run go__master test cases against `go1.8` with gRPC release `master` docker image in GCR. Note: - File path starting with `tools/` or `template/` are relative to the grpc repo root dir. File path starting with `./` are relative to current directory (`tools/interop_matrix`). diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py index 12051e70a0b..9a7c90acd32 100644 --- a/tools/interop_matrix/client_matrix.py +++ b/tools/interop_matrix/client_matrix.py @@ -57,7 +57,7 @@ def should_build_docker_interop_image_from_release_tag(lang): # Dictionary of runtimes per language LANG_RUNTIME_MATRIX = { 'cxx': ['cxx'], # This is actually debian8. - 'go': ['go1.7', 'go1.8', 'go1.11'], + 'go': ['go1.8', 'go1.11'], 'java': ['java_oracle8'], 'python': ['python'], 'node': ['node'], @@ -116,7 +116,7 @@ LANG_RELEASE_MATRIX = { ('v1.14.0', ReleaseInfo(skip_runtime=['go1.11'])), ('v1.15.0', ReleaseInfo(skip_runtime=['go1.11'])), ('v1.16.0', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.17.0', ReleaseInfo(skip_runtime=['go1.7', 'go1.8'])), + ('v1.17.0', ReleaseInfo(skip_runtime=['go1.8'])), ]), 'java': OrderedDict([ From bd5e15608d217e7a5efcaac73dc45f7d1be28a21 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 9 Jan 2019 16:44:43 +0100 Subject: [PATCH 354/375] minor doc updates --- tools/interop_matrix/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/interop_matrix/README.md b/tools/interop_matrix/README.md index 531bef82b8e..5a8965757ee 100644 --- a/tools/interop_matrix/README.md +++ b/tools/interop_matrix/README.md @@ -11,8 +11,8 @@ We have continuous nightly test setup to test gRPC backward compatibility betwee - Build new client docker image(s). For example, for C and wrapper languages release `v1.9.9`, do - `tools/interop_matrix/create_matrix_images.py --git_checkout --release=v1.9.9 --upload_images --language cxx csharp python ruby php` - Verify that the new docker image was built successfully and uploaded to GCR. For example, - - `gcloud beta container images list --repository gcr.io/grpc-testing` shows image repos. - - `gcloud beta container images list-tags gcr.io/grpc-testing/grpc_interop_java_oracle8` should show an image entry with tag `v1.9.9`. + - `gcloud container images list --repository gcr.io/grpc-testing` lists available images. + - `gcloud container images list-tags gcr.io/grpc-testing/grpc_interop_java_oracle8` should show an image entry with tag `v1.9.9`. - Verify the just-created docker client image would pass backward compatibility test (it should). For example, - `gcloud docker -- pull gcr.io/grpc-testing/grpc_interop_java_oracle8:v1.9.9` followed by - `docker_image=gcr.io/grpc-testing/grpc_interop_java_oracle8:v1.9.9 tools/interop_matrix/testcases/java__master` From 2a997c66eada4015912230a482d3b898ec526800 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 9 Jan 2019 16:51:51 +0100 Subject: [PATCH 355/375] allow creating images for non-yet-listed releases --- tools/interop_matrix/client_matrix.py | 2 +- tools/interop_matrix/create_matrix_images.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py index 9a7c90acd32..ec499a98b61 100644 --- a/tools/interop_matrix/client_matrix.py +++ b/tools/interop_matrix/client_matrix.py @@ -36,7 +36,7 @@ def get_release_tags(lang): def get_runtimes_for_lang_release(lang, release): """Get list of valid runtimes for given release of lang.""" runtimes_to_skip = [] - release_info = LANG_RELEASE_MATRIX[lang][release] + release_info = LANG_RELEASE_MATRIX[lang].get(release) if release_info: runtimes_to_skip = release_info.skip_runtime return [ diff --git a/tools/interop_matrix/create_matrix_images.py b/tools/interop_matrix/create_matrix_images.py index 31a0e1c7ba6..28dc4be0f4d 100755 --- a/tools/interop_matrix/create_matrix_images.py +++ b/tools/interop_matrix/create_matrix_images.py @@ -260,7 +260,7 @@ atexit.register(cleanup) def maybe_apply_patches_on_git_tag(stack_base, lang, release): files_to_patch = [] - release_info = client_matrix.LANG_RELEASE_MATRIX[lang][release] + release_info = client_matrix.LANG_RELEASE_MATRIX[lang].get(release) if release_info: files_to_patch = release_info.patch if not files_to_patch: From 0d1743b3cc2a24dc2a17fb8e87e2fc8795d44585 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 9 Jan 2019 17:11:54 +0100 Subject: [PATCH 356/375] having GCR images with ":master" tag is an antipattern. --- tools/interop_matrix/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/interop_matrix/README.md b/tools/interop_matrix/README.md index 5a8965757ee..a2c3189bbd6 100644 --- a/tools/interop_matrix/README.md +++ b/tools/interop_matrix/README.md @@ -42,10 +42,10 @@ For more details on each step, refer to sections below. - The output for all the test cases is recorded in a junit style xml file (default to 'report.xml'). ## Instructions for running test cases against a GCR image manually -- Download docker image from GCR. For example: `gcloud docker -- pull gcr.io/grpc-testing/grpc_interop_go1.8:master`. +- Download docker image from GCR. For example: `gcloud docker -- pull gcr.io/grpc-testing/grpc_interop_go1.8:v1.16.0`. - Run test cases by specifying `docker_image` variable inline with the test case script created above. For example: - - `docker_image=gcr.io/grpc-testing/grpc_interop_go1.8:master ./testcases/go__master` will run go__master test cases against `go1.8` with gRPC release `master` docker image in GCR. + - `docker_image=gcr.io/grpc-testing/grpc_interop_go1.8:v1.16.0 ./testcases/go__master` will run go__master test cases against `go1.8` with gRPC release `v1.16.0` docker image in GCR. Note: - File path starting with `tools/` or `template/` are relative to the grpc repo root dir. File path starting with `./` are relative to current directory (`tools/interop_matrix`). From b2044fdd6f8a74cbd489affee7f195b82bb15aac Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 9 Jan 2019 17:22:09 +0100 Subject: [PATCH 357/375] remove confusing remarks from interop_matrix README.md --- tools/interop_matrix/README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tools/interop_matrix/README.md b/tools/interop_matrix/README.md index a2c3189bbd6..ecd71be7f87 100644 --- a/tools/interop_matrix/README.md +++ b/tools/interop_matrix/README.md @@ -13,6 +13,7 @@ We have continuous nightly test setup to test gRPC backward compatibility betwee - Verify that the new docker image was built successfully and uploaded to GCR. For example, - `gcloud container images list --repository gcr.io/grpc-testing` lists available images. - `gcloud container images list-tags gcr.io/grpc-testing/grpc_interop_java_oracle8` should show an image entry with tag `v1.9.9`. + - images can also be viewed in https://pantheon.corp.google.com/gcr/images/grpc-testing?project=grpc-testing - Verify the just-created docker client image would pass backward compatibility test (it should). For example, - `gcloud docker -- pull gcr.io/grpc-testing/grpc_interop_java_oracle8:v1.9.9` followed by - `docker_image=gcr.io/grpc-testing/grpc_interop_java_oracle8:v1.9.9 tools/interop_matrix/testcases/java__master` @@ -20,13 +21,11 @@ We have continuous nightly test setup to test gRPC backward compatibility betwee - (Optional) clean up the tmp directory to where grpc source is cloned at `/export/hda3/tmp/grpc_matrix/`. For more details on each step, refer to sections below. -## Instructions for adding new language/runtimes* +## Instructions for adding new language/runtimes - Create new `Dockerfile.template`, `build_interop.sh.template` for the language/runtime under `template/tools/dockerfile/`. - Run `tools/buildgen/generate_projects.sh` to create corresponding files under `tools/dockerfile/`. - Add language/runtimes to `client_matrix.py` following existing language/runtimes examples. -- Run `tools/interop_matrix/create_matrix_images.py` which will build and upload images to GCR. Unless you are also building images for a gRPC release, make sure not to set `--release` (the default release 'master' is used for testing). - -*: Please delete your docker images at https://pantheon.corp.google.com/gcr/images/grpc-testing?project=grpc-testing afterwards. Permissions to access GrpcTesting project is required for this step. +- Run `tools/interop_matrix/create_matrix_images.py` which will build (and upload) images to GCR. ## Instructions for creating new test cases - Create test cases by running `LANG= [RELEASE=] ./create_testcases.sh`. For example, @@ -39,7 +38,7 @@ For more details on each step, refer to sections below. - `--release` specifies a git release tag. Defaults to `--release=all`. Make sure the GCR images with the tag have been created using `create_matrix_images.py` above. - `--language` specifies a language. Defaults to `--language=all`. For example, To test all languages for all gRPC releases across all runtimes, do `tools/interop_matrix/run_interop_matrix_test.py --release=all`. -- The output for all the test cases is recorded in a junit style xml file (default to 'report.xml'). +- The output for all the test cases is recorded in a junit style xml file (defaults to 'report.xml'). ## Instructions for running test cases against a GCR image manually - Download docker image from GCR. For example: `gcloud docker -- pull gcr.io/grpc-testing/grpc_interop_go1.8:v1.16.0`. From 905cd6a3151269fd2c3ad8577fbce5431d8f791b Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 9 Jan 2019 18:10:06 +0100 Subject: [PATCH 358/375] invert the strategy test runtimes are being selected per release --- tools/interop_matrix/client_matrix.py | 53 ++++++++++++++------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py index ec499a98b61..655c7c7b6bf 100644 --- a/tools/interop_matrix/client_matrix.py +++ b/tools/interop_matrix/client_matrix.py @@ -35,14 +35,15 @@ def get_release_tags(lang): def get_runtimes_for_lang_release(lang, release): """Get list of valid runtimes for given release of lang.""" - runtimes_to_skip = [] + runtimes = list(LANG_RUNTIME_MATRIX[lang]) release_info = LANG_RELEASE_MATRIX[lang].get(release) - if release_info: - runtimes_to_skip = release_info.skip_runtime - return [ - runtime for runtime in LANG_RUNTIME_MATRIX[lang] - if runtime not in runtimes_to_skip - ] + if release_info and release_info.runtime_subset: + runtimes = list(release_info.runtime_subset) + + # check that all selected runtimes are valid for given language + for runtime in runtimes: + assert runtime in LANG_RUNTIME_MATRIX[lang] + return runtimes def should_build_docker_interop_image_from_release_tag(lang): @@ -70,9 +71,9 @@ LANG_RUNTIME_MATRIX = { class ReleaseInfo: """Info about a single release of a language""" - def __init__(self, patch=[], skip_runtime=[], testcases_file=None): + def __init__(self, patch=[], runtime_subset=[], testcases_file=None): self.patch = patch - self.skip_runtime = skip_runtime + self.runtime_subset = runtime_subset self.testcases_file = None @@ -100,23 +101,23 @@ LANG_RELEASE_MATRIX = { ]), 'go': OrderedDict([ - ('v1.0.5', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.2.1', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.3.0', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.4.2', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.5.2', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.6.0', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.7.4', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.8.2', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.9.2', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.10.1', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.11.3', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.12.2', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.13.0', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.14.0', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.15.0', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.16.0', ReleaseInfo(skip_runtime=['go1.11'])), - ('v1.17.0', ReleaseInfo(skip_runtime=['go1.8'])), + ('v1.0.5', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.2.1', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.3.0', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.4.2', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.5.2', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.6.0', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.7.4', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.8.2', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.9.2', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.10.1', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.11.3', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.12.2', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.13.0', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.14.0', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.15.0', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.16.0', ReleaseInfo(runtime_subset=['go1.8'])), + ('v1.17.0', ReleaseInfo(runtime_subset=['go1.11'])), ]), 'java': OrderedDict([ From 93e84947dfa3c3af2fdaaf5af0c6d6c93dd4e9fc Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 9 Jan 2019 14:58:50 -0800 Subject: [PATCH 359/375] Reviewer comments --- examples/protos/keyvaluestore.proto | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/protos/keyvaluestore.proto b/examples/protos/keyvaluestore.proto index 06b516a1501..9b5e53d8135 100644 --- a/examples/protos/keyvaluestore.proto +++ b/examples/protos/keyvaluestore.proto @@ -18,16 +18,16 @@ package keyvaluestore; // Key value store service definition. service KeyValueStore { - // Provides a value for each key reques - rpc GetValues (stream Key) returns (stream Value) {} + // Provides a value for each key request + rpc GetValues (stream Request) returns (stream Response) {} } // The request message containing the key -message Key { +message Request { string key = 1; } -// The response message containing the greetings -message Value { +// The response message containing the value associated with the key +message Response { string value = 1; } From 121e04bc1e44bb684d464be6788f1c0a065b1116 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 9 Jan 2019 15:22:05 -0800 Subject: [PATCH 360/375] address comments 2 --- src/objective-c/GRPCClient/GRPCCall.m | 1 - src/objective-c/RxLibrary/GRXForwardingWriter.m | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index c0d10cacc14..e8fae09a1f8 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -56,7 +56,6 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Make them read-write. @property(atomic, strong) NSDictionary *responseHeaders; @property(atomic, strong) NSDictionary *responseTrailers; -@property(atomic) BOOL isWaitingForToken; - (instancetype)initWithHost:(NSString *)host path:(NSString *)path diff --git a/src/objective-c/RxLibrary/GRXForwardingWriter.m b/src/objective-c/RxLibrary/GRXForwardingWriter.m index f5ed603698d..27ac0acdfff 100644 --- a/src/objective-c/RxLibrary/GRXForwardingWriter.m +++ b/src/objective-c/RxLibrary/GRXForwardingWriter.m @@ -72,7 +72,11 @@ #pragma mark GRXWriter implementation - (GRXWriterState)state { - return _writer ? _writer.state : GRXWriterStateFinished; + GRXWriter *copiedWriter; + @synchronized(self) { + copiedWriter = _writer; + } + return copiedWriter ? copiedWriter.state : GRXWriterStateFinished; } - (void)setState:(GRXWriterState)state { @@ -106,6 +110,7 @@ @synchronized(self) { [self finishOutputWithError:errorOrNil]; copiedWriter = _writer; + _writer = nil; } copiedWriter.state = GRXWriterStateFinished; } From de902e18b7db2cd93deff87a17d76ced99a2305a Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 9 Jan 2019 16:03:29 -0800 Subject: [PATCH 361/375] Reviewer comments --- examples/protos/keyvaluestore.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protos/keyvaluestore.proto b/examples/protos/keyvaluestore.proto index 9b5e53d8135..74ad57e0297 100644 --- a/examples/protos/keyvaluestore.proto +++ b/examples/protos/keyvaluestore.proto @@ -16,7 +16,7 @@ syntax = "proto3"; package keyvaluestore; -// Key value store service definition. +// A simple key-value storage service service KeyValueStore { // Provides a value for each key request rpc GetValues (stream Request) returns (stream Response) {} From 38f0fa394b1d75772a37aac2829a51a037d3271f Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 9 Jan 2019 17:01:07 -0800 Subject: [PATCH 362/375] Attempt to fix homebrew installation problem --- tools/internal_ci/helper_scripts/prepare_build_macos_rc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/internal_ci/helper_scripts/prepare_build_macos_rc b/tools/internal_ci/helper_scripts/prepare_build_macos_rc index 632db5ae145..5b6b2569393 100644 --- a/tools/internal_ci/helper_scripts/prepare_build_macos_rc +++ b/tools/internal_ci/helper_scripts/prepare_build_macos_rc @@ -38,6 +38,8 @@ if [ -n "$KOKORO_GITHUB_PULL_REQUEST_NUMBER" ]; then fi set +ex # rvm script is very verbose and exits with errorcode +# Advice from https://github.com/Homebrew/homebrew-cask/issues/8629#issuecomment-68641176 +brew update && brew upgrade brew-cask && brew cleanup && brew cask cleanup source $HOME/.rvm/scripts/rvm set -e # rvm commands are very verbose time rvm install 2.5.0 From c059946a75cab05a38dfb0c93afdbc0ee824d3a3 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 9 Jan 2019 18:26:22 -0800 Subject: [PATCH 363/375] Fix bug where remote host's trailing slash is not removed, causing name resolution failure --- src/objective-c/GRPCClient/private/GRPCChannelPool.m | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/objective-c/GRPCClient/private/GRPCChannelPool.m b/src/objective-c/GRPCClient/private/GRPCChannelPool.m index a323f0490c8..60a33eda824 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannelPool.m +++ b/src/objective-c/GRPCClient/private/GRPCChannelPool.m @@ -236,6 +236,12 @@ static const NSTimeInterval kDefaultChannelDestroyDelay = 30; return nil; } + // remove trailing slash of hostname + NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:host]]; + if (hostURL.host && hostURL.port == nil) { + host = [hostURL.host stringByAppendingString:@":443"]; + } + GRPCPooledChannel *pooledChannel = nil; GRPCChannelConfiguration *configuration = [[GRPCChannelConfiguration alloc] initWithHost:host callOptions:callOptions]; From 7a814e2597fbda08e06034717324d8e5b423b93a Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 10 Jan 2019 11:50:14 +0100 Subject: [PATCH 364/375] fix build with bazel 0.21 --- bazel/grpc_deps.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bazel/grpc_deps.bzl b/bazel/grpc_deps.bzl index 3eacd2b0475..ba0d72a266d 100644 --- a/bazel/grpc_deps.bzl +++ b/bazel/grpc_deps.bzl @@ -124,8 +124,8 @@ def grpc_deps(): if "com_google_protobuf" not in native.existing_rules(): http_archive( name = "com_google_protobuf", - strip_prefix = "protobuf-48cb18e5c419ddd23d9badcfe4e9df7bde1979b2", - url = "https://github.com/google/protobuf/archive/48cb18e5c419ddd23d9badcfe4e9df7bde1979b2.tar.gz", + strip_prefix = "protobuf-66dc42d891a4fc8e9190c524fd67961688a37bbe", + url = "https://github.com/google/protobuf/archive/66dc42d891a4fc8e9190c524fd67961688a37bbe.tar.gz", ) if "com_github_nanopb_nanopb" not in native.existing_rules(): From 5eed6d9d58b96e4d14d2cb9423656c90f572b57c Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Thu, 10 Jan 2019 10:23:43 -0800 Subject: [PATCH 365/375] fixed version on toolchain --- third_party/toolchains/BUILD | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/third_party/toolchains/BUILD b/third_party/toolchains/BUILD index 2499d1c788c..a1bee7f1f68 100644 --- a/third_party/toolchains/BUILD +++ b/third_party/toolchains/BUILD @@ -74,14 +74,12 @@ platform( """, ) -# This target is auto-generated from release/cpp.tpl and should not be -# modified directly. toolchain( name = "cc-toolchain-clang-x86_64-default", exec_compatible_with = [ ], target_compatible_with = [ ], - toolchain = "@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.1/bazel_0.16.1/default:cc-compiler-k8", + toolchain = "@com_github_bazelbuild_bazeltoolchains//configs/ubuntu16_04_clang/1.1/bazel_0.20.0/default:cc-compiler-k8", toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", ) From 7a5a9544ef9afb8456e5241741ceb387153bfb38 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 9 Jan 2019 14:56:42 -0800 Subject: [PATCH 366/375] Add a naive client server implementation --- examples/BUILD | 14 +++ .../cpp/keyvaluestore/caching_interceptor.cc | 0 examples/cpp/keyvaluestore/client.cc | 85 ++++++++++++++++ examples/cpp/keyvaluestore/server.cc | 99 +++++++++++++++++++ 4 files changed, 198 insertions(+) create mode 100644 examples/cpp/keyvaluestore/caching_interceptor.cc create mode 100644 examples/cpp/keyvaluestore/client.cc create mode 100644 examples/cpp/keyvaluestore/server.cc diff --git a/examples/BUILD b/examples/BUILD index b6cb9d48d3c..4fee663bd9e 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -98,3 +98,17 @@ cc_binary( defines = ["BAZEL_BUILD"], deps = [":helloworld", "//:grpc++"], ) + +cc_binary( + name = "keyvaluestore_client", + srcs = ["cpp/keyvaluestore/client.cc"], + defines = ["BAZEL_BUILD"], + deps = [":keyvaluestore", "//:grpc++"], +) + +cc_binary( + name = "keyvaluestore_server", + srcs = ["cpp/keyvaluestore/server.cc"], + defines = ["BAZEL_BUILD"], + deps = [":keyvaluestore", "//:grpc++"], +) \ No newline at end of file diff --git a/examples/cpp/keyvaluestore/caching_interceptor.cc b/examples/cpp/keyvaluestore/caching_interceptor.cc new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/cpp/keyvaluestore/client.cc b/examples/cpp/keyvaluestore/client.cc new file mode 100644 index 00000000000..9f5fa37cb1e --- /dev/null +++ b/examples/cpp/keyvaluestore/client.cc @@ -0,0 +1,85 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include + +#ifdef BAZEL_BUILD +#include "examples/protos/keyvaluestore.grpc.pb.h" +#else +#include "keyvaluestore.grpc.pb.h" +#endif + +using grpc::Channel; +using grpc::ClientContext; +using grpc::Status; +using keyvaluestore::Request; +using keyvaluestore::Response; +using keyvaluestore::KeyValueStore; + +class KeyValueStoreClient { + public: + KeyValueStoreClient(std::shared_ptr channel) + : stub_(KeyValueStore::NewStub(channel)) {} + + // Assembles the client's payload, sends it and presents the response back + // from the server. + void GetValues(const std::vector& keys) { + // Context for the client. It could be used to convey extra information to + // the server and/or tweak certain RPC behaviors. + ClientContext context; + auto stream = stub_->GetValues(&context); + for (const auto& key:keys) { + // Data we are sending to the server. + Request request; + request.set_key(key); + stream->Write(request); + + Response response; + stream->Read(&response); + std::cout << key << " : " << response.value() << "\n"; + } + stream->WritesDone(); + Status status = stream->Finish(); + if(!status.ok()) { + std::cout << status.error_code() << ": " << status.error_message() + << std::endl; + std::cout << "RPC failed"; + } + } + + private: + std::unique_ptr stub_; +}; + +int main(int argc, char** argv) { + // Instantiate the client. It requires a channel, out of which the actual RPCs + // are created. This channel models a connection to an endpoint (in this case, + // localhost at port 50051). We indicate that the channel isn't authenticated + // (use of InsecureChannelCredentials()). + KeyValueStoreClient client(grpc::CreateChannel( + "localhost:50051", grpc::InsecureChannelCredentials())); + std::vector keys = {"key1", "key2", "key3", "key4", "key5"}; + client.GetValues(keys); + + return 0; +} diff --git a/examples/cpp/keyvaluestore/server.cc b/examples/cpp/keyvaluestore/server.cc new file mode 100644 index 00000000000..75d30eb1f88 --- /dev/null +++ b/examples/cpp/keyvaluestore/server.cc @@ -0,0 +1,99 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#include + +#ifdef BAZEL_BUILD +#include "examples/protos/keyvaluestore.grpc.pb.h" +#else +#include "keyvaluestore.grpc.pb.h" +#endif + +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::ServerReaderWriter; +using grpc::Status; +using keyvaluestore::Request; +using keyvaluestore::Response; +using keyvaluestore::KeyValueStore; + +struct kv_pair { + const char* key; + const char* value; +}; + +static const kv_pair kvs_map[] = { + {"key1", "value1"}, + {"key2", "value2"}, + {"key3", "value3"}, + {"key4", "value4"}, + {"key5", "value5"}, +}; + +const char * get_value_from_map(const char* key) { + for(size_t i = 0; i < sizeof(kvs_map) / sizeof(kv_pair); ++i) { + if(strcmp(key, kvs_map[i].key) == 0) { + return kvs_map[i].value; + } + } + return nullptr; +} + +// Logic and data behind the server's behavior. +class KeyValueStoreServiceImpl final : public KeyValueStore::Service { + Status GetValues(ServerContext* context, ServerReaderWriter *stream) override { + Request request; + while(stream->Read(&request)) { + Response response; + response.set_value(get_value_from_map(request.key().c_str())); + stream->Write(response); + } + return Status::OK; + } +}; + +void RunServer() { + std::string server_address("0.0.0.0:50051"); + KeyValueStoreServiceImpl service; + + ServerBuilder builder; + // Listen on the given address without any authentication mechanism. + builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); + // Register "service" as the instance through which we'll communicate with + // clients. In this case it corresponds to an *synchronous* service. + builder.RegisterService(&service); + // Finally assemble the server. + std::unique_ptr server(builder.BuildAndStart()); + std::cout << "Server listening on " << server_address << std::endl; + + // Wait for the server to shutdown. Note that some other thread must be + // responsible for shutting down the server for this call to ever return. + server->Wait(); +} + +int main(int argc, char** argv) { + RunServer(); + + return 0; +} From f1e9306c702ee83f4808597212824301d3a909a5 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 10 Jan 2019 13:22:37 -0800 Subject: [PATCH 367/375] return empty string instead of nullptr --- examples/cpp/keyvaluestore/server.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/cpp/keyvaluestore/server.cc b/examples/cpp/keyvaluestore/server.cc index 75d30eb1f88..8dc8752edab 100644 --- a/examples/cpp/keyvaluestore/server.cc +++ b/examples/cpp/keyvaluestore/server.cc @@ -57,7 +57,7 @@ const char * get_value_from_map(const char* key) { return kvs_map[i].value; } } - return nullptr; + return ""; } // Logic and data behind the server's behavior. From c01e866a88beee6143f19fa243b85d5792c36cae Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 10 Jan 2019 13:25:57 -0800 Subject: [PATCH 368/375] better documentation --- examples/cpp/keyvaluestore/client.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/cpp/keyvaluestore/client.cc b/examples/cpp/keyvaluestore/client.cc index 9f5fa37cb1e..cdf353fafd1 100644 --- a/examples/cpp/keyvaluestore/client.cc +++ b/examples/cpp/keyvaluestore/client.cc @@ -41,19 +41,19 @@ class KeyValueStoreClient { KeyValueStoreClient(std::shared_ptr channel) : stub_(KeyValueStore::NewStub(channel)) {} - // Assembles the client's payload, sends it and presents the response back - // from the server. + // Requests each key in the vector and displays the value as a pair void GetValues(const std::vector& keys) { // Context for the client. It could be used to convey extra information to // the server and/or tweak certain RPC behaviors. ClientContext context; auto stream = stub_->GetValues(&context); for (const auto& key:keys) { - // Data we are sending to the server. + // Key we are sending to the server. Request request; request.set_key(key); stream->Write(request); + // Get the value for the sent key Response response; stream->Read(&response); std::cout << key << " : " << response.value() << "\n"; From aa5950936923437b45dbe75f5d981033ec00a2f9 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 10 Jan 2019 14:13:43 -0800 Subject: [PATCH 369/375] Reviewer comments --- examples/cpp/keyvaluestore/caching_interceptor.cc | 0 examples/cpp/keyvaluestore/client.cc | 3 ++- examples/cpp/keyvaluestore/server.cc | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) delete mode 100644 examples/cpp/keyvaluestore/caching_interceptor.cc diff --git a/examples/cpp/keyvaluestore/caching_interceptor.cc b/examples/cpp/keyvaluestore/caching_interceptor.cc deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/examples/cpp/keyvaluestore/client.cc b/examples/cpp/keyvaluestore/client.cc index cdf353fafd1..e956a165734 100644 --- a/examples/cpp/keyvaluestore/client.cc +++ b/examples/cpp/keyvaluestore/client.cc @@ -41,7 +41,8 @@ class KeyValueStoreClient { KeyValueStoreClient(std::shared_ptr channel) : stub_(KeyValueStore::NewStub(channel)) {} - // Requests each key in the vector and displays the value as a pair + // Requests each key in the vector and displays the key and its corresponding + // value as a pair void GetValues(const std::vector& keys) { // Context for the client. It could be used to convey extra information to // the server and/or tweak certain RPC behaviors. diff --git a/examples/cpp/keyvaluestore/server.cc b/examples/cpp/keyvaluestore/server.cc index 8dc8752edab..515a1ba4c9b 100644 --- a/examples/cpp/keyvaluestore/server.cc +++ b/examples/cpp/keyvaluestore/server.cc @@ -81,7 +81,7 @@ void RunServer() { // Listen on the given address without any authentication mechanism. builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); // Register "service" as the instance through which we'll communicate with - // clients. In this case it corresponds to an *synchronous* service. + // clients. In this case, it corresponds to an *synchronous* service. builder.RegisterService(&service); // Finally assemble the server. std::unique_ptr server(builder.BuildAndStart()); From b72bb30126b8baf8b8140266bad2009e6d3c4ded Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 10 Jan 2019 14:18:24 -0800 Subject: [PATCH 370/375] Clang format --- examples/cpp/keyvaluestore/client.cc | 8 ++++---- examples/cpp/keyvaluestore/server.cc | 20 +++++++++----------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/examples/cpp/keyvaluestore/client.cc b/examples/cpp/keyvaluestore/client.cc index e956a165734..17e407c273b 100644 --- a/examples/cpp/keyvaluestore/client.cc +++ b/examples/cpp/keyvaluestore/client.cc @@ -32,9 +32,9 @@ using grpc::Channel; using grpc::ClientContext; using grpc::Status; +using keyvaluestore::KeyValueStore; using keyvaluestore::Request; using keyvaluestore::Response; -using keyvaluestore::KeyValueStore; class KeyValueStoreClient { public: @@ -48,7 +48,7 @@ class KeyValueStoreClient { // the server and/or tweak certain RPC behaviors. ClientContext context; auto stream = stub_->GetValues(&context); - for (const auto& key:keys) { + for (const auto& key : keys) { // Key we are sending to the server. Request request; request.set_key(key); @@ -61,7 +61,7 @@ class KeyValueStoreClient { } stream->WritesDone(); Status status = stream->Finish(); - if(!status.ok()) { + if (!status.ok()) { std::cout << status.error_code() << ": " << status.error_message() << std::endl; std::cout << "RPC failed"; @@ -79,7 +79,7 @@ int main(int argc, char** argv) { // (use of InsecureChannelCredentials()). KeyValueStoreClient client(grpc::CreateChannel( "localhost:50051", grpc::InsecureChannelCredentials())); - std::vector keys = {"key1", "key2", "key3", "key4", "key5"}; + std::vector keys = {"key1", "key2", "key3", "key4", "key5"}; client.GetValues(keys); return 0; diff --git a/examples/cpp/keyvaluestore/server.cc b/examples/cpp/keyvaluestore/server.cc index 515a1ba4c9b..e75da9c62d1 100644 --- a/examples/cpp/keyvaluestore/server.cc +++ b/examples/cpp/keyvaluestore/server.cc @@ -34,9 +34,9 @@ using grpc::ServerBuilder; using grpc::ServerContext; using grpc::ServerReaderWriter; using grpc::Status; +using keyvaluestore::KeyValueStore; using keyvaluestore::Request; using keyvaluestore::Response; -using keyvaluestore::KeyValueStore; struct kv_pair { const char* key; @@ -44,16 +44,13 @@ struct kv_pair { }; static const kv_pair kvs_map[] = { - {"key1", "value1"}, - {"key2", "value2"}, - {"key3", "value3"}, - {"key4", "value4"}, - {"key5", "value5"}, + {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}, + {"key4", "value4"}, {"key5", "value5"}, }; -const char * get_value_from_map(const char* key) { - for(size_t i = 0; i < sizeof(kvs_map) / sizeof(kv_pair); ++i) { - if(strcmp(key, kvs_map[i].key) == 0) { +const char* get_value_from_map(const char* key) { + for (size_t i = 0; i < sizeof(kvs_map) / sizeof(kv_pair); ++i) { + if (strcmp(key, kvs_map[i].key) == 0) { return kvs_map[i].value; } } @@ -62,9 +59,10 @@ const char * get_value_from_map(const char* key) { // Logic and data behind the server's behavior. class KeyValueStoreServiceImpl final : public KeyValueStore::Service { - Status GetValues(ServerContext* context, ServerReaderWriter *stream) override { + Status GetValues(ServerContext* context, + ServerReaderWriter* stream) override { Request request; - while(stream->Read(&request)) { + while (stream->Read(&request)) { Response response; response.set_value(get_value_from_map(request.key().c_str())); stream->Write(response); From f36a6e9aeff37b7d14c29e817b9b573359aa5cf5 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 10 Jan 2019 18:04:36 -0800 Subject: [PATCH 371/375] Eliminate compiler warning --- src/compiler/objective_c_generator.cc | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc index af5398ec683..e806f46d814 100644 --- a/src/compiler/objective_c_generator.cc +++ b/src/compiler/objective_c_generator.cc @@ -353,20 +353,23 @@ void PrintMethodImplementations(Printer* printer, printer.Print(vars, "@implementation $service_class$\n\n" + "#pragma clang diagnostic push\n" + "#pragma clang diagnostic ignored " + "\"-Wobjc-designated-initializers\"\n\n" "// Designated initializer\n" "- (instancetype)initWithHost:(NSString *)host " "callOptions:(GRPCCallOptions *_Nullable)callOptions {\n" - " self = [super initWithHost:host\n" + " return [super initWithHost:host\n" " packageName:@\"$package$\"\n" " serviceName:@\"$service_name$\"\n" " callOptions:callOptions];\n" - " return self;\n" "}\n\n" "- (instancetype)initWithHost:(NSString *)host {\n" " return [super initWithHost:host\n" " packageName:@\"$package$\"\n" " serviceName:@\"$service_name$\"];\n" - "}\n\n"); + "}\n\n" + "#pragma clang diagnostic pop\n\n"); printer.Print( "// Override superclass initializer to disallow different" @@ -375,6 +378,12 @@ void PrintMethodImplementations(Printer* printer, " packageName:(NSString *)packageName\n" " serviceName:(NSString *)serviceName {\n" " return [self initWithHost:host];\n" + "}\n\n" + "- (instancetype)initWithHost:(NSString *)host\n" + " packageName:(NSString *)packageName\n" + " serviceName:(NSString *)serviceName\n" + " callOptions:(GRPCCallOptions *)callOptions {\n" + " return [self initWithHost:host callOptions:callOptions];\n" "}\n\n"); printer.Print( From b12dd1be055d81a68d535cc052aac804734453df Mon Sep 17 00:00:00 2001 From: Mehrdad Afshari Date: Thu, 10 Jan 2019 22:12:03 -0800 Subject: [PATCH 372/375] Fix GrpcCodegen initialization Initializing GrpcCodegen as a global static variable is problematic because it is possible for it to get destructed before the last instance of `GrpcLibraryCodegen` gets destructed and leaves the program dealing with a dangling pointer (imagine a scenario where another thread is using gRPC resources and the main thread tries to join it in an object's destructor after main ends and CoreCodegen is destructed.) In fact, Google style guide explicitly forbids non-trivially-destructible global variables of static storage duration for this and other reasons and the solution in this commit is among the recommended workarounds referenced in https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables --- include/grpcpp/impl/grpc_library.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/include/grpcpp/impl/grpc_library.h b/include/grpcpp/impl/grpc_library.h index d1f3ff1297b..3711c098790 100644 --- a/include/grpcpp/impl/grpc_library.h +++ b/include/grpcpp/impl/grpc_library.h @@ -35,18 +35,17 @@ class GrpcLibrary final : public GrpcLibraryInterface { void shutdown() override { grpc_shutdown(); } }; -static GrpcLibrary g_gli; -static CoreCodegen g_core_codegen; - /// Instantiating this class ensures the proper initialization of gRPC. class GrpcLibraryInitializer final { public: GrpcLibraryInitializer() { if (grpc::g_glip == nullptr) { - grpc::g_glip = &g_gli; + static auto* const g_gli = new GrpcLibrary(); + grpc::g_glip = g_gli; } if (grpc::g_core_codegen_interface == nullptr) { - grpc::g_core_codegen_interface = &g_core_codegen; + static auto* const g_core_codegen = new CoreCodegen(); + grpc::g_core_codegen_interface = g_core_codegen; } } From 371b987bf41af61488f19e57fc0d2a1c612d35c8 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Fri, 11 Jan 2019 09:54:16 -0800 Subject: [PATCH 373/375] Revert turning c-ares on by default --- .../client_channel/resolver/dns/c_ares/dns_resolver_ares.cc | 2 +- templates/test/cpp/naming/resolver_component_tests_defs.include | 1 + test/core/client_channel/resolvers/dns_resolver_test.cc | 2 +- test/cpp/naming/resolver_component_tests_runner.py | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index fba20000ef6..abacd0c960d 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -472,7 +472,7 @@ static grpc_address_resolver_vtable ares_resolver = { grpc_resolve_address_ares, blocking_resolve_address_ares}; static bool should_use_ares(const char* resolver_env) { - return resolver_env == nullptr || gpr_stricmp(resolver_env, "ares") == 0; + return resolver_env != nullptr && gpr_stricmp(resolver_env, "ares") == 0; } void grpc_resolver_dns_ares_init() { diff --git a/templates/test/cpp/naming/resolver_component_tests_defs.include b/templates/test/cpp/naming/resolver_component_tests_defs.include index d38316cbe68..b34845e01a3 100644 --- a/templates/test/cpp/naming/resolver_component_tests_defs.include +++ b/templates/test/cpp/naming/resolver_component_tests_defs.include @@ -55,6 +55,7 @@ if cur_resolver and cur_resolver != 'ares': 'needs to use GRPC_DNS_RESOLVER=ares.')) test_runner_log('Exit 1 without running tests.') sys.exit(1) +os.environ.update({'GRPC_DNS_RESOLVER': 'ares'}) os.environ.update({'GRPC_TRACE': 'cares_resolver'}) def wait_until_dns_server_is_up(args, diff --git a/test/core/client_channel/resolvers/dns_resolver_test.cc b/test/core/client_channel/resolvers/dns_resolver_test.cc index 6f153cc9bf6..f426eab9592 100644 --- a/test/core/client_channel/resolvers/dns_resolver_test.cc +++ b/test/core/client_channel/resolvers/dns_resolver_test.cc @@ -75,7 +75,7 @@ int main(int argc, char** argv) { test_succeeds(dns, "dns:www.google.com"); test_succeeds(dns, "dns:///www.google.com"); char* resolver_env = gpr_getenv("GRPC_DNS_RESOLVER"); - if (resolver_env != nullptr && gpr_stricmp(resolver_env, "native") == 0) { + if (resolver_env == nullptr || gpr_stricmp(resolver_env, "native") == 0) { test_fails(dns, "dns://8.8.8.8/8.8.8.8:8888"); } else { test_succeeds(dns, "dns://8.8.8.8/8.8.8.8:8888"); diff --git a/test/cpp/naming/resolver_component_tests_runner.py b/test/cpp/naming/resolver_component_tests_runner.py index 950a9d4897e..1873eec35bd 100755 --- a/test/cpp/naming/resolver_component_tests_runner.py +++ b/test/cpp/naming/resolver_component_tests_runner.py @@ -55,6 +55,7 @@ if cur_resolver and cur_resolver != 'ares': 'needs to use GRPC_DNS_RESOLVER=ares.')) test_runner_log('Exit 1 without running tests.') sys.exit(1) +os.environ.update({'GRPC_DNS_RESOLVER': 'ares'}) os.environ.update({'GRPC_TRACE': 'cares_resolver'}) def wait_until_dns_server_is_up(args, From 95965f71d3e99f6baa4a237e0a7046d51cd0441f Mon Sep 17 00:00:00 2001 From: Prashant Jaikumar Date: Fri, 11 Jan 2019 10:40:20 -0800 Subject: [PATCH 374/375] Remove network_status_tracker Remove network_status_tracker and its unit test as it does nothing. We can add tests for network status change in another commit. --- BUILD | 6 +- CMakeLists.txt | 8 - Makefile | 8 - build.yaml | 2 - config.m4 | 1 - config.w32 | 1 - gRPC-C++.podspec | 2 - gRPC-Core.podspec | 4 - grpc.gemspec | 2 - grpc.gyp | 6 - package.xml | 2 - src/core/lib/iomgr/iomgr.cc | 3 - src/core/lib/iomgr/network_status_tracker.cc | 36 - src/core/lib/iomgr/network_status_tracker.h | 32 - src/core/lib/iomgr/tcp_custom.cc | 4 - src/core/lib/iomgr/tcp_posix.cc | 13 +- src/core/lib/iomgr/tcp_uv.cc | 1 - src/core/lib/iomgr/tcp_windows.cc | 4 - .../CoreCronetEnd2EndTests.mm | 4 - src/python/grpcio/grpc_core_dependencies.py | 1 - test/core/end2end/end2end_nosec_tests.cc | 8 - test/core/end2end/end2end_tests.cc | 8 - test/core/end2end/gen_build_yaml.py | 1 - test/core/end2end/generate_tests.bzl | 1 - .../end2end/tests/network_status_change.cc | 237 ----- tools/doxygen/Doxyfile.c++.internal | 1 - tools/doxygen/Doxyfile.core.internal | 2 - .../generated/sources_and_headers.json | 5 - tools/run_tests/generated/tests.json | 883 +----------------- 29 files changed, 53 insertions(+), 1233 deletions(-) delete mode 100644 src/core/lib/iomgr/network_status_tracker.cc delete mode 100644 src/core/lib/iomgr/network_status_tracker.h delete mode 100644 test/core/end2end/tests/network_status_change.cc diff --git a/BUILD b/BUILD index 453c64ab08c..5f53bbc6f0b 100644 --- a/BUILD +++ b/BUILD @@ -724,6 +724,8 @@ grpc_cc_library( "src/core/lib/iomgr/gethostname_fallback.cc", "src/core/lib/iomgr/gethostname_host_name_max.cc", "src/core/lib/iomgr/gethostname_sysconf.cc", + "src/core/lib/iomgr/grpc_if_nametoindex_posix.cc", + "src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc", "src/core/lib/iomgr/internal_errqueue.cc", "src/core/lib/iomgr/iocp_windows.cc", "src/core/lib/iomgr/iomgr.cc", @@ -732,11 +734,8 @@ grpc_cc_library( "src/core/lib/iomgr/iomgr_posix.cc", "src/core/lib/iomgr/iomgr_windows.cc", "src/core/lib/iomgr/is_epollexclusive_available.cc", - "src/core/lib/iomgr/grpc_if_nametoindex_posix.cc", - "src/core/lib/iomgr/grpc_if_nametoindex_unsupported.cc", "src/core/lib/iomgr/load_file.cc", "src/core/lib/iomgr/lockfree_event.cc", - "src/core/lib/iomgr/network_status_tracker.cc", "src/core/lib/iomgr/polling_entity.cc", "src/core/lib/iomgr/pollset.cc", "src/core/lib/iomgr/pollset_custom.cc", @@ -886,7 +885,6 @@ grpc_cc_library( "src/core/lib/iomgr/load_file.h", "src/core/lib/iomgr/lockfree_event.h", "src/core/lib/iomgr/nameser.h", - "src/core/lib/iomgr/network_status_tracker.h", "src/core/lib/iomgr/polling_entity.h", "src/core/lib/iomgr/pollset.h", "src/core/lib/iomgr/pollset_custom.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 38f8ad915ff..13d5aca6584 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1008,7 +1008,6 @@ add_library(grpc src/core/lib/iomgr/is_epollexclusive_available.cc src/core/lib/iomgr/load_file.cc src/core/lib/iomgr/lockfree_event.cc - src/core/lib/iomgr/network_status_tracker.cc src/core/lib/iomgr/polling_entity.cc src/core/lib/iomgr/pollset.cc src/core/lib/iomgr/pollset_custom.cc @@ -1432,7 +1431,6 @@ add_library(grpc_cronet src/core/lib/iomgr/is_epollexclusive_available.cc src/core/lib/iomgr/load_file.cc src/core/lib/iomgr/lockfree_event.cc - src/core/lib/iomgr/network_status_tracker.cc src/core/lib/iomgr/polling_entity.cc src/core/lib/iomgr/pollset.cc src/core/lib/iomgr/pollset_custom.cc @@ -1840,7 +1838,6 @@ add_library(grpc_test_util src/core/lib/iomgr/is_epollexclusive_available.cc src/core/lib/iomgr/load_file.cc src/core/lib/iomgr/lockfree_event.cc - src/core/lib/iomgr/network_status_tracker.cc src/core/lib/iomgr/polling_entity.cc src/core/lib/iomgr/pollset.cc src/core/lib/iomgr/pollset_custom.cc @@ -2164,7 +2161,6 @@ add_library(grpc_test_util_unsecure src/core/lib/iomgr/is_epollexclusive_available.cc src/core/lib/iomgr/load_file.cc src/core/lib/iomgr/lockfree_event.cc - src/core/lib/iomgr/network_status_tracker.cc src/core/lib/iomgr/polling_entity.cc src/core/lib/iomgr/pollset.cc src/core/lib/iomgr/pollset_custom.cc @@ -2465,7 +2461,6 @@ add_library(grpc_unsecure src/core/lib/iomgr/is_epollexclusive_available.cc src/core/lib/iomgr/load_file.cc src/core/lib/iomgr/lockfree_event.cc - src/core/lib/iomgr/network_status_tracker.cc src/core/lib/iomgr/polling_entity.cc src/core/lib/iomgr/pollset.cc src/core/lib/iomgr/pollset_custom.cc @@ -3352,7 +3347,6 @@ add_library(grpc++_cronet src/core/lib/iomgr/is_epollexclusive_available.cc src/core/lib/iomgr/load_file.cc src/core/lib/iomgr/lockfree_event.cc - src/core/lib/iomgr/network_status_tracker.cc src/core/lib/iomgr/polling_entity.cc src/core/lib/iomgr/pollset.cc src/core/lib/iomgr/pollset_custom.cc @@ -5609,7 +5603,6 @@ add_library(end2end_tests test/core/end2end/tests/max_connection_idle.cc test/core/end2end/tests/max_message_length.cc test/core/end2end/tests/negative_deadline.cc - test/core/end2end/tests/network_status_change.cc test/core/end2end/tests/no_error_on_hotpath.cc test/core/end2end/tests/no_logging.cc test/core/end2end/tests/no_op.cc @@ -5733,7 +5726,6 @@ add_library(end2end_nosec_tests test/core/end2end/tests/max_connection_idle.cc test/core/end2end/tests/max_message_length.cc test/core/end2end/tests/negative_deadline.cc - test/core/end2end/tests/network_status_change.cc test/core/end2end/tests/no_error_on_hotpath.cc test/core/end2end/tests/no_logging.cc test/core/end2end/tests/no_op.cc diff --git a/Makefile b/Makefile index 504ef409630..00186d891c6 100644 --- a/Makefile +++ b/Makefile @@ -3525,7 +3525,6 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/is_epollexclusive_available.cc \ src/core/lib/iomgr/load_file.cc \ src/core/lib/iomgr/lockfree_event.cc \ - src/core/lib/iomgr/network_status_tracker.cc \ src/core/lib/iomgr/polling_entity.cc \ src/core/lib/iomgr/pollset.cc \ src/core/lib/iomgr/pollset_custom.cc \ @@ -3943,7 +3942,6 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/iomgr/is_epollexclusive_available.cc \ src/core/lib/iomgr/load_file.cc \ src/core/lib/iomgr/lockfree_event.cc \ - src/core/lib/iomgr/network_status_tracker.cc \ src/core/lib/iomgr/polling_entity.cc \ src/core/lib/iomgr/pollset.cc \ src/core/lib/iomgr/pollset_custom.cc \ @@ -4344,7 +4342,6 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/iomgr/is_epollexclusive_available.cc \ src/core/lib/iomgr/load_file.cc \ src/core/lib/iomgr/lockfree_event.cc \ - src/core/lib/iomgr/network_status_tracker.cc \ src/core/lib/iomgr/polling_entity.cc \ src/core/lib/iomgr/pollset.cc \ src/core/lib/iomgr/pollset_custom.cc \ @@ -4655,7 +4652,6 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \ src/core/lib/iomgr/is_epollexclusive_available.cc \ src/core/lib/iomgr/load_file.cc \ src/core/lib/iomgr/lockfree_event.cc \ - src/core/lib/iomgr/network_status_tracker.cc \ src/core/lib/iomgr/polling_entity.cc \ src/core/lib/iomgr/pollset.cc \ src/core/lib/iomgr/pollset_custom.cc \ @@ -4930,7 +4926,6 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/is_epollexclusive_available.cc \ src/core/lib/iomgr/load_file.cc \ src/core/lib/iomgr/lockfree_event.cc \ - src/core/lib/iomgr/network_status_tracker.cc \ src/core/lib/iomgr/polling_entity.cc \ src/core/lib/iomgr/pollset.cc \ src/core/lib/iomgr/pollset_custom.cc \ @@ -5794,7 +5789,6 @@ LIBGRPC++_CRONET_SRC = \ src/core/lib/iomgr/is_epollexclusive_available.cc \ src/core/lib/iomgr/load_file.cc \ src/core/lib/iomgr/lockfree_event.cc \ - src/core/lib/iomgr/network_status_tracker.cc \ src/core/lib/iomgr/polling_entity.cc \ src/core/lib/iomgr/pollset.cc \ src/core/lib/iomgr/pollset_custom.cc \ @@ -10379,7 +10373,6 @@ LIBEND2END_TESTS_SRC = \ test/core/end2end/tests/max_connection_idle.cc \ test/core/end2end/tests/max_message_length.cc \ test/core/end2end/tests/negative_deadline.cc \ - test/core/end2end/tests/network_status_change.cc \ test/core/end2end/tests/no_error_on_hotpath.cc \ test/core/end2end/tests/no_logging.cc \ test/core/end2end/tests/no_op.cc \ @@ -10496,7 +10489,6 @@ LIBEND2END_NOSEC_TESTS_SRC = \ test/core/end2end/tests/max_connection_idle.cc \ test/core/end2end/tests/max_message_length.cc \ test/core/end2end/tests/negative_deadline.cc \ - test/core/end2end/tests/network_status_change.cc \ test/core/end2end/tests/no_error_on_hotpath.cc \ test/core/end2end/tests/no_logging.cc \ test/core/end2end/tests/no_op.cc \ diff --git a/build.yaml b/build.yaml index 28375c82589..c7b4d751731 100644 --- a/build.yaml +++ b/build.yaml @@ -289,7 +289,6 @@ filegroups: - src/core/lib/iomgr/is_epollexclusive_available.cc - src/core/lib/iomgr/load_file.cc - src/core/lib/iomgr/lockfree_event.cc - - src/core/lib/iomgr/network_status_tracker.cc - src/core/lib/iomgr/polling_entity.cc - src/core/lib/iomgr/pollset.cc - src/core/lib/iomgr/pollset_custom.cc @@ -465,7 +464,6 @@ filegroups: - src/core/lib/iomgr/load_file.h - src/core/lib/iomgr/lockfree_event.h - src/core/lib/iomgr/nameser.h - - src/core/lib/iomgr/network_status_tracker.h - src/core/lib/iomgr/polling_entity.h - src/core/lib/iomgr/pollset.h - src/core/lib/iomgr/pollset_custom.h diff --git a/config.m4 b/config.m4 index 3c3c0210d87..ccb218a1200 100644 --- a/config.m4 +++ b/config.m4 @@ -141,7 +141,6 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/is_epollexclusive_available.cc \ src/core/lib/iomgr/load_file.cc \ src/core/lib/iomgr/lockfree_event.cc \ - src/core/lib/iomgr/network_status_tracker.cc \ src/core/lib/iomgr/polling_entity.cc \ src/core/lib/iomgr/pollset.cc \ src/core/lib/iomgr/pollset_custom.cc \ diff --git a/config.w32 b/config.w32 index f87859ad09f..fd48ec6f485 100644 --- a/config.w32 +++ b/config.w32 @@ -116,7 +116,6 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\iomgr\\is_epollexclusive_available.cc " + "src\\core\\lib\\iomgr\\load_file.cc " + "src\\core\\lib\\iomgr\\lockfree_event.cc " + - "src\\core\\lib\\iomgr\\network_status_tracker.cc " + "src\\core\\lib\\iomgr\\polling_entity.cc " + "src\\core\\lib\\iomgr\\pollset.cc " + "src\\core\\lib\\iomgr\\pollset_custom.cc " + diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 4e0a471fb44..bf124304487 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -434,7 +434,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/load_file.h', 'src/core/lib/iomgr/lockfree_event.h', 'src/core/lib/iomgr/nameser.h', - 'src/core/lib/iomgr/network_status_tracker.h', 'src/core/lib/iomgr/polling_entity.h', 'src/core/lib/iomgr/pollset.h', 'src/core/lib/iomgr/pollset_custom.h', @@ -628,7 +627,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/load_file.h', 'src/core/lib/iomgr/lockfree_event.h', 'src/core/lib/iomgr/nameser.h', - 'src/core/lib/iomgr/network_status_tracker.h', 'src/core/lib/iomgr/polling_entity.h', 'src/core/lib/iomgr/pollset.h', 'src/core/lib/iomgr/pollset_custom.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 4e4c8662411..60f34ebd6a2 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -428,7 +428,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/load_file.h', 'src/core/lib/iomgr/lockfree_event.h', 'src/core/lib/iomgr/nameser.h', - 'src/core/lib/iomgr/network_status_tracker.h', 'src/core/lib/iomgr/polling_entity.h', 'src/core/lib/iomgr/pollset.h', 'src/core/lib/iomgr/pollset_custom.h', @@ -585,7 +584,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/is_epollexclusive_available.cc', 'src/core/lib/iomgr/load_file.cc', 'src/core/lib/iomgr/lockfree_event.cc', - 'src/core/lib/iomgr/network_status_tracker.cc', 'src/core/lib/iomgr/polling_entity.cc', 'src/core/lib/iomgr/pollset.cc', 'src/core/lib/iomgr/pollset_custom.cc', @@ -1054,7 +1052,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/load_file.h', 'src/core/lib/iomgr/lockfree_event.h', 'src/core/lib/iomgr/nameser.h', - 'src/core/lib/iomgr/network_status_tracker.h', 'src/core/lib/iomgr/polling_entity.h', 'src/core/lib/iomgr/pollset.h', 'src/core/lib/iomgr/pollset_custom.h', @@ -1300,7 +1297,6 @@ Pod::Spec.new do |s| 'test/core/end2end/tests/max_connection_idle.cc', 'test/core/end2end/tests/max_message_length.cc', 'test/core/end2end/tests/negative_deadline.cc', - 'test/core/end2end/tests/network_status_change.cc', 'test/core/end2end/tests/no_error_on_hotpath.cc', 'test/core/end2end/tests/no_logging.cc', 'test/core/end2end/tests/no_op.cc', diff --git a/grpc.gemspec b/grpc.gemspec index 42b1db35b4d..60c5bc480b6 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -364,7 +364,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/load_file.h ) s.files += %w( src/core/lib/iomgr/lockfree_event.h ) s.files += %w( src/core/lib/iomgr/nameser.h ) - s.files += %w( src/core/lib/iomgr/network_status_tracker.h ) s.files += %w( src/core/lib/iomgr/polling_entity.h ) s.files += %w( src/core/lib/iomgr/pollset.h ) s.files += %w( src/core/lib/iomgr/pollset_custom.h ) @@ -521,7 +520,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/is_epollexclusive_available.cc ) s.files += %w( src/core/lib/iomgr/load_file.cc ) s.files += %w( src/core/lib/iomgr/lockfree_event.cc ) - s.files += %w( src/core/lib/iomgr/network_status_tracker.cc ) s.files += %w( src/core/lib/iomgr/polling_entity.cc ) s.files += %w( src/core/lib/iomgr/pollset.cc ) s.files += %w( src/core/lib/iomgr/pollset_custom.cc ) diff --git a/grpc.gyp b/grpc.gyp index 13b9c1bc78b..1f5b6384975 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -323,7 +323,6 @@ 'src/core/lib/iomgr/is_epollexclusive_available.cc', 'src/core/lib/iomgr/load_file.cc', 'src/core/lib/iomgr/lockfree_event.cc', - 'src/core/lib/iomgr/network_status_tracker.cc', 'src/core/lib/iomgr/polling_entity.cc', 'src/core/lib/iomgr/pollset.cc', 'src/core/lib/iomgr/pollset_custom.cc', @@ -687,7 +686,6 @@ 'src/core/lib/iomgr/is_epollexclusive_available.cc', 'src/core/lib/iomgr/load_file.cc', 'src/core/lib/iomgr/lockfree_event.cc', - 'src/core/lib/iomgr/network_status_tracker.cc', 'src/core/lib/iomgr/polling_entity.cc', 'src/core/lib/iomgr/pollset.cc', 'src/core/lib/iomgr/pollset_custom.cc', @@ -931,7 +929,6 @@ 'src/core/lib/iomgr/is_epollexclusive_available.cc', 'src/core/lib/iomgr/load_file.cc', 'src/core/lib/iomgr/lockfree_event.cc', - 'src/core/lib/iomgr/network_status_tracker.cc', 'src/core/lib/iomgr/polling_entity.cc', 'src/core/lib/iomgr/pollset.cc', 'src/core/lib/iomgr/pollset_custom.cc', @@ -1152,7 +1149,6 @@ 'src/core/lib/iomgr/is_epollexclusive_available.cc', 'src/core/lib/iomgr/load_file.cc', 'src/core/lib/iomgr/lockfree_event.cc', - 'src/core/lib/iomgr/network_status_tracker.cc', 'src/core/lib/iomgr/polling_entity.cc', 'src/core/lib/iomgr/pollset.cc', 'src/core/lib/iomgr/pollset_custom.cc', @@ -2721,7 +2717,6 @@ 'test/core/end2end/tests/max_connection_idle.cc', 'test/core/end2end/tests/max_message_length.cc', 'test/core/end2end/tests/negative_deadline.cc', - 'test/core/end2end/tests/network_status_change.cc', 'test/core/end2end/tests/no_error_on_hotpath.cc', 'test/core/end2end/tests/no_logging.cc', 'test/core/end2end/tests/no_op.cc', @@ -2811,7 +2806,6 @@ 'test/core/end2end/tests/max_connection_idle.cc', 'test/core/end2end/tests/max_message_length.cc', 'test/core/end2end/tests/negative_deadline.cc', - 'test/core/end2end/tests/network_status_change.cc', 'test/core/end2end/tests/no_error_on_hotpath.cc', 'test/core/end2end/tests/no_logging.cc', 'test/core/end2end/tests/no_op.cc', diff --git a/package.xml b/package.xml index de5c56f4511..81a4aabdf5a 100644 --- a/package.xml +++ b/package.xml @@ -369,7 +369,6 @@ - @@ -526,7 +525,6 @@ - diff --git a/src/core/lib/iomgr/iomgr.cc b/src/core/lib/iomgr/iomgr.cc index a4921468578..dcc69332e0b 100644 --- a/src/core/lib/iomgr/iomgr.cc +++ b/src/core/lib/iomgr/iomgr.cc @@ -38,7 +38,6 @@ #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/internal_errqueue.h" #include "src/core/lib/iomgr/iomgr_internal.h" -#include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer_manager.h" @@ -57,7 +56,6 @@ void grpc_iomgr_init() { grpc_timer_list_init(); g_root_object.next = g_root_object.prev = &g_root_object; g_root_object.name = (char*)"root"; - grpc_network_status_init(); grpc_iomgr_platform_init(); grpc_core::grpc_errqueue_init(); } @@ -152,7 +150,6 @@ void grpc_iomgr_shutdown() { gpr_mu_unlock(&g_mu); grpc_iomgr_platform_shutdown(); - grpc_network_status_shutdown(); gpr_mu_destroy(&g_mu); gpr_cv_destroy(&g_rcv); } diff --git a/src/core/lib/iomgr/network_status_tracker.cc b/src/core/lib/iomgr/network_status_tracker.cc deleted file mode 100644 index d4b7f4a57d1..00000000000 --- a/src/core/lib/iomgr/network_status_tracker.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/lib/iomgr/endpoint.h" -#include "src/core/lib/iomgr/network_status_tracker.h" - -void grpc_network_status_shutdown(void) {} - -void grpc_network_status_init(void) { - // TODO(makarandd): Install callback with OS to monitor network status. -} - -void grpc_destroy_network_status_monitor() {} - -void grpc_network_status_register_endpoint(grpc_endpoint* ep) { (void)ep; } - -void grpc_network_status_unregister_endpoint(grpc_endpoint* ep) { (void)ep; } - -void grpc_network_status_shutdown_all_endpoints() {} diff --git a/src/core/lib/iomgr/network_status_tracker.h b/src/core/lib/iomgr/network_status_tracker.h deleted file mode 100644 index 198877f60f8..00000000000 --- a/src/core/lib/iomgr/network_status_tracker.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H -#define GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H -#include - -#include "src/core/lib/iomgr/endpoint.h" - -void grpc_network_status_init(void); -void grpc_network_status_shutdown(void); - -void grpc_network_status_register_endpoint(grpc_endpoint* ep); -void grpc_network_status_unregister_endpoint(grpc_endpoint* ep); -void grpc_network_status_shutdown_all_endpoints(); - -#endif /* GRPC_CORE_LIB_IOMGR_NETWORK_STATUS_TRACKER_H */ diff --git a/src/core/lib/iomgr/tcp_custom.cc b/src/core/lib/iomgr/tcp_custom.cc index f7a5f36cdcd..1e5696e1279 100644 --- a/src/core/lib/iomgr/tcp_custom.cc +++ b/src/core/lib/iomgr/tcp_custom.cc @@ -31,7 +31,6 @@ #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/iomgr_custom.h" -#include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/resource_quota.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_custom.h" @@ -309,7 +308,6 @@ static void custom_close_callback(grpc_custom_socket* socket) { } static void endpoint_destroy(grpc_endpoint* ep) { - grpc_network_status_unregister_endpoint(ep); custom_tcp_endpoint* tcp = (custom_tcp_endpoint*)ep; grpc_custom_socket_vtable->close(tcp->socket, custom_close_callback); } @@ -361,8 +359,6 @@ grpc_endpoint* custom_tcp_endpoint_create(grpc_custom_socket* socket, tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); grpc_resource_user_slice_allocator_init( &tcp->slice_allocator, tcp->resource_user, tcp_read_allocation_done, tcp); - /* Tell network status tracking code about the new endpoint */ - grpc_network_status_register_endpoint(&tcp->base); return &tcp->base; } diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index c268c18664a..d0642c015ff 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -22,7 +22,6 @@ #ifdef GRPC_POSIX_SOCKET_TCP -#include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/tcp_posix.h" #include @@ -127,9 +126,8 @@ struct grpc_tcp { bool socket_ts_enabled; /* True if timestamping options are set on the socket */ bool ts_capable; /* Cache whether we can set timestamping options */ - gpr_atm - stop_error_notification; /* Set to 1 if we do not want to be notified on - errors anymore */ + gpr_atm stop_error_notification; /* Set to 1 if we do not want to be notified + on errors anymore */ }; struct backup_poller { @@ -388,7 +386,6 @@ static void tcp_ref(grpc_tcp* tcp) { gpr_ref(&tcp->refcount); } #endif static void tcp_destroy(grpc_endpoint* ep) { - grpc_network_status_unregister_endpoint(ep); grpc_tcp* tcp = reinterpret_cast(ep); grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); if (grpc_event_engine_can_track_errors()) { @@ -701,7 +698,8 @@ static void process_errors(grpc_tcp* tcp) { union { char rbuf[1024 /*CMSG_SPACE(sizeof(scm_timestamping)) + - CMSG_SPACE(sizeof(sock_extended_err) + sizeof(sockaddr_in))*/]; + CMSG_SPACE(sizeof(sock_extended_err) + sizeof(sockaddr_in))*/ + ]; struct cmsghdr align; } aligned_buf; memset(&aligned_buf, 0, sizeof(aligned_buf)); @@ -1131,8 +1129,6 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd, tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); grpc_resource_user_slice_allocator_init( &tcp->slice_allocator, tcp->resource_user, tcp_read_allocation_done, tcp); - /* Tell network status tracker about new endpoint */ - grpc_network_status_register_endpoint(&tcp->base); grpc_resource_quota_unref_internal(resource_quota); gpr_mu_init(&tcp->tb_mu); tcp->tb_head = nullptr; @@ -1159,7 +1155,6 @@ int grpc_tcp_fd(grpc_endpoint* ep) { void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd, grpc_closure* done) { - grpc_network_status_unregister_endpoint(ep); grpc_tcp* tcp = reinterpret_cast(ep); GPR_ASSERT(ep->vtable == &vtable); tcp->release_fd = fd; diff --git a/src/core/lib/iomgr/tcp_uv.cc b/src/core/lib/iomgr/tcp_uv.cc index 8d0e4a5e79e..e53ff472fef 100644 --- a/src/core/lib/iomgr/tcp_uv.cc +++ b/src/core/lib/iomgr/tcp_uv.cc @@ -33,7 +33,6 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/iomgr_custom.h" -#include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/resolve_address_custom.h" #include "src/core/lib/iomgr/resource_quota.h" #include "src/core/lib/iomgr/tcp_custom.h" diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc index 86ee1010cf7..43817c5a024 100644 --- a/src/core/lib/iomgr/tcp_windows.cc +++ b/src/core/lib/iomgr/tcp_windows.cc @@ -24,7 +24,6 @@ #include -#include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/sockaddr_windows.h" #include @@ -470,7 +469,6 @@ static void win_shutdown(grpc_endpoint* ep, grpc_error* why) { } static void win_destroy(grpc_endpoint* ep) { - grpc_network_status_unregister_endpoint(ep); grpc_tcp* tcp = (grpc_tcp*)ep; grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); TCP_UNREF(tcp, "destroy"); @@ -526,8 +524,6 @@ grpc_endpoint* grpc_tcp_create(grpc_winsocket* socket, tcp->peer_string = gpr_strdup(peer_string); grpc_slice_buffer_init(&tcp->last_read_buffer); tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string); - /* Tell network status tracking code about the new endpoint */ - grpc_network_status_register_endpoint(&tcp->base); grpc_resource_quota_unref_internal(resource_quota); return &tcp->base; diff --git a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm index fe85e915d4d..2fac1be3d0e 100644 --- a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm +++ b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm @@ -318,10 +318,6 @@ static char *roots_filename; [self testIndividualCase:(char *)"negative_deadline"]; } -- (void)testNetworkStatusChange { - [self testIndividualCase:(char *)"network_status_change"]; -} - - (void)testNoOp { [self testIndividualCase:(char *)"no_op"]; } diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 06de23903cb..f5e43ca657e 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -115,7 +115,6 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/is_epollexclusive_available.cc', 'src/core/lib/iomgr/load_file.cc', 'src/core/lib/iomgr/lockfree_event.cc', - 'src/core/lib/iomgr/network_status_tracker.cc', 'src/core/lib/iomgr/polling_entity.cc', 'src/core/lib/iomgr/pollset.cc', 'src/core/lib/iomgr/pollset_custom.cc', diff --git a/test/core/end2end/end2end_nosec_tests.cc b/test/core/end2end/end2end_nosec_tests.cc index c6a4005fb3e..614d1f98e2b 100644 --- a/test/core/end2end/end2end_nosec_tests.cc +++ b/test/core/end2end/end2end_nosec_tests.cc @@ -98,8 +98,6 @@ extern void max_message_length(grpc_end2end_test_config config); extern void max_message_length_pre_init(void); extern void negative_deadline(grpc_end2end_test_config config); extern void negative_deadline_pre_init(void); -extern void network_status_change(grpc_end2end_test_config config); -extern void network_status_change_pre_init(void); extern void no_error_on_hotpath(grpc_end2end_test_config config); extern void no_error_on_hotpath_pre_init(void); extern void no_logging(grpc_end2end_test_config config); @@ -223,7 +221,6 @@ void grpc_end2end_tests_pre_init(void) { max_connection_idle_pre_init(); max_message_length_pre_init(); negative_deadline_pre_init(); - network_status_change_pre_init(); no_error_on_hotpath_pre_init(); no_logging_pre_init(); no_op_pre_init(); @@ -309,7 +306,6 @@ void grpc_end2end_tests(int argc, char **argv, max_connection_idle(config); max_message_length(config); negative_deadline(config); - network_status_change(config); no_error_on_hotpath(config); no_logging(config); no_op(config); @@ -492,10 +488,6 @@ void grpc_end2end_tests(int argc, char **argv, negative_deadline(config); continue; } - if (0 == strcmp("network_status_change", argv[i])) { - network_status_change(config); - continue; - } if (0 == strcmp("no_error_on_hotpath", argv[i])) { no_error_on_hotpath(config); continue; diff --git a/test/core/end2end/end2end_tests.cc b/test/core/end2end/end2end_tests.cc index 7748a39cb59..9d3d231b3c5 100644 --- a/test/core/end2end/end2end_tests.cc +++ b/test/core/end2end/end2end_tests.cc @@ -100,8 +100,6 @@ extern void max_message_length(grpc_end2end_test_config config); extern void max_message_length_pre_init(void); extern void negative_deadline(grpc_end2end_test_config config); extern void negative_deadline_pre_init(void); -extern void network_status_change(grpc_end2end_test_config config); -extern void network_status_change_pre_init(void); extern void no_error_on_hotpath(grpc_end2end_test_config config); extern void no_error_on_hotpath_pre_init(void); extern void no_logging(grpc_end2end_test_config config); @@ -226,7 +224,6 @@ void grpc_end2end_tests_pre_init(void) { max_connection_idle_pre_init(); max_message_length_pre_init(); negative_deadline_pre_init(); - network_status_change_pre_init(); no_error_on_hotpath_pre_init(); no_logging_pre_init(); no_op_pre_init(); @@ -313,7 +310,6 @@ void grpc_end2end_tests(int argc, char **argv, max_connection_idle(config); max_message_length(config); negative_deadline(config); - network_status_change(config); no_error_on_hotpath(config); no_logging(config); no_op(config); @@ -500,10 +496,6 @@ void grpc_end2end_tests(int argc, char **argv, negative_deadline(config); continue; } - if (0 == strcmp("network_status_change", argv[i])) { - network_status_change(config); - continue; - } if (0 == strcmp("no_error_on_hotpath", argv[i])) { no_error_on_hotpath(config); continue; diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index 28a7a4e25d6..0ff1b7ee796 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -146,7 +146,6 @@ END2END_TESTS = { proxyable=False, exclude_iomgrs=['uv'], cpu_cost=LOWCPU), 'max_message_length': default_test_options._replace(cpu_cost=LOWCPU), 'negative_deadline': default_test_options, - 'network_status_change': default_test_options._replace(cpu_cost=LOWCPU), 'no_error_on_hotpath': default_test_options._replace(proxyable=False), 'no_logging': default_test_options._replace(traceable=False), 'no_op': default_test_options, diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index 853619fcdaf..ec32aa5102c 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -234,7 +234,6 @@ END2END_TESTS = { "max_connection_idle": _test_options(needs_fullstack = True, proxyable = False), "max_message_length": _test_options(), "negative_deadline": _test_options(), - "network_status_change": _test_options(), "no_error_on_hotpath": _test_options(proxyable = False), "no_logging": _test_options(traceable = False), "no_op": _test_options(), diff --git a/test/core/end2end/tests/network_status_change.cc b/test/core/end2end/tests/network_status_change.cc deleted file mode 100644 index 98a95582046..00000000000 --- a/test/core/end2end/tests/network_status_change.cc +++ /dev/null @@ -1,237 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "test/core/end2end/end2end_tests.h" - -#include -#include - -#include -#include -#include -#include -#include "test/core/end2end/cq_verifier.h" - -/* this is a private API but exposed here for testing*/ -extern void grpc_network_status_shutdown_all_endpoints(); - -static void* tag(intptr_t t) { return (void*)t; } - -static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, - const char* test_name, - grpc_channel_args* client_args, - grpc_channel_args* server_args) { - grpc_end2end_test_fixture f; - gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); - f = config.create_fixture(client_args, server_args); - config.init_server(&f, server_args); - config.init_client(&f, client_args); - return f; -} - -static gpr_timespec n_seconds_from_now(int n) { - return grpc_timeout_seconds_to_deadline(n); -} - -static gpr_timespec five_seconds_from_now(void) { - return n_seconds_from_now(500); -} - -static void drain_cq(grpc_completion_queue* cq) { - grpc_event ev; - do { - ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr); - } while (ev.type != GRPC_QUEUE_SHUTDOWN); -} - -static void shutdown_server(grpc_end2end_test_fixture* f) { - if (!f->server) return; - grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000)); - GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000), - grpc_timeout_seconds_to_deadline(5), - nullptr) - .type == GRPC_OP_COMPLETE); - grpc_server_destroy(f->server); - f->server = nullptr; -} - -static void shutdown_client(grpc_end2end_test_fixture* f) { - if (!f->client) return; - grpc_channel_destroy(f->client); - f->client = nullptr; -} - -static void end_test(grpc_end2end_test_fixture* f) { - shutdown_server(f); - shutdown_client(f); - - grpc_completion_queue_shutdown(f->cq); - drain_cq(f->cq); - grpc_completion_queue_destroy(f->cq); - grpc_completion_queue_destroy(f->shutdown_cq); -} - -/* Client sends a request with payload, server reads then returns status. */ -static void test_invoke_network_status_change(grpc_end2end_test_config config) { - grpc_call* c; - grpc_call* s; - grpc_slice request_payload_slice = - grpc_slice_from_copied_string("hello world"); - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_end2end_test_fixture f = - begin_test(config, "test_invoke_request_with_payload", nullptr, nullptr); - cq_verifier* cqv = cq_verifier_create(f.cq); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = five_seconds_from_now(); - c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), nullptr, - deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), tag(1), - nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( - f.server, &s, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101))); - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - cq_verify(cqv); - - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), tag(102), - nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(102), 1); - cq_verify(cqv); - - // Simulate the network loss event - grpc_network_status_shutdown_all_endpoints(); - - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), tag(103), - nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - // TODO(makdharma) Update this when the shutdown_all_endpoints is implemented. - // Expected behavior of a RPC when network is lost. - // GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); - GPR_ASSERT(status == GRPC_STATUS_OK); - - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(request_payload_recv); - - end_test(&f); - config.tear_down_data(&f); -} - -void network_status_change(grpc_end2end_test_config config) { - if (config.feature_mask & - FEATURE_MASK_DOES_NOT_SUPPORT_NETWORK_STATUS_CHANGE) { - return; - } - test_invoke_network_status_change(config); -} - -void network_status_change_pre_init(void) {} diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index a76a261d071..363df22aa15 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1111,7 +1111,6 @@ src/core/lib/iomgr/is_epollexclusive_available.h \ src/core/lib/iomgr/load_file.h \ src/core/lib/iomgr/lockfree_event.h \ src/core/lib/iomgr/nameser.h \ -src/core/lib/iomgr/network_status_tracker.h \ src/core/lib/iomgr/polling_entity.h \ src/core/lib/iomgr/pollset.h \ src/core/lib/iomgr/pollset_custom.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 38d17b6f21f..bb350550e94 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1238,8 +1238,6 @@ src/core/lib/iomgr/load_file.h \ src/core/lib/iomgr/lockfree_event.cc \ src/core/lib/iomgr/lockfree_event.h \ src/core/lib/iomgr/nameser.h \ -src/core/lib/iomgr/network_status_tracker.cc \ -src/core/lib/iomgr/network_status_tracker.h \ src/core/lib/iomgr/polling_entity.cc \ src/core/lib/iomgr/polling_entity.h \ src/core/lib/iomgr/pollset.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 1478ac2cd5e..197de64dbe1 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -8809,7 +8809,6 @@ "test/core/end2end/tests/max_connection_idle.cc", "test/core/end2end/tests/max_message_length.cc", "test/core/end2end/tests/negative_deadline.cc", - "test/core/end2end/tests/network_status_change.cc", "test/core/end2end/tests/no_error_on_hotpath.cc", "test/core/end2end/tests/no_logging.cc", "test/core/end2end/tests/no_op.cc", @@ -8908,7 +8907,6 @@ "test/core/end2end/tests/max_connection_idle.cc", "test/core/end2end/tests/max_message_length.cc", "test/core/end2end/tests/negative_deadline.cc", - "test/core/end2end/tests/network_status_change.cc", "test/core/end2end/tests/no_error_on_hotpath.cc", "test/core/end2end/tests/no_logging.cc", "test/core/end2end/tests/no_op.cc", @@ -9416,7 +9414,6 @@ "src/core/lib/iomgr/is_epollexclusive_available.cc", "src/core/lib/iomgr/load_file.cc", "src/core/lib/iomgr/lockfree_event.cc", - "src/core/lib/iomgr/network_status_tracker.cc", "src/core/lib/iomgr/polling_entity.cc", "src/core/lib/iomgr/pollset.cc", "src/core/lib/iomgr/pollset_custom.cc", @@ -9593,7 +9590,6 @@ "src/core/lib/iomgr/load_file.h", "src/core/lib/iomgr/lockfree_event.h", "src/core/lib/iomgr/nameser.h", - "src/core/lib/iomgr/network_status_tracker.h", "src/core/lib/iomgr/polling_entity.h", "src/core/lib/iomgr/pollset.h", "src/core/lib/iomgr/pollset_custom.h", @@ -9747,7 +9743,6 @@ "src/core/lib/iomgr/load_file.h", "src/core/lib/iomgr/lockfree_event.h", "src/core/lib/iomgr/nameser.h", - "src/core/lib/iomgr/network_status_tracker.h", "src/core/lib/iomgr/polling_entity.h", "src/core/lib/iomgr/pollset.h", "src/core/lib/iomgr/pollset_custom.h", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index f2d0cab5ede..6c667f10c48 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -8183,29 +8183,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_census_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -9958,29 +9935,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_compress_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -11675,28 +11629,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_fakesec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -13266,29 +13198,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_fd_test", - "platforms": [ - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -14627,29 +14536,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_full_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -16258,25 +16144,6 @@ "linux" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "linux" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_full+pipe_test", - "platforms": [ - "linux" - ] - }, { "args": [ "no_error_on_hotpath" @@ -17842,29 +17709,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_full+trace_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -19594,29 +19438,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_full+workarounds_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -21400,30 +21221,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_http_proxy_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -23191,29 +22988,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_local_ipv4_test", - "platforms": [ - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -24918,14 +24692,14 @@ }, { "args": [ - "network_status_change" + "no_error_on_hotpath" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -24941,7 +24715,7 @@ }, { "args": [ - "no_error_on_hotpath" + "no_logging" ], "ci_platforms": [ "linux", @@ -24964,7 +24738,7 @@ }, { "args": [ - "no_logging" + "no_op" ], "ci_platforms": [ "linux", @@ -24987,7 +24761,7 @@ }, { "args": [ - "no_op" + "payload" ], "ci_platforms": [ "linux", @@ -25010,14 +24784,14 @@ }, { "args": [ - "payload" + "ping" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -25033,7 +24807,7 @@ }, { "args": [ - "ping" + "ping_pong_streaming" ], "ci_platforms": [ "linux", @@ -25056,14 +24830,14 @@ }, { "args": [ - "ping_pong_streaming" + "registered_call" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -25079,14 +24853,14 @@ }, { "args": [ - "registered_call" + "request_with_flags" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -25102,7 +24876,7 @@ }, { "args": [ - "request_with_flags" + "request_with_payload" ], "ci_platforms": [ "linux", @@ -25125,14 +24899,14 @@ }, { "args": [ - "request_with_payload" + "resource_quota_server" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -25148,14 +24922,14 @@ }, { "args": [ - "resource_quota_server" + "retry" ], "ci_platforms": [ "linux", "mac", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -25171,7 +24945,7 @@ }, { "args": [ - "retry" + "retry_cancellation" ], "ci_platforms": [ "linux", @@ -25194,7 +24968,7 @@ }, { "args": [ - "retry_cancellation" + "retry_disabled" ], "ci_platforms": [ "linux", @@ -25217,7 +24991,7 @@ }, { "args": [ - "retry_disabled" + "retry_exceeds_buffer_size_in_initial_batch" ], "ci_platforms": [ "linux", @@ -25240,30 +25014,7 @@ }, { "args": [ - "retry_exceeds_buffer_size_in_initial_batch" - ], - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_local_ipv6_test", - "platforms": [ - "linux", - "mac", - "posix" - ] - }, - { - "args": [ - "retry_exceeds_buffer_size_in_subsequent_batch" + "retry_exceeds_buffer_size_in_subsequent_batch" ], "ci_platforms": [ "linux", @@ -26641,29 +26392,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_local_uds_test", - "platforms": [ - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -28447,30 +28175,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_oauth2_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -30127,30 +29831,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_proxy_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_logging" @@ -31327,30 +31007,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -32575,30 +32231,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair+trace_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -33857,32 +33489,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [ - "msan" - ], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair_1byte_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -35264,29 +34870,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_ssl_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -36902,30 +36485,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_ssl_proxy_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_logging" @@ -38165,29 +37724,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_uds_test", - "platforms": [ - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -39662,7 +39198,7 @@ }, { "args": [ - "network_status_change" + "no_error_on_hotpath" ], "ci_platforms": [ "windows", @@ -39670,7 +39206,7 @@ "mac", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [], "flaky": false, @@ -39685,53 +39221,30 @@ }, { "args": [ - "no_error_on_hotpath" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 1.0, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "inproc_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, - { - "args": [ - "no_logging" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 1.0, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "inproc_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, - { - "args": [ - "no_op" + "no_logging" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "inproc_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "no_op" ], "ci_platforms": [ "windows", @@ -40883,29 +40396,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_census_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -42635,29 +42125,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_compress_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -44222,29 +43689,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_fd_nosec_test", - "platforms": [ - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -45560,29 +45004,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_full_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -47172,25 +46593,6 @@ "linux" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "linux" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_full+pipe_nosec_test", - "platforms": [ - "linux" - ] - }, { "args": [ "no_error_on_hotpath" @@ -48733,29 +48135,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_full+trace_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -50462,29 +49841,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [], - "flaky": false, - "language": "c", - "name": "h2_full+workarounds_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -52244,30 +51600,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_http_proxy_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -53924,30 +53256,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_proxy_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_logging" @@ -55100,30 +54408,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -56324,30 +55608,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair+trace_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -57580,32 +56840,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [ - "msan" - ], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair_1byte_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" @@ -58914,29 +58148,6 @@ "posix" ] }, - { - "args": [ - "network_status_change" - ], - "ci_platforms": [ - "linux", - "mac", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_uds_nosec_test", - "platforms": [ - "linux", - "mac", - "posix" - ] - }, { "args": [ "no_error_on_hotpath" From 4d391b64e12bb14fc894f5699884c1b029e9078c Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Fri, 11 Jan 2019 13:35:02 -0800 Subject: [PATCH 375/375] avoid AttributeError when object init fails --- src/python/grpcio/grpc/_channel.py | 2 +- src/python/grpcio/grpc/_server.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py index 8051fb306cd..3685969c7fe 100644 --- a/src/python/grpcio/grpc/_channel.py +++ b/src/python/grpcio/grpc/_channel.py @@ -1063,5 +1063,5 @@ class Channel(grpc.Channel): cygrpc.fork_unregister_channel(self) # This prevent the failed-at-initializing object removal from failing. # Though the __init__ failed, the removal will still trigger __del__. - if _moot is not None and hasattr(self, "_connectivity_state"): + if _moot is not None and hasattr(self, '_connectivity_state'): _moot(self._connectivity_state) diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py index eb750ef1a82..c3ff1fa6bd3 100644 --- a/src/python/grpcio/grpc/_server.py +++ b/src/python/grpcio/grpc/_server.py @@ -860,9 +860,10 @@ class _Server(grpc.Server): return _stop(self._state, grace) def __del__(self): - # We can not grab a lock in __del__(), so set a flag to signal the - # serving daemon thread (if it exists) to initiate shutdown. - self._state.server_deallocated = True + if hasattr(self, '_state'): + # We can not grab a lock in __del__(), so set a flag to signal the + # serving daemon thread (if it exists) to initiate shutdown. + self._state.server_deallocated = True def create_server(thread_pool, generic_rpc_handlers, interceptors, options,