From 4924a2143470af4f7802230a3875e2cf3ddb9a53 Mon Sep 17 00:00:00 2001 From: Wilson Date: Fri, 9 Mar 2018 23:12:15 -0800 Subject: [PATCH 001/218] Improve clarity of Compression Method Asymmetry Between Peers section --- doc/compression.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/compression.md b/doc/compression.md index b8cdfb30485..15e35ae350c 100644 --- a/doc/compression.md +++ b/doc/compression.md @@ -30,7 +30,7 @@ configured: therefore the compression that SHALL be used in the absence of per-RPC compression configuration. + At response time, via: - + For unary RPCs, the {Client,Server}Context instance. + + For unary RPCs, the {Client,Server}Context instance. + For streaming RPCs, the {Client,Server}Writer instance. In this case, configuration is reduced to disabling compression altogether. @@ -41,14 +41,14 @@ of the request, including not performing any compression, regardless of channel and RPC settings (for example, if compression would result in small or negative gains). -When a message from a client compressed with an unsupported algorithm is -processed by a server, it WILL result in an `UNIMPLEMENTED` error status on the -server. The server will then include in its response a `grpc-accept-encoding` -header specifying the algorithms it does accept. If an `UNIMPLEMENTED` error -status is returned from the server despite having used one of the algorithms -from the `grpc-accept-encoding` header, the cause MUST NOT be related to -compression. Data sent from a server compressed with an algorithm not supported -by the client WILL result in an `INTERNAL` error status on the client side. +If a client message is compressed by an algorithm that is not supported +by a server, the message WILL result in an `UNIMPLEMENTED` error status on the +server. The server will then include a `grpc-accept-encoding` response +header which specifies the algorithms that the server accepts. If the client +message is compressed using one of the algorithms from the `grpc-accept-encoding` header +and an `UNIMPLEMENTED` error status is returned from the server, the cause of the error +MUST NOT be related to compression. If a server sent data which is compressed by an algorithm +that is not supported by the client, an `INTERNAL` error status will occur on the client side. Note that a peer MAY choose to not disclose all the encodings it supports. However, if it receives a message compressed in an undisclosed but supported @@ -57,7 +57,7 @@ header. For every message a server is requested to compress using an algorithm it knows the client doesn't support (as indicated by the last `grpc-accept-encoding` -header received from the client), it SHALL send the message uncompressed. +header received from the client), it SHALL send the message uncompressed. ### Specific Disabling of Compression From a4e9f33b85cb9fde3cb1ed51ae4b8e28811967a7 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Tue, 13 Nov 2018 16:38:44 -0800 Subject: [PATCH 002/218] Add interop cloud to prod test for GoogleDefaultCredentials --- doc/interop-test-descriptions.md | 38 ++++++++ test/cpp/interop/client.cc | 6 ++ test/cpp/interop/interop_client.cc | 19 ++++ test/cpp/interop/interop_client.h | 2 + .../internal_ci/macos/grpc_interop_toprod.sh | 3 +- tools/run_tests/run_interop_tests.py | 93 ++++++++++--------- 6 files changed, 117 insertions(+), 44 deletions(-) diff --git a/doc/interop-test-descriptions.md b/doc/interop-test-descriptions.md index 1d6535d7ea0..9f6961f5199 100644 --- a/doc/interop-test-descriptions.md +++ b/doc/interop-test-descriptions.md @@ -679,6 +679,44 @@ Client asserts: by the auth library. The client can optionally check the username matches the email address in the key file. +### google_default_credentials + +Similar to the other auth tests, this test should only be run against prod +servers. Different from some of the other auth tests however, this test +may be also run from outside of GCP. + +This test verifies unary calls succeed when the client uses +GoogleDefaultCredentials. The path to a service account key file in the +GOOGLE_APPLICATION_CREDENTIALS environment variable may or may not be +provided by the test runner. For example, the test runner might set +this environment when outside of GCP but keep it unset when on GCP. + +The test uses `--default_service_account` with GCE service account email. + +Server features: +* [UnaryCall][] +* [Echo Authenticated Username][] + +Procedure: + 1. Client configures the channel to use GoogleDefaultCredentials + * Note: the term `GoogleDefaultCredentials` within the context + of this test description refers to an API which encapsulates + both "transport credentials" and "call credentials" and which + is capable of transport creds auto-selection (including ALTS). + Similar APIs involving only auto-selection of OAuth mechanisms + might work for this test but aren't the intended subjects. + 2. Client calls UnaryCall with: + + ``` + { + fill_username: true + } + ``` + +Client asserts: +* call was successful +* received SimpleResponse.username matches the value of + `--default_service_account` ### custom_metadata diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc index a4b1a85f856..99315e3c85d 100644 --- a/test/cpp/interop/client.cc +++ b/test/cpp/interop/client.cc @@ -54,6 +54,7 @@ DEFINE_string( "custom_metadata: server will echo custom metadata;\n" "empty_stream : bi-di stream with no request/response;\n" "empty_unary : empty (zero bytes) request and response;\n" + "google_default_credentials: large unary using GDC;\n" "half_duplex : half-duplex streaming;\n" "jwt_token_creds: large_unary with JWT token auth;\n" "large_unary : single request and (large) response;\n" @@ -151,6 +152,11 @@ int main(int argc, char** argv) { std::bind(&grpc::testing::InteropClient::DoPerRpcCreds, &client, GetServiceAccountJsonKey()); } + if (FLAGS_custom_credentials_type == "google_default_credentials") { + actions["google_default_credentials"] = + std::bind(&grpc::testing::InteropClient::DoGoogleDefaultCredentials, + &client, FLAGS_default_service_account); + } actions["status_code_and_message"] = std::bind(&grpc::testing::InteropClient::DoStatusWithMessage, &client); actions["custom_metadata"] = diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc index 4ff153f980a..649abf8a938 100644 --- a/test/cpp/interop/interop_client.cc +++ b/test/cpp/interop/interop_client.cc @@ -294,6 +294,25 @@ bool InteropClient::DoJwtTokenCreds(const grpc::string& username) { return true; } +bool InteropClient::DoGoogleDefaultCredentials( + const grpc::string& default_service_account) { + gpr_log(GPR_DEBUG, + "Sending a large unary rpc with GoogleDefaultCredentials..."); + SimpleRequest request; + SimpleResponse response; + request.set_fill_username(true); + + if (!PerformLargeUnary(&request, &response)) { + return false; + } + + gpr_log(GPR_DEBUG, "Got username %s", response.username().c_str()); + GPR_ASSERT(!response.username().empty()); + GPR_ASSERT(response.username().c_str() == default_service_account); + gpr_log(GPR_DEBUG, "Large unary rpc with GoogleDefaultCredentials done."); + return true; +} + bool InteropClient::DoLargeUnary() { gpr_log(GPR_DEBUG, "Sending a large unary rpc..."); SimpleRequest request; diff --git a/test/cpp/interop/interop_client.h b/test/cpp/interop/interop_client.h index 0ceff55c5c2..8644844d952 100644 --- a/test/cpp/interop/interop_client.h +++ b/test/cpp/interop/interop_client.h @@ -89,6 +89,8 @@ class InteropClient { const grpc::string& oauth_scope); // username is a string containing the user email bool DoPerRpcCreds(const grpc::string& json_key); + // username is the GCE default service account email + bool DoGoogleDefaultCredentials(const grpc::string& username); private: class ServiceStub { diff --git a/tools/internal_ci/macos/grpc_interop_toprod.sh b/tools/internal_ci/macos/grpc_interop_toprod.sh index e748a62e761..d1ab54fe01e 100755 --- a/tools/internal_ci/macos/grpc_interop_toprod.sh +++ b/tools/internal_ci/macos/grpc_interop_toprod.sh @@ -30,7 +30,8 @@ export GRPC_DEFAULT_SSL_ROOTS_FILE_PATH="$(pwd)/etc/roots.pem" # building all languages in the same working copy can also lead to conflicts # due to different compilation flags tools/run_tests/run_interop_tests.py -l c++ \ - --cloud_to_prod --cloud_to_prod_auth --prod_servers default gateway_v4 \ + --cloud_to_prod --cloud_to_prod_auth --on_gce=false \ + --prod_servers default gateway_v4 \ --service_account_key_file="${KOKORO_GFILE_DIR}/GrpcTesting-726eb1347f15.json" \ --skip_compute_engine_creds --internal_ci -t -j 4 || FAILED="true" diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index d026145d66f..de3f01a53e0 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -65,6 +65,12 @@ _SKIP_ADVANCED = [ _SKIP_SPECIAL_STATUS_MESSAGE = ['special_status_message'] +_GOOGLE_DEFAULT_CREDS_TEST_CASE = 'google_default_credentials' + +_SKIP_GOOGLE_DEFAULT_CREDS = [ + _GOOGLE_DEFAULT_CREDS_TEST_CASE, +] + _TEST_TIMEOUT = 3 * 60 # disable this test on core-based languages, @@ -129,7 +135,7 @@ class CSharpLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_SERVER_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + return _SKIP_SERVER_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return _SKIP_COMPRESSION @@ -158,7 +164,7 @@ class CSharpCoreCLRLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_SERVER_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + return _SKIP_SERVER_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return _SKIP_COMPRESSION @@ -188,7 +194,7 @@ class DartLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_COMPRESSION + _SKIP_SPECIAL_STATUS_MESSAGE + return _SKIP_COMPRESSION + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return _SKIP_COMPRESSION + _SKIP_SPECIAL_STATUS_MESSAGE @@ -223,7 +229,7 @@ class JavaLanguage: return {} def unimplemented_test_cases(self): - return [] + return _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return _SKIP_COMPRESSION @@ -248,7 +254,7 @@ class JavaOkHttpClient: return {} def unimplemented_test_cases(self): - return _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + return _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS def __str__(self): return 'javaokhttp' @@ -279,7 +285,7 @@ class GoLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_COMPRESSION + return _SKIP_COMPRESSION + _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return _SKIP_COMPRESSION @@ -309,7 +315,7 @@ class Http2Server: return {} def unimplemented_test_cases(self): - return _TEST_CASES + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + return _TEST_CASES + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return _TEST_CASES @@ -339,7 +345,7 @@ class Http2Client: return {} def unimplemented_test_cases(self): - return _TEST_CASES + _SKIP_SPECIAL_STATUS_MESSAGE + return _TEST_CASES + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return _TEST_CASES @@ -376,7 +382,7 @@ class NodeLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return _SKIP_COMPRESSION @@ -406,7 +412,7 @@ class NodePureJSLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return [] @@ -431,7 +437,7 @@ class PHPLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return [] @@ -456,7 +462,7 @@ class PHP7Language: return {} def unimplemented_test_cases(self): - return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return [] @@ -491,7 +497,7 @@ class ObjcLanguage: # cmdline argument. Here we return all but one test cases as unimplemented, # and depend upon ObjC test's behavior that it runs all cases even when # we tell it to run just one. - return _TEST_CASES[1:] + _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + return _TEST_CASES[1:] + _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return _SKIP_COMPRESSION @@ -526,7 +532,7 @@ class RubyLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_SERVER_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + return _SKIP_SERVER_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return _SKIP_COMPRESSION @@ -571,7 +577,7 @@ class PythonLanguage: } def unimplemented_test_cases(self): - return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_GOOGLE_DEFAULT_CREDS def unimplemented_test_cases_server(self): return _SKIP_COMPRESSION @@ -614,8 +620,11 @@ _TEST_CASES = [ ] _AUTH_TEST_CASES = [ - 'compute_engine_creds', 'jwt_token_creds', 'oauth2_auth_token', - 'per_rpc_creds' + 'compute_engine_creds', + 'jwt_token_creds', + 'oauth2_auth_token', + 'per_rpc_creds', + _GOOGLE_DEFAULT_CREDS_TEST_CASE, ] _HTTP2_TEST_CASES = ['tls', 'framing'] @@ -714,7 +723,7 @@ def compute_engine_creds_required(language, test_case): return False -def auth_options(language, test_case, service_account_key_file=None): +def auth_options(language, test_case, on_gce, service_account_key_file=None): """Returns (cmdline, env) tuple with cloud_to_prod_auth test options.""" language = str(language) @@ -728,9 +737,6 @@ def auth_options(language, test_case, service_account_key_file=None): key_file_arg = '--service_account_key_file=%s' % service_account_key_file default_account_arg = '--default_service_account=830293263384-compute@developer.gserviceaccount.com' - # TODO: When using google_default_credentials outside of cloud-to-prod, the environment variable - # 'GOOGLE_APPLICATION_CREDENTIALS' needs to be set for the test case - # 'jwt_token_creds' to work. if test_case in ['jwt_token_creds', 'per_rpc_creds', 'oauth2_auth_token']: if language in [ 'csharp', 'csharpcoreclr', 'node', 'php', 'php7', 'python', @@ -750,6 +756,11 @@ def auth_options(language, test_case, service_account_key_file=None): if test_case == 'compute_engine_creds': cmdargs += [oauth_scope_arg, default_account_arg] + if test_case == _GOOGLE_DEFAULT_CREDS_TEST_CASE: + if not on_gce: + env['GOOGLE_APPLICATION_CREDENTIALS'] = service_account_key_file + cmdargs += [default_account_arg] + return (cmdargs, env) @@ -767,6 +778,7 @@ def cloud_to_prod_jobspec(language, test_case, server_host_nickname, server_host, + on_gce, docker_image=None, auth=False, manual_cmd_log=None, @@ -793,7 +805,7 @@ def cloud_to_prod_jobspec(language, cmdargs = cmdargs + transport_security_options environ = dict(language.cloud_to_prod_env(), **language.global_env()) if auth: - auth_cmdargs, auth_env = auth_options(language, test_case, + auth_cmdargs, auth_env = auth_options(language, test_case, on_gce, service_account_key_file) cmdargs += auth_cmdargs environ.update(auth_env) @@ -1071,6 +1083,12 @@ argp.add_argument( action='store_const', const=True, help='Run cloud_to_prod_auth tests.') +argp.add_argument( + '--on_gce', + default=True, + action='store_const', + const=True, + help='Whether or not this test script is running on GCE.') argp.add_argument( '--prod_servers', choices=prod_servers.keys(), @@ -1326,6 +1344,7 @@ try: test_case, server_host_nickname, prod_servers[server_host_nickname], + on_gce=args.on_gce, docker_image=docker_images.get(str(language)), manual_cmd_log=client_manual_cmd_log, service_account_key_file=args. @@ -1340,6 +1359,7 @@ try: test_case, server_host_nickname, prod_servers[server_host_nickname], + on_gce=args.on_gce, docker_image=docker_images.get( str(language)), manual_cmd_log=client_manual_cmd_log, @@ -1356,6 +1376,7 @@ try: test_case, server_host_nickname, prod_servers[server_host_nickname], + on_gce=args.on_gce, docker_image=docker_images.get(str(http2Interop)), manual_cmd_log=client_manual_cmd_log, service_account_key_file=args.service_account_key_file, @@ -1374,36 +1395,22 @@ try: not compute_engine_creds_required( language, test_case)): if not test_case in language.unimplemented_test_cases(): - tls_test_job = cloud_to_prod_jobspec( + transport_security = 'tls' + if test_case == _GOOGLE_DEFAULT_CREDS_TEST_CASE: + transport_security = 'google_default_credentials' + test_job = cloud_to_prod_jobspec( language, test_case, server_host_nickname, prod_servers[server_host_nickname], + on_gce=args.on_gce, docker_image=docker_images.get(str(language)), auth=True, manual_cmd_log=client_manual_cmd_log, service_account_key_file=args. service_account_key_file, - transport_security='tls') - jobs.append(tls_test_job) - if str(language) in [ - 'go' - ]: # Add more languages to the list to turn on tests. - google_default_creds_test_job = cloud_to_prod_jobspec( - language, - test_case, - server_host_nickname, - prod_servers[server_host_nickname], - docker_image=docker_images.get( - str(language)), - auth=True, - manual_cmd_log=client_manual_cmd_log, - service_account_key_file=args. - service_account_key_file, - transport_security= - 'google_default_credentials') - jobs.append(google_default_creds_test_job) - + transport_security=transport_security) + jobs.append(test_job) for server in args.override_server: server_name = server[0] (server_host, server_port) = server[1].split(':') From b6ac1cb5b477d0182126a4b51d33ac58e66f3e83 Mon Sep 17 00:00:00 2001 From: Maxim Bunkov Date: Tue, 11 Dec 2018 14:11:00 +0500 Subject: [PATCH 003/218] added support tvos --- gRPC-C++.podspec | 1 + gRPC-Core.podspec | 1 + gRPC-ProtoRPC.podspec | 1 + gRPC-RxLibrary.podspec | 1 + src/objective-c/BoringSSL-GRPC.podspec | 1 + 5 files changed, 5 insertions(+) diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 73c87942430..eac7fa7b9c4 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -40,6 +40,7 @@ Pod::Spec.new do |s| s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '10.0' s.requires_arc = false name = 'grpcpp' diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index ff4d79426fe..284c8fbb3a2 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -40,6 +40,7 @@ Pod::Spec.new do |s| s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '10.0' s.requires_arc = false name = 'grpc' diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index d7050906e43..64e199eabd4 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -35,6 +35,7 @@ Pod::Spec.new do |s| s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '10.0' name = 'ProtoRPC' s.module_name = name diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec index 955f3682f67..76d023b475b 100644 --- a/gRPC-RxLibrary.podspec +++ b/gRPC-RxLibrary.podspec @@ -35,6 +35,7 @@ Pod::Spec.new do |s| s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '10.0' name = 'RxLibrary' s.module_name = name diff --git a/src/objective-c/BoringSSL-GRPC.podspec b/src/objective-c/BoringSSL-GRPC.podspec index 04e4d5768f2..3f02268b4fe 100644 --- a/src/objective-c/BoringSSL-GRPC.podspec +++ b/src/objective-c/BoringSSL-GRPC.podspec @@ -80,6 +80,7 @@ Pod::Spec.new do |s| s.ios.deployment_target = '5.0' s.osx.deployment_target = '10.7' + s.tvos.deployment_target = '10.0' name = 'openssl_grpc' From 814c858f3f2363a1ac59e137aa479a5b29ef0762 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Fri, 4 Jan 2019 18:45:01 -0800 Subject: [PATCH 004/218] Enable Python 3 --- BUILD | 5 +++++ src/python/grpcio/grpc/BUILD.bazel | 6 ++++-- .../grpcio/grpc/framework/common/BUILD.bazel | 14 ++++++++------ .../grpcio/grpc/framework/foundation/BUILD.bazel | 6 ++++-- .../grpc/framework/interfaces/base/BUILD.bazel | 13 ++++++++----- .../grpc/framework/interfaces/face/BUILD.bazel | 6 ++++-- src/python/grpcio_tests/tests/interop/BUILD.bazel | 6 ++++-- src/python/grpcio_tests/tests/unit/_api_test.py | 1 + third_party/py/python_configure.bzl | 6 +++--- tools/bazel.rc | 3 +++ 10 files changed, 44 insertions(+), 22 deletions(-) diff --git a/BUILD b/BUILD index e3c765198b2..c00ec27a333 100644 --- a/BUILD +++ b/BUILD @@ -63,6 +63,11 @@ config_setting( values = {"cpu": "x64_windows_msvc"}, ) +config_setting( + name = "python3", + values = {"python_path": "python3"}, +) + # This should be updated along with build.yaml g_stands_for = "goose" diff --git a/src/python/grpcio/grpc/BUILD.bazel b/src/python/grpcio/grpc/BUILD.bazel index 6958ccdfb66..27d5d2e4bb2 100644 --- a/src/python/grpcio/grpc/BUILD.bazel +++ b/src/python/grpcio/grpc/BUILD.bazel @@ -15,9 +15,11 @@ py_library( "//src/python/grpcio/grpc/_cython:cygrpc", "//src/python/grpcio/grpc/experimental", "//src/python/grpcio/grpc/framework", - requirement('enum34'), requirement('six'), - ], + ] + select({ + "//conditions:default": [requirement('enum34'),], + "//:python3": [], + }), data = [ "//:grpc", ], diff --git a/src/python/grpcio/grpc/framework/common/BUILD.bazel b/src/python/grpcio/grpc/framework/common/BUILD.bazel index 9d9ef682c90..52fbb2b516c 100644 --- a/src/python/grpcio/grpc/framework/common/BUILD.bazel +++ b/src/python/grpcio/grpc/framework/common/BUILD.bazel @@ -13,15 +13,17 @@ py_library( py_library( name = "cardinality", srcs = ["cardinality.py"], - deps = [ - requirement("enum34"), - ], + deps = select({ + "//conditions:default": [requirement('enum34'),], + "//:python3": [], + }), ) py_library( name = "style", srcs = ["style.py"], - deps = [ - requirement("enum34"), - ], + deps = select({ + "//conditions:default": [requirement('enum34'),], + "//:python3": [], + }), ) diff --git a/src/python/grpcio/grpc/framework/foundation/BUILD.bazel b/src/python/grpcio/grpc/framework/foundation/BUILD.bazel index 1287fdd44ed..98618b769af 100644 --- a/src/python/grpcio/grpc/framework/foundation/BUILD.bazel +++ b/src/python/grpcio/grpc/framework/foundation/BUILD.bazel @@ -23,9 +23,11 @@ py_library( name = "callable_util", srcs = ["callable_util.py"], deps = [ - requirement("enum34"), requirement("six"), - ], + ] + select({ + "//conditions:default": [requirement('enum34'),], + "//:python3": [], + }), ) py_library( diff --git a/src/python/grpcio/grpc/framework/interfaces/base/BUILD.bazel b/src/python/grpcio/grpc/framework/interfaces/base/BUILD.bazel index 408a66a6310..35cfe877f34 100644 --- a/src/python/grpcio/grpc/framework/interfaces/base/BUILD.bazel +++ b/src/python/grpcio/grpc/framework/interfaces/base/BUILD.bazel @@ -15,15 +15,18 @@ py_library( srcs = ["base.py"], deps = [ "//src/python/grpcio/grpc/framework/foundation:abandonment", - requirement("enum34"), requirement("six"), - ], + ] + select({ + "//conditions:default": [requirement('enum34'),], + "//:python3": [], + }), ) py_library( name = "utilities", srcs = ["utilities.py"], - deps = [ - requirement("enum34"), - ], + deps = select({ + "//conditions:default": [requirement('enum34'),], + "//:python3": [], + }), ) diff --git a/src/python/grpcio/grpc/framework/interfaces/face/BUILD.bazel b/src/python/grpcio/grpc/framework/interfaces/face/BUILD.bazel index e683e7cc426..83fadb6372e 100644 --- a/src/python/grpcio/grpc/framework/interfaces/face/BUILD.bazel +++ b/src/python/grpcio/grpc/framework/interfaces/face/BUILD.bazel @@ -16,9 +16,11 @@ py_library( deps = [ "//src/python/grpcio/grpc/framework/foundation", "//src/python/grpcio/grpc/framework/common", - requirement("enum34"), requirement("six"), - ], + ] + select({ + "//conditions:default": [requirement('enum34'),], + "//:python3": [], + }), ) py_library( diff --git a/src/python/grpcio_tests/tests/interop/BUILD.bazel b/src/python/grpcio_tests/tests/interop/BUILD.bazel index aebdbf67ebf..edb2e778b08 100644 --- a/src/python/grpcio_tests/tests/interop/BUILD.bazel +++ b/src/python/grpcio_tests/tests/interop/BUILD.bazel @@ -34,12 +34,14 @@ py_library( "//src/proto/grpc/testing:py_test_proto", requirement('google-auth'), requirement('requests'), - requirement('enum34'), requirement('urllib3'), requirement('chardet'), requirement('certifi'), requirement('idna'), - ], + ] + select({ + "//conditions:default": [requirement('enum34'),], + "//:python3": [], + }), imports=["../../",], ) diff --git a/src/python/grpcio_tests/tests/unit/_api_test.py b/src/python/grpcio_tests/tests/unit/_api_test.py index 0dc6a8718c3..b06a46249ad 100644 --- a/src/python/grpcio_tests/tests/unit/_api_test.py +++ b/src/python/grpcio_tests/tests/unit/_api_test.py @@ -103,6 +103,7 @@ class ChannelTest(unittest.TestCase): channel = grpc.secure_channel('google.com:443', channel_credentials) channel.close() +print("HELLO", "WORLD", end='!\n') if __name__ == '__main__': logging.basicConfig() diff --git a/third_party/py/python_configure.bzl b/third_party/py/python_configure.bzl index 2ba1e07049c..ae5132e002e 100644 --- a/third_party/py/python_configure.bzl +++ b/third_party/py/python_configure.bzl @@ -139,9 +139,9 @@ def _symlink_genrule_for_dir(repository_ctx, def _get_python_bin(repository_ctx): """Gets the python bin path.""" python_bin = repository_ctx.os.environ.get(_PYTHON_BIN_PATH) - if python_bin != None: - return python_bin - python_bin_path = repository_ctx.which("python") + if python_bin == None: + python_bin = 'python' + python_bin_path = repository_ctx.which(python_bin) if python_bin_path != None: return str(python_bin_path) _fail("Cannot find python in PATH, please make sure " + diff --git a/tools/bazel.rc b/tools/bazel.rc index 59e597b4723..29db17a51cb 100644 --- a/tools/bazel.rc +++ b/tools/bazel.rc @@ -57,3 +57,6 @@ build:basicprof --copt=-DNDEBUG build:basicprof --copt=-O2 build:basicprof --copt=-DGRPC_BASIC_PROFILER build:basicprof --copt=-DGRPC_TIMERS_RDTSC + +build:python3 --python_path=python3 +build:python3 --action_env=PYTHON_BIN_PATH=python3 From 0d931d9c8f2fedd264bd519abc343627fb42a36c Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Mon, 7 Jan 2019 13:41:02 -0800 Subject: [PATCH 005/218] Make Python 3 pass all unit tests --- .../grpc/framework/foundation/BUILD.bazel | 7 ++++--- .../reflection/_reflection_servicer_test.py | 20 ++++++++++++++----- .../grpcio_tests/tests/unit/_api_test.py | 1 - 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/python/grpcio/grpc/framework/foundation/BUILD.bazel b/src/python/grpcio/grpc/framework/foundation/BUILD.bazel index 98618b769af..a447ecded49 100644 --- a/src/python/grpcio/grpc/framework/foundation/BUILD.bazel +++ b/src/python/grpcio/grpc/framework/foundation/BUILD.bazel @@ -41,9 +41,10 @@ py_library( py_library( name = "logging_pool", srcs = ["logging_pool.py"], - deps = [ - requirement("futures"), - ], + deps = select({ + "//conditions:default": [requirement('futures'),], + "//:python3": [], + }), ) py_library( 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 560f6d3ddb3..0ee40e6f2da 100644 --- a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py +++ b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py @@ -50,6 +50,16 @@ def _file_descriptor_to_proto(descriptor): class ReflectionServicerTest(unittest.TestCase): + # NOTE(lidiz) Bazel + Python 3 will result in creating two different + # instance of DESCRIPTOR for each message. So, the equal comparision + # between protobuf returned by stub and manually crafted protobuf will + # always fail. + def _assert_sequence_of_proto_equal(self, x, y): + self.assertSequenceEqual( + list(map(lambda x: x.SerializeToString(), x)), + list(map(lambda x: x.SerializeToString(), y)), + ) + def setUp(self): self._server = test_common.test_server() reflection.enable_server_reflection(_SERVICE_NAMES, self._server) @@ -84,7 +94,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self.assertSequenceEqual(expected_responses, responses) + self._assert_sequence_of_proto_equal(expected_responses, responses) def testFileBySymbol(self): requests = ( @@ -108,7 +118,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self.assertSequenceEqual(expected_responses, responses) + self._assert_sequence_of_proto_equal(expected_responses, responses) def testFileContainingExtension(self): requests = ( @@ -137,7 +147,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self.assertSequenceEqual(expected_responses, responses) + self._assert_sequence_of_proto_equal(expected_responses, responses) def testExtensionNumbersOfType(self): requests = ( @@ -162,7 +172,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self.assertSequenceEqual(expected_responses, responses) + self._assert_sequence_of_proto_equal(expected_responses, responses) def testListServices(self): requests = (reflection_pb2.ServerReflectionRequest(list_services='',),) @@ -173,7 +183,7 @@ class ReflectionServicerTest(unittest.TestCase): service=tuple( reflection_pb2.ServiceResponse(name=name) for name in _SERVICE_NAMES))),) - self.assertSequenceEqual(expected_responses, responses) + self._assert_sequence_of_proto_equal(expected_responses, responses) def testReflectionServiceName(self): self.assertEqual(reflection.SERVICE_NAME, diff --git a/src/python/grpcio_tests/tests/unit/_api_test.py b/src/python/grpcio_tests/tests/unit/_api_test.py index b06a46249ad..0dc6a8718c3 100644 --- a/src/python/grpcio_tests/tests/unit/_api_test.py +++ b/src/python/grpcio_tests/tests/unit/_api_test.py @@ -103,7 +103,6 @@ class ChannelTest(unittest.TestCase): channel = grpc.secure_channel('google.com:443', channel_credentials) channel.close() -print("HELLO", "WORLD", end='!\n') if __name__ == '__main__': logging.basicConfig() From b8a542cd234d32c8da7cb8474e26c9c21f3c9581 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 8 Jan 2019 09:20:15 -0800 Subject: [PATCH 006/218] Update Send message interception methods docs --- include/grpcpp/impl/codegen/interceptor.h | 27 +++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/include/grpcpp/impl/codegen/interceptor.h b/include/grpcpp/impl/codegen/interceptor.h index 5dea796a3b7..32a2d439d94 100644 --- a/include/grpcpp/impl/codegen/interceptor.h +++ b/include/grpcpp/impl/codegen/interceptor.h @@ -107,6 +107,24 @@ class InterceptorBatchMethods { /// of the hijacking interceptor. virtual void Hijack() = 0; + /// Send Message Methods + /// GetSerializedSendMessage and GetSendMessage/ModifySendMessage are the + /// available methods to view and modify the request payload. An interceptor + /// can access the payload in either serialized form or non-serialized form + /// but not both at the same time. + /// gRPC performs serialization in a lazy manner, which means + /// that a call to GetSerializedSendMessage will result in a serialization + /// operation if the payload stored is not in the serialized form already. The + /// non-serialized form is lost and GetSendMessage will no longer return a + /// valid pointer, and this will remain true for later interceptors too. This + /// can change however if ModifySendMessage is used to replace the current + /// payload. Note that ModifySendMessage requires a new payload message in the + /// non-serialized form. This will overwrite the existing payload irrespective + /// of whether it had been serialized earlier. Also note that gRPC Async API + /// requires early serialization of the payload which means that the payload + /// would be available in the serialized form only unless an interceptor + /// replaces the payload with ModifySendMessage. + /// 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. @@ -114,15 +132,16 @@ class InterceptorBatchMethods { /// 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. + /// nullptr indicates that this field is not valid. 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. + /// the life of the message till it is serialized or it receives the + /// POST_SEND_MESSAGE interception point, whichever happens earlier. The + /// modifying interceptor may itself force early serialization by calling + /// GetSerializedSendMessage. virtual void ModifySendMessage(const void* message) = 0; /// Checks whether the SEND MESSAGE op succeeded. Valid for POST_SEND_MESSAGE From 73b1a918e4ae437ec7ac5f1d1c63c9fc2f153073 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 8 Jan 2019 09:28:09 -0800 Subject: [PATCH 007/218] Slight update to grammar. Can probably be improved more --- include/grpcpp/impl/codegen/interceptor.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/grpcpp/impl/codegen/interceptor.h b/include/grpcpp/impl/codegen/interceptor.h index 32a2d439d94..03520867f9c 100644 --- a/include/grpcpp/impl/codegen/interceptor.h +++ b/include/grpcpp/impl/codegen/interceptor.h @@ -114,16 +114,16 @@ class InterceptorBatchMethods { /// but not both at the same time. /// gRPC performs serialization in a lazy manner, which means /// that a call to GetSerializedSendMessage will result in a serialization - /// operation if the payload stored is not in the serialized form already. The - /// non-serialized form is lost and GetSendMessage will no longer return a - /// valid pointer, and this will remain true for later interceptors too. This - /// can change however if ModifySendMessage is used to replace the current - /// payload. Note that ModifySendMessage requires a new payload message in the - /// non-serialized form. This will overwrite the existing payload irrespective - /// of whether it had been serialized earlier. Also note that gRPC Async API - /// requires early serialization of the payload which means that the payload - /// would be available in the serialized form only unless an interceptor - /// replaces the payload with ModifySendMessage. + /// operation if the payload stored is not in the serialized form already; the + /// non-serialized form will be lost and GetSendMessage will no longer return + /// a valid pointer, and this will remain true for later interceptors too. + /// This can change however if ModifySendMessage is used to replace the + /// current payload. Note that ModifySendMessage requires a new payload + /// message in the non-serialized form. This will overwrite the existing + /// payload irrespective of whether it had been serialized earlier. Also note + /// that gRPC Async API requires early serialization of the payload which + /// means that the payload would be available in the serialized form only + /// unless an interceptor replaces the payload with ModifySendMessage. /// Returns a modifable ByteBuffer holding the serialized form of the message /// that is going to be sent. Valid for PRE_SEND_MESSAGE interceptions. From 7105626569bd5f829cf40ccd82bd82f5112de025 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Tue, 8 Jan 2019 10:07:47 -0800 Subject: [PATCH 008/218] Pump force Python version & simplify code --- third_party/py/python_configure.bzl | 4 +--- tools/bazel.rc | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/third_party/py/python_configure.bzl b/third_party/py/python_configure.bzl index ae5132e002e..6e25cc493b3 100644 --- a/third_party/py/python_configure.bzl +++ b/third_party/py/python_configure.bzl @@ -138,9 +138,7 @@ def _symlink_genrule_for_dir(repository_ctx, def _get_python_bin(repository_ctx): """Gets the python bin path.""" - python_bin = repository_ctx.os.environ.get(_PYTHON_BIN_PATH) - if python_bin == None: - python_bin = 'python' + python_bin = repository_ctx.os.environ.get(_PYTHON_BIN_PATH, 'python') python_bin_path = repository_ctx.which(python_bin) if python_bin_path != None: return str(python_bin_path) diff --git a/tools/bazel.rc b/tools/bazel.rc index 29db17a51cb..99347495361 100644 --- a/tools/bazel.rc +++ b/tools/bazel.rc @@ -59,4 +59,5 @@ build:basicprof --copt=-DGRPC_BASIC_PROFILER build:basicprof --copt=-DGRPC_TIMERS_RDTSC build:python3 --python_path=python3 +build:python3 --force_python=PY3 build:python3 --action_env=PYTHON_BIN_PATH=python3 From 7df3475a9f74839c63702773e9f4a7e4278ea600 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Wed, 9 Jan 2019 14:36:23 -0800 Subject: [PATCH 009/218] Enable Bazel Python 3 for every PR * Reverted hack in _reflection_servicer_test.py * To see if Kokoro is happy about it --- .../reflection/_reflection_servicer_test.py | 20 +++++-------------- .../linux/grpc_python_bazel_test_in_docker.sh | 1 + 2 files changed, 6 insertions(+), 15 deletions(-) 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 0ee40e6f2da..560f6d3ddb3 100644 --- a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py +++ b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py @@ -50,16 +50,6 @@ def _file_descriptor_to_proto(descriptor): class ReflectionServicerTest(unittest.TestCase): - # NOTE(lidiz) Bazel + Python 3 will result in creating two different - # instance of DESCRIPTOR for each message. So, the equal comparision - # between protobuf returned by stub and manually crafted protobuf will - # always fail. - def _assert_sequence_of_proto_equal(self, x, y): - self.assertSequenceEqual( - list(map(lambda x: x.SerializeToString(), x)), - list(map(lambda x: x.SerializeToString(), y)), - ) - def setUp(self): self._server = test_common.test_server() reflection.enable_server_reflection(_SERVICE_NAMES, self._server) @@ -94,7 +84,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self._assert_sequence_of_proto_equal(expected_responses, responses) + self.assertSequenceEqual(expected_responses, responses) def testFileBySymbol(self): requests = ( @@ -118,7 +108,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self._assert_sequence_of_proto_equal(expected_responses, responses) + self.assertSequenceEqual(expected_responses, responses) def testFileContainingExtension(self): requests = ( @@ -147,7 +137,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self._assert_sequence_of_proto_equal(expected_responses, responses) + self.assertSequenceEqual(expected_responses, responses) def testExtensionNumbersOfType(self): requests = ( @@ -172,7 +162,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self._assert_sequence_of_proto_equal(expected_responses, responses) + self.assertSequenceEqual(expected_responses, responses) def testListServices(self): requests = (reflection_pb2.ServerReflectionRequest(list_services='',),) @@ -183,7 +173,7 @@ class ReflectionServicerTest(unittest.TestCase): service=tuple( reflection_pb2.ServiceResponse(name=name) for name in _SERVICE_NAMES))),) - self._assert_sequence_of_proto_equal(expected_responses, responses) + self.assertSequenceEqual(expected_responses, responses) def testReflectionServiceName(self): self.assertEqual(reflection.SERVICE_NAME, diff --git a/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh b/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh index 156d65955ad..0e0734084dc 100755 --- a/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh +++ b/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh @@ -25,3 +25,4 @@ git clone /var/local/jenkins/grpc /var/local/git/grpc ${name}') cd /var/local/git/grpc/test bazel test --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... +bazel test --config=python3 --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... From 15be9de11bce4d9fc17a3706854abfbfc988f5e9 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Wed, 9 Jan 2019 14:52:56 -0800 Subject: [PATCH 010/218] Bazel clean between builds of Python 2/3 --- tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh b/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh index 0e0734084dc..14989648a2a 100755 --- a/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh +++ b/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh @@ -25,4 +25,5 @@ git clone /var/local/jenkins/grpc /var/local/git/grpc ${name}') cd /var/local/git/grpc/test bazel test --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... +bazel clean --expunge bazel test --config=python3 --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... From 222db627212b331381d97468813233738d720e75 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Fri, 11 Jan 2019 17:01:54 -0800 Subject: [PATCH 011/218] Revert the compare of protobuf message to comparing encoded result --- .../reflection/_reflection_servicer_test.py | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) 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 560f6d3ddb3..0ee40e6f2da 100644 --- a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py +++ b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py @@ -50,6 +50,16 @@ def _file_descriptor_to_proto(descriptor): class ReflectionServicerTest(unittest.TestCase): + # NOTE(lidiz) Bazel + Python 3 will result in creating two different + # instance of DESCRIPTOR for each message. So, the equal comparision + # between protobuf returned by stub and manually crafted protobuf will + # always fail. + def _assert_sequence_of_proto_equal(self, x, y): + self.assertSequenceEqual( + list(map(lambda x: x.SerializeToString(), x)), + list(map(lambda x: x.SerializeToString(), y)), + ) + def setUp(self): self._server = test_common.test_server() reflection.enable_server_reflection(_SERVICE_NAMES, self._server) @@ -84,7 +94,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self.assertSequenceEqual(expected_responses, responses) + self._assert_sequence_of_proto_equal(expected_responses, responses) def testFileBySymbol(self): requests = ( @@ -108,7 +118,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self.assertSequenceEqual(expected_responses, responses) + self._assert_sequence_of_proto_equal(expected_responses, responses) def testFileContainingExtension(self): requests = ( @@ -137,7 +147,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self.assertSequenceEqual(expected_responses, responses) + self._assert_sequence_of_proto_equal(expected_responses, responses) def testExtensionNumbersOfType(self): requests = ( @@ -162,7 +172,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self.assertSequenceEqual(expected_responses, responses) + self._assert_sequence_of_proto_equal(expected_responses, responses) def testListServices(self): requests = (reflection_pb2.ServerReflectionRequest(list_services='',),) @@ -173,7 +183,7 @@ class ReflectionServicerTest(unittest.TestCase): service=tuple( reflection_pb2.ServiceResponse(name=name) for name in _SERVICE_NAMES))),) - self.assertSequenceEqual(expected_responses, responses) + self._assert_sequence_of_proto_equal(expected_responses, responses) def testReflectionServiceName(self): self.assertEqual(reflection.SERVICE_NAME, From 206a76b332dbc0c1e2127e03857831225003f092 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Tue, 15 Jan 2019 10:04:00 -0800 Subject: [PATCH 012/218] Upgrade Bazel to 21.0 --- tools/dockerfile/test/bazel/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dockerfile/test/bazel/Dockerfile b/tools/dockerfile/test/bazel/Dockerfile index 0aa6209f4fd..05c187894cc 100644 --- a/tools/dockerfile/test/bazel/Dockerfile +++ b/tools/dockerfile/test/bazel/Dockerfile @@ -46,7 +46,7 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t # Bazel installation RUN apt-get update && apt-get install -y wget && apt-get clean -RUN wget -q https://github.com/bazelbuild/bazel/releases/download/0.17.1/bazel-0.17.1-linux-x86_64 -O /usr/local/bin/bazel +RUN wget -q https://github.com/bazelbuild/bazel/releases/download/0.21.0/bazel-0.21.0-linux-x86_64 -O /usr/local/bin/bazel RUN chmod 755 /usr/local/bin/bazel From 30a95d354c045d7e0127ad18857b099117330683 Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Tue, 15 Jan 2019 13:04:34 -0800 Subject: [PATCH 013/218] rename census context hooks --- src/python/grpcio/grpc/_channel.py | 8 ++++---- src/python/grpcio/grpc/_cython/_cygrpc/_hooks.pyx.pxi | 4 ++-- src/python/grpcio/grpc/_server.py | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py index 3685969c7fe..f7da028e3a7 100644 --- a/src/python/grpcio/grpc/_channel.py +++ b/src/python/grpcio/grpc/_channel.py @@ -499,7 +499,7 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): self._method = method self._request_serializer = request_serializer self._response_deserializer = response_deserializer - self._context = cygrpc.build_context() + self._context = cygrpc.build_census_context() def _prepare(self, request, timeout, metadata, wait_for_ready): deadline, serialized_request, rendezvous = _start_unary_request( @@ -590,7 +590,7 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): self._method = method self._request_serializer = request_serializer self._response_deserializer = response_deserializer - self._context = cygrpc.build_context() + self._context = cygrpc.build_census_context() def __call__(self, request, @@ -637,7 +637,7 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): self._method = method self._request_serializer = request_serializer self._response_deserializer = response_deserializer - self._context = cygrpc.build_context() + self._context = cygrpc.build_census_context() def _blocking(self, request_iterator, timeout, metadata, credentials, wait_for_ready): @@ -714,7 +714,7 @@ class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable): self._method = method self._request_serializer = request_serializer self._response_deserializer = response_deserializer - self._context = cygrpc.build_context() + self._context = cygrpc.build_census_context() def __call__(self, request_iterator, diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/_hooks.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/_hooks.pyx.pxi index cd4a51a635e..6d1c36b2b35 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/_hooks.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/_hooks.pyx.pxi @@ -16,13 +16,13 @@ cdef object _custom_op_on_c_call(int op, grpc_call *call): raise NotImplementedError("No custom hooks are implemented") -def install_census_context_from_call(Call call): +def install_context_from_call(Call call): pass def uninstall_context(): pass -def build_context(): +def build_census_context(): pass cdef class CensusContext: diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py index c3ff1fa6bd3..5cdd58ec954 100644 --- a/src/python/grpcio/grpc/_server.py +++ b/src/python/grpcio/grpc/_server.py @@ -484,7 +484,7 @@ def _status(rpc_event, state, serialized_response): def _unary_response_in_pool(rpc_event, state, behavior, argument_thunk, request_deserializer, response_serializer): - cygrpc.install_census_context_from_call(rpc_event.call) + cygrpc.install_context_from_call(rpc_event.call) try: argument = argument_thunk() if argument is not None: @@ -501,7 +501,7 @@ def _unary_response_in_pool(rpc_event, state, behavior, argument_thunk, def _stream_response_in_pool(rpc_event, state, behavior, argument_thunk, request_deserializer, response_serializer): - cygrpc.install_census_context_from_call(rpc_event.call) + cygrpc.install_context_from_call(rpc_event.call) try: argument = argument_thunk() if argument is not None: From 109a6a9a09320e48fbd8e8f73ca98425d150f2a1 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Wed, 16 Jan 2019 10:32:18 -0800 Subject: [PATCH 014/218] Revert "Upgrade Bazel to 21.0" This reverts commit 206a76b332dbc0c1e2127e03857831225003f092. --- tools/dockerfile/test/bazel/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dockerfile/test/bazel/Dockerfile b/tools/dockerfile/test/bazel/Dockerfile index 05c187894cc..0aa6209f4fd 100644 --- a/tools/dockerfile/test/bazel/Dockerfile +++ b/tools/dockerfile/test/bazel/Dockerfile @@ -46,7 +46,7 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t # Bazel installation RUN apt-get update && apt-get install -y wget && apt-get clean -RUN wget -q https://github.com/bazelbuild/bazel/releases/download/0.21.0/bazel-0.21.0-linux-x86_64 -O /usr/local/bin/bazel +RUN wget -q https://github.com/bazelbuild/bazel/releases/download/0.17.1/bazel-0.17.1-linux-x86_64 -O /usr/local/bin/bazel RUN chmod 755 /usr/local/bin/bazel From 17fa4b0caf059791e66ae5edf7c9c1a82db94d7b Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Wed, 16 Jan 2019 10:43:15 -0800 Subject: [PATCH 015/218] Use monkey patch function to solve namespace package issue --- .../grpcio_status/grpc_status/rpc_status.py | 5 --- src/python/grpcio_tests/tests/BUILD.bazel | 8 +++++ src/python/grpcio_tests/tests/bazel_patch.py | 32 +++++++++++++++++++ .../grpcio_tests/tests/interop/BUILD.bazel | 1 + .../grpcio_tests/tests/interop/methods.py | 3 ++ .../grpcio_tests/tests/status/BUILD.bazel | 1 + .../tests/status/_grpc_status_test.py | 3 ++ 7 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 src/python/grpcio_tests/tests/BUILD.bazel create mode 100644 src/python/grpcio_tests/tests/bazel_patch.py diff --git a/src/python/grpcio_status/grpc_status/rpc_status.py b/src/python/grpcio_status/grpc_status/rpc_status.py index 87618fa5412..76891e2422e 100644 --- a/src/python/grpcio_status/grpc_status/rpc_status.py +++ b/src/python/grpcio_status/grpc_status/rpc_status.py @@ -17,11 +17,6 @@ import collections import grpc -# TODO(https://github.com/bazelbuild/bazel/issues/6844) -# Due to Bazel issue, the namespace packages won't resolve correctly. -# Adding this unused-import as a workaround to avoid module-not-found error -# under Bazel builds. -import google.protobuf # pylint: disable=unused-import from google.rpc import status_pb2 _CODE_TO_GRPC_CODE_MAPPING = {x.value[0]: x for x in grpc.StatusCode} diff --git a/src/python/grpcio_tests/tests/BUILD.bazel b/src/python/grpcio_tests/tests/BUILD.bazel new file mode 100644 index 00000000000..118cd0ea0dd --- /dev/null +++ b/src/python/grpcio_tests/tests/BUILD.bazel @@ -0,0 +1,8 @@ +py_library( + name = "bazel_patch", + srcs = ["bazel_patch.py"], + visibility = ["//visibility:public"], + data=[ + "//src/python/grpcio_tests/tests/unit/credentials", + ], +) diff --git a/src/python/grpcio_tests/tests/bazel_patch.py b/src/python/grpcio_tests/tests/bazel_patch.py new file mode 100644 index 00000000000..af48697de30 --- /dev/null +++ b/src/python/grpcio_tests/tests/bazel_patch.py @@ -0,0 +1,32 @@ +# Copyright 2019 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. + +import os +import site +import sys + + +# TODO(https://github.com/bazelbuild/bazel/issues/6844) Bazel failed to +# interpret namespace packages correctly. This monkey patch will force the +# Python process to parse the .pth file in the sys.path to resolve namespace +# package in the right place. +# Analysis in depth: https://github.com/bazelbuild/rules_python/issues/55 +def bazel_patch(): + """Add valid sys.path item to site directory to parse the .pth files.""" + for item in sys.path: + if os.path.exists(item): + # The only difference between sys.path and site-directory is + # whether the .pth file will be parsed or not. A site-directory + # will always exist in sys.path, but not another way around. + site.addsitedir(item) diff --git a/src/python/grpcio_tests/tests/interop/BUILD.bazel b/src/python/grpcio_tests/tests/interop/BUILD.bazel index edb2e778b08..bb5f0f344e2 100644 --- a/src/python/grpcio_tests/tests/interop/BUILD.bazel +++ b/src/python/grpcio_tests/tests/interop/BUILD.bazel @@ -29,6 +29,7 @@ py_library( srcs = ["methods.py"], deps = [ "//src/python/grpcio/grpc:grpcio", + "//src/python/grpcio_tests/tests:bazel_patch", "//src/proto/grpc/testing:py_empty_proto", "//src/proto/grpc/testing:py_messages_proto", "//src/proto/grpc/testing:py_test_proto", diff --git a/src/python/grpcio_tests/tests/interop/methods.py b/src/python/grpcio_tests/tests/interop/methods.py index c11f6c8fad7..e037046691b 100644 --- a/src/python/grpcio_tests/tests/interop/methods.py +++ b/src/python/grpcio_tests/tests/interop/methods.py @@ -13,6 +13,9 @@ # limitations under the License. """Implementations of interoperability test methods.""" +from tests.bazel_patch import bazel_patch +bazel_patch() + import enum import json import os diff --git a/src/python/grpcio_tests/tests/status/BUILD.bazel b/src/python/grpcio_tests/tests/status/BUILD.bazel index 937e50498e0..21dea5a76dc 100644 --- a/src/python/grpcio_tests/tests/status/BUILD.bazel +++ b/src/python/grpcio_tests/tests/status/BUILD.bazel @@ -10,6 +10,7 @@ py_test( deps = [ "//src/python/grpcio/grpc:grpcio", "//src/python/grpcio_status/grpc_status:grpc_status", + "//src/python/grpcio_tests/tests:bazel_patch", "//src/python/grpcio_tests/tests/unit:test_common", "//src/python/grpcio_tests/tests/unit/framework/common:common", requirement('protobuf'), diff --git a/src/python/grpcio_tests/tests/status/_grpc_status_test.py b/src/python/grpcio_tests/tests/status/_grpc_status_test.py index 519c372a960..67b1785becb 100644 --- a/src/python/grpcio_tests/tests/status/_grpc_status_test.py +++ b/src/python/grpcio_tests/tests/status/_grpc_status_test.py @@ -13,6 +13,9 @@ # limitations under the License. """Tests of grpc_status.""" +from tests.bazel_patch import bazel_patch +bazel_patch() + import unittest import logging From 1b07aba6af03626a8dc24a895f349648e4aebaa1 Mon Sep 17 00:00:00 2001 From: Maxim Bunkov Date: Thu, 17 Jan 2019 10:24:39 +0500 Subject: [PATCH 016/218] Update templates for supprt tvOS --- templates/gRPC-C++.podspec.template | 2 + templates/gRPC-Core.podspec.template | 2 + templates/gRPC-ProtoRPC.podspec.template | 1 + templates/gRPC-RxLibrary.podspec.template | 1 + templates/gRPC.podspec.template | 1 + ...!ProtoCompiler-gRPCPlugin.podspec.template | 1 + .../BoringSSL-GRPC.podspec.template | 6027 ++++++++++++----- 7 files changed, 4508 insertions(+), 1527 deletions(-) diff --git a/templates/gRPC-C++.podspec.template b/templates/gRPC-C++.podspec.template index 94d5a4fb09e..371d25cd6ba 100644 --- a/templates/gRPC-C++.podspec.template +++ b/templates/gRPC-C++.podspec.template @@ -156,6 +156,8 @@ s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '10.0' + s.requires_arc = false name = 'grpcpp' diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template index 98b6344a4bf..7a1d3b1acdc 100644 --- a/templates/gRPC-Core.podspec.template +++ b/templates/gRPC-Core.podspec.template @@ -99,6 +99,8 @@ s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '10.0' + s.requires_arc = false name = 'grpc' diff --git a/templates/gRPC-ProtoRPC.podspec.template b/templates/gRPC-ProtoRPC.podspec.template index 96966784f18..9d7e392a24a 100644 --- a/templates/gRPC-ProtoRPC.podspec.template +++ b/templates/gRPC-ProtoRPC.podspec.template @@ -37,6 +37,7 @@ s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '10.0' name = 'ProtoRPC' s.module_name = name diff --git a/templates/gRPC-RxLibrary.podspec.template b/templates/gRPC-RxLibrary.podspec.template index 14147d7dc1b..0973b6551db 100644 --- a/templates/gRPC-RxLibrary.podspec.template +++ b/templates/gRPC-RxLibrary.podspec.template @@ -37,6 +37,7 @@ s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '10.0' name = 'RxLibrary' s.module_name = name diff --git a/templates/gRPC.podspec.template b/templates/gRPC.podspec.template index a3190c2d8e6..7cbd52157f5 100644 --- a/templates/gRPC.podspec.template +++ b/templates/gRPC.podspec.template @@ -36,6 +36,7 @@ s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '10.0' name = 'GRPCClient' s.module_name = name diff --git a/templates/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec.template b/templates/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec.template index 30b6c5684cc..3e095d7aab7 100644 --- a/templates/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec.template +++ b/templates/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec.template @@ -107,6 +107,7 @@ # For the Protobuf dependency not to complain: s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '10.0' # Restrict the gRPC runtime version to the one supported by this plugin. s.dependency 'gRPC-ProtoRPC', v diff --git a/templates/src/objective-c/BoringSSL-GRPC.podspec.template b/templates/src/objective-c/BoringSSL-GRPC.podspec.template index 2b3bb8d97a4..42e3c7a82ea 100644 --- a/templates/src/objective-c/BoringSSL-GRPC.podspec.template +++ b/templates/src/objective-c/BoringSSL-GRPC.podspec.template @@ -4,1559 +4,4532 @@ def expand_symbol_list(symbol_list): return ',\n '.join("'#define %s GRPC_SHADOW_%s'" % (symbol, symbol) for symbol in symbol_list) %> - # This file has been automatically generated from a template file. - # Please make modifications to - # `templates/src/objective-c/BoringSSL-GRPC.podspec.template` instead. This - # file can be regenerated from the template by running - # `tools/buildgen/generate_projects.sh`. - # BoringSSL CocoaPods podspec +# This file has been automatically generated from a template file. +# Please make modifications to +# `templates/src/objective-c/BoringSSL-GRPC.podspec.template` instead. This +# file can be regenerated from the template by running +# `tools/buildgen/generate_projects.sh`. - # Copyright 2015, Google Inc. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are - # met: - # - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # * Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following disclaimer - # in the documentation and/or other materials provided with the - # distribution. - # * Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# BoringSSL CocoaPods podspec + +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - Pod::Spec.new do |s| - s.name = 'BoringSSL-GRPC' - version = '0.0.2' - s.version = version - s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.' - # Adapted from the homepage: - s.description = <<-DESC - BoringSSL is a fork of OpenSSL that is designed to meet Google's needs. +Pod::Spec.new do |s| + s.name = 'BoringSSL-GRPC' + version = '0.0.2' + s.version = version + s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.' + # Adapted from the homepage: + s.description = <<-DESC + BoringSSL is a fork of OpenSSL that is designed to meet Google's needs. - Although BoringSSL is an open source project, it is not intended for general use, as OpenSSL is. - We don't recommend that third parties depend upon it. Doing so is likely to be frustrating - because there are no guarantees of API stability. Only the latest version of this pod is - supported, and every new version is a new major version. + Although BoringSSL is an open source project, it is not intended for general use, as OpenSSL is. + We don't recommend that third parties depend upon it. Doing so is likely to be frustrating + because there are no guarantees of API stability. Only the latest version of this pod is + supported, and every new version is a new major version. - We update Google libraries and programs that use BoringSSL as needed when deciding to make API - changes. This allows us to mostly avoid compromises in the name of compatibility. It works for - us, but it may not work for you. + We update Google libraries and programs that use BoringSSL as needed when deciding to make API + changes. This allows us to mostly avoid compromises in the name of compatibility. It works for + us, but it may not work for you. - As a Cocoapods pod, it has the advantage over OpenSSL's pods that the library doesn't need to - be precompiled. This eliminates the 10 - 20 minutes of wait the first time a user does "pod - install", lets it be used as a dynamic framework (pending solution of Cocoapods' issue #4605), - and works with bitcode automatically. It's also thought to be smaller than OpenSSL (which takes - 1MB - 2MB per ARM architecture), but we don't have specific numbers yet. + As a Cocoapods pod, it has the advantage over OpenSSL's pods that the library doesn't need to + be precompiled. This eliminates the 10 - 20 minutes of wait the first time a user does "pod + install", lets it be used as a dynamic framework (pending solution of Cocoapods' issue #4605), + and works with bitcode automatically. It's also thought to be smaller than OpenSSL (which takes + 1MB - 2MB per ARM architecture), but we don't have specific numbers yet. - BoringSSL arose because Google used OpenSSL for many years in various ways and, over time, built - up a large number of patches that were maintained while tracking upstream OpenSSL. As Google's - product portfolio became more complex, more copies of OpenSSL sprung up and the effort involved - in maintaining all these patches in multiple places was growing steadily. + BoringSSL arose because Google used OpenSSL for many years in various ways and, over time, built + up a large number of patches that were maintained while tracking upstream OpenSSL. As Google's + product portfolio became more complex, more copies of OpenSSL sprung up and the effort involved + in maintaining all these patches in multiple places was growing steadily. - Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it's not part of the - NDK) and a number of other apps/programs. - DESC - s.homepage = 'https://github.com/google/boringssl' - s.license = { :type => 'Mixed', :file => 'LICENSE' } - # "The name and email addresses of the library maintainers, not the Podspec maintainer." - s.authors = 'Adam Langley', 'David Benjamin', 'Matt Braithwaite' + Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it's not part of the + NDK) and a number of other apps/programs. + DESC + s.homepage = 'https://github.com/google/boringssl' + s.license = { :type => 'Mixed', :file => 'LICENSE' } + # "The name and email addresses of the library maintainers, not the Podspec maintainer." + s.authors = 'Adam Langley', 'David Benjamin', 'Matt Braithwaite' - s.source = { - :git => 'https://github.com/google/boringssl.git', - :commit => "b29b21a81b32ec273f118f589f46d56ad3332420", - } + s.source = { + :git => 'https://github.com/google/boringssl.git', + :commit => "b29b21a81b32ec273f118f589f46d56ad3332420", + } - s.ios.deployment_target = '5.0' - s.osx.deployment_target = '10.7' + s.ios.deployment_target = '5.0' + s.osx.deployment_target = '10.7' + s.tvos.deployment_target = '10.0' - name = 'openssl_grpc' + name = 'openssl_grpc' - # When creating a dynamic framework, name it openssl.framework instead of BoringSSL.framework. - # This lets users write their includes like `#include ` as opposed to `#include - # `. - s.module_name = name + # When creating a dynamic framework, name it openssl.framework instead of BoringSSL.framework. + # This lets users write their includes like `#include ` as opposed to `#include + # `. + s.module_name = name - # When creating a dynamic framework, copy the headers under `include/openssl/` into the root of - # the `Headers/` directory of the framework (i.e., not under `Headers/include/openssl`). - # - # TODO(jcanizales): Debug why this doesn't work on macOS. - s.header_mappings_dir = 'include/openssl' + # When creating a dynamic framework, copy the headers under `include/openssl/` into the root of + # the `Headers/` directory of the framework (i.e., not under `Headers/include/openssl`). + # + # TODO(jcanizales): Debug why this doesn't work on macOS. + s.header_mappings_dir = 'include/openssl' - # The above has an undesired effect when creating a static library: It forces users to write - # includes like `#include `. `s.header_dir` adds a path prefix to that, and - # because Cocoapods lets omit the pod name when including headers of static libraries, the - # following lets users write `#include `. - s.header_dir = name + # The above has an undesired effect when creating a static library: It forces users to write + # includes like `#include `. `s.header_dir` adds a path prefix to that, and + # because Cocoapods lets omit the pod name when including headers of static libraries, the + # following lets users write `#include `. + s.header_dir = name - # The module map and umbrella header created automatically by Cocoapods don't work for C libraries - # like this one. The following file, and a correct umbrella header, are created on the fly by the - # `prepare_command` of this pod. - s.module_map = 'include/openssl/BoringSSL.modulemap' + # The module map and umbrella header created automatically by Cocoapods don't work for C libraries + # like this one. The following file, and a correct umbrella header, are created on the fly by the + # `prepare_command` of this pod. + s.module_map = 'include/openssl/BoringSSL.modulemap' - # We don't need to inhibit all warnings; only -Wno-shorten-64-to-32. But Cocoapods' linter doesn't - # want that for some reason. - s.compiler_flags = '-DOPENSSL_NO_ASM', '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w' - s.requires_arc = false + # We don't need to inhibit all warnings; only -Wno-shorten-64-to-32. But Cocoapods' linter doesn't + # want that for some reason. + s.compiler_flags = '-DOPENSSL_NO_ASM', '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w' + s.requires_arc = false - # Like many other C libraries, BoringSSL has its public headers under `include//` and its - # sources and private headers in other directories outside `include/`. Cocoapods' linter doesn't - # allow any header to be listed outside the `header_mappings_dir` (even though doing so works in - # practice). Because we need our `header_mappings_dir` to be `include/openssl/` for the reason - # mentioned above, we work around the linter limitation by dividing the pod into two subspecs, one - # for public headers and the other for implementation. Each gets its own `header_mappings_dir`, - # making the linter happy. - s.subspec 'Interface' do |ss| - ss.header_mappings_dir = 'include/openssl' - ss.source_files = 'include/openssl/*.h' - end - s.subspec 'Implementation' do |ss| - ss.header_mappings_dir = '.' - ss.source_files = 'ssl/*.{h,cc}', - 'ssl/**/*.{h,cc}', - '*.{h,c}', - 'crypto/*.{h,c}', - 'crypto/**/*.{h,c}', - 'third_party/fiat/*.{h,c}' - ss.private_header_files = 'ssl/*.h', - 'ssl/**/*.h', - '*.h', - 'crypto/*.h', - 'crypto/**/*.h' - # bcm.c includes other source files, creating duplicated symbols. Since it is not used, we - # explicitly exclude it from the pod. - # TODO (mxyan): Work with BoringSSL team to remove this hack. - ss.exclude_files = 'crypto/fipsmodule/bcm.c', - '**/*_test.*', - '**/test_*.*', - '**/test/*.*' + # Like many other C libraries, BoringSSL has its public headers under `include//` and its + # sources and private headers in other directories outside `include/`. Cocoapods' linter doesn't + # allow any header to be listed outside the `header_mappings_dir` (even though doing so works in + # practice). Because we need our `header_mappings_dir` to be `include/openssl/` for the reason + # mentioned above, we work around the linter limitation by dividing the pod into two subspecs, one + # for public headers and the other for implementation. Each gets its own `header_mappings_dir`, + # making the linter happy. + s.subspec 'Interface' do |ss| + ss.header_mappings_dir = 'include/openssl' + ss.source_files = 'include/openssl/*.h' + end + s.subspec 'Implementation' do |ss| + ss.header_mappings_dir = '.' + ss.source_files = 'ssl/*.{h,cc}', + 'ssl/**/*.{h,cc}', + '*.{h,c}', + 'crypto/*.{h,c}', + 'crypto/**/*.{h,c}', + 'third_party/fiat/*.{h,c}' + ss.private_header_files = 'ssl/*.h', + 'ssl/**/*.h', + '*.h', + 'crypto/*.h', + 'crypto/**/*.h' + # bcm.c includes other source files, creating duplicated symbols. Since it is not used, we + # explicitly exclude it from the pod. + # TODO (mxyan): Work with BoringSSL team to remove this hack. + ss.exclude_files = 'crypto/fipsmodule/bcm.c', + '**/*_test.*', + '**/test_*.*', + '**/test/*.*' - ss.dependency "#{s.name}/Interface", version - end + ss.dependency "#{s.name}/Interface", version + end - s.prepare_command = <<-END_OF_COMMAND - # Add a module map and an umbrella header - cat > include/openssl/umbrella.h < include/openssl/BoringSSL.modulemap < include/openssl/umbrella.h < include/openssl/BoringSSL.modulemap < err_data.c < err_data.c < - #include - #include + #include + #include + #include - OPENSSL_COMPILE_ASSERT(ERR_LIB_NONE == 1, library_values_changed_1); - OPENSSL_COMPILE_ASSERT(ERR_LIB_SYS == 2, library_values_changed_2); - OPENSSL_COMPILE_ASSERT(ERR_LIB_BN == 3, library_values_changed_3); - OPENSSL_COMPILE_ASSERT(ERR_LIB_RSA == 4, library_values_changed_4); - OPENSSL_COMPILE_ASSERT(ERR_LIB_DH == 5, library_values_changed_5); - OPENSSL_COMPILE_ASSERT(ERR_LIB_EVP == 6, library_values_changed_6); - OPENSSL_COMPILE_ASSERT(ERR_LIB_BUF == 7, library_values_changed_7); - OPENSSL_COMPILE_ASSERT(ERR_LIB_OBJ == 8, library_values_changed_8); - OPENSSL_COMPILE_ASSERT(ERR_LIB_PEM == 9, library_values_changed_9); - OPENSSL_COMPILE_ASSERT(ERR_LIB_DSA == 10, library_values_changed_10); - OPENSSL_COMPILE_ASSERT(ERR_LIB_X509 == 11, library_values_changed_11); - OPENSSL_COMPILE_ASSERT(ERR_LIB_ASN1 == 12, library_values_changed_12); - OPENSSL_COMPILE_ASSERT(ERR_LIB_CONF == 13, library_values_changed_13); - OPENSSL_COMPILE_ASSERT(ERR_LIB_CRYPTO == 14, library_values_changed_14); - OPENSSL_COMPILE_ASSERT(ERR_LIB_EC == 15, library_values_changed_15); - OPENSSL_COMPILE_ASSERT(ERR_LIB_SSL == 16, library_values_changed_16); - OPENSSL_COMPILE_ASSERT(ERR_LIB_BIO == 17, library_values_changed_17); - OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS7 == 18, library_values_changed_18); - OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS8 == 19, library_values_changed_19); - OPENSSL_COMPILE_ASSERT(ERR_LIB_X509V3 == 20, library_values_changed_20); - OPENSSL_COMPILE_ASSERT(ERR_LIB_RAND == 21, library_values_changed_21); - OPENSSL_COMPILE_ASSERT(ERR_LIB_ENGINE == 22, library_values_changed_22); - OPENSSL_COMPILE_ASSERT(ERR_LIB_OCSP == 23, library_values_changed_23); - OPENSSL_COMPILE_ASSERT(ERR_LIB_UI == 24, library_values_changed_24); - OPENSSL_COMPILE_ASSERT(ERR_LIB_COMP == 25, library_values_changed_25); - OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDSA == 26, library_values_changed_26); - OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDH == 27, library_values_changed_27); - OPENSSL_COMPILE_ASSERT(ERR_LIB_HMAC == 28, library_values_changed_28); - OPENSSL_COMPILE_ASSERT(ERR_LIB_DIGEST == 29, library_values_changed_29); - OPENSSL_COMPILE_ASSERT(ERR_LIB_CIPHER == 30, library_values_changed_30); - OPENSSL_COMPILE_ASSERT(ERR_LIB_HKDF == 31, library_values_changed_31); - OPENSSL_COMPILE_ASSERT(ERR_LIB_USER == 32, library_values_changed_32); - OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num); + OPENSSL_COMPILE_ASSERT(ERR_LIB_NONE == 1, library_values_changed_1); + OPENSSL_COMPILE_ASSERT(ERR_LIB_SYS == 2, library_values_changed_2); + OPENSSL_COMPILE_ASSERT(ERR_LIB_BN == 3, library_values_changed_3); + OPENSSL_COMPILE_ASSERT(ERR_LIB_RSA == 4, library_values_changed_4); + OPENSSL_COMPILE_ASSERT(ERR_LIB_DH == 5, library_values_changed_5); + OPENSSL_COMPILE_ASSERT(ERR_LIB_EVP == 6, library_values_changed_6); + OPENSSL_COMPILE_ASSERT(ERR_LIB_BUF == 7, library_values_changed_7); + OPENSSL_COMPILE_ASSERT(ERR_LIB_OBJ == 8, library_values_changed_8); + OPENSSL_COMPILE_ASSERT(ERR_LIB_PEM == 9, library_values_changed_9); + OPENSSL_COMPILE_ASSERT(ERR_LIB_DSA == 10, library_values_changed_10); + OPENSSL_COMPILE_ASSERT(ERR_LIB_X509 == 11, library_values_changed_11); + OPENSSL_COMPILE_ASSERT(ERR_LIB_ASN1 == 12, library_values_changed_12); + OPENSSL_COMPILE_ASSERT(ERR_LIB_CONF == 13, library_values_changed_13); + OPENSSL_COMPILE_ASSERT(ERR_LIB_CRYPTO == 14, library_values_changed_14); + OPENSSL_COMPILE_ASSERT(ERR_LIB_EC == 15, library_values_changed_15); + OPENSSL_COMPILE_ASSERT(ERR_LIB_SSL == 16, library_values_changed_16); + OPENSSL_COMPILE_ASSERT(ERR_LIB_BIO == 17, library_values_changed_17); + OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS7 == 18, library_values_changed_18); + OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS8 == 19, library_values_changed_19); + OPENSSL_COMPILE_ASSERT(ERR_LIB_X509V3 == 20, library_values_changed_20); + OPENSSL_COMPILE_ASSERT(ERR_LIB_RAND == 21, library_values_changed_21); + OPENSSL_COMPILE_ASSERT(ERR_LIB_ENGINE == 22, library_values_changed_22); + OPENSSL_COMPILE_ASSERT(ERR_LIB_OCSP == 23, library_values_changed_23); + OPENSSL_COMPILE_ASSERT(ERR_LIB_UI == 24, library_values_changed_24); + OPENSSL_COMPILE_ASSERT(ERR_LIB_COMP == 25, library_values_changed_25); + OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDSA == 26, library_values_changed_26); + OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDH == 27, library_values_changed_27); + OPENSSL_COMPILE_ASSERT(ERR_LIB_HMAC == 28, library_values_changed_28); + OPENSSL_COMPILE_ASSERT(ERR_LIB_DIGEST == 29, library_values_changed_29); + OPENSSL_COMPILE_ASSERT(ERR_LIB_CIPHER == 30, library_values_changed_30); + OPENSSL_COMPILE_ASSERT(ERR_LIB_HKDF == 31, library_values_changed_31); + OPENSSL_COMPILE_ASSERT(ERR_LIB_USER == 32, library_values_changed_32); + OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num); - const uint32_t kOpenSSLReasonValues[] = { - 0xc320838, - 0xc328852, - 0xc330861, - 0xc338871, - 0xc340880, - 0xc348899, - 0xc3508a5, - 0xc3588c2, - 0xc3608e2, - 0xc3688f0, - 0xc370900, - 0xc37890d, - 0xc38091d, - 0xc388928, - 0xc39093e, - 0xc39894d, - 0xc3a0961, - 0xc3a8845, - 0xc3b00ea, - 0xc3b88d4, - 0x10320845, - 0x10329513, - 0x1033151f, - 0x10339538, - 0x1034154b, - 0x10348eed, - 0x10350c5e, - 0x1035955e, - 0x10361573, - 0x10369586, - 0x103715a5, - 0x103795be, - 0x103815d3, - 0x103895f1, - 0x10391600, - 0x1039961c, - 0x103a1637, - 0x103a9646, - 0x103b1662, - 0x103b967d, - 0x103c1694, - 0x103c80ea, - 0x103d16a5, - 0x103d96b9, - 0x103e16d8, - 0x103e96e7, - 0x103f16fe, - 0x103f9711, - 0x10400c22, - 0x10409724, - 0x10411742, - 0x10419755, - 0x1042176f, - 0x1042977f, - 0x10431793, - 0x104397a9, - 0x104417c1, - 0x104497d6, - 0x104517ea, - 0x104597fc, - 0x104605fb, - 0x1046894d, - 0x10471811, - 0x10479828, - 0x1048183d, - 0x1048984b, - 0x10490e4f, - 0x14320c05, - 0x14328c13, - 0x14330c22, - 0x14338c34, - 0x143400ac, - 0x143480ea, - 0x18320083, - 0x18328f43, - 0x183300ac, - 0x18338f59, - 0x18340f6d, - 0x183480ea, - 0x18350f82, - 0x18358f9a, - 0x18360faf, - 0x18368fc3, - 0x18370fe7, - 0x18378ffd, - 0x18381011, - 0x18389021, - 0x18390a73, - 0x18399031, - 0x183a1059, - 0x183a907f, - 0x183b0c6a, - 0x183b90b4, - 0x183c10c6, - 0x183c90d1, - 0x183d10e1, - 0x183d90f2, - 0x183e1103, - 0x183e9115, - 0x183f113e, - 0x183f9157, - 0x1840116f, - 0x184086d3, - 0x184110a2, - 0x1841906d, - 0x1842108c, - 0x18429046, - 0x20321196, - 0x243211a2, - 0x24328993, - 0x243311b4, - 0x243391c1, - 0x243411ce, - 0x243491e0, - 0x243511ef, - 0x2435920c, - 0x24361219, - 0x24369227, - 0x24371235, - 0x24379243, - 0x2438124c, - 0x24389259, - 0x2439126c, - 0x28320c52, - 0x28328c6a, - 0x28330c22, - 0x28338c7d, - 0x28340c5e, - 0x283480ac, - 0x283500ea, - 0x2c322c30, - 0x2c329283, - 0x2c332c3e, - 0x2c33ac50, - 0x2c342c64, - 0x2c34ac76, - 0x2c352c91, - 0x2c35aca3, - 0x2c362cb6, - 0x2c36832d, - 0x2c372cc3, - 0x2c37acd5, - 0x2c382cfa, - 0x2c38ad11, - 0x2c392d1f, - 0x2c39ad2f, - 0x2c3a2d41, - 0x2c3aad55, - 0x2c3b2d66, - 0x2c3bad85, - 0x2c3c1295, - 0x2c3c92ab, - 0x2c3d2d99, - 0x2c3d92c4, - 0x2c3e2db6, - 0x2c3eadc4, - 0x2c3f2ddc, - 0x2c3fadf4, - 0x2c402e01, - 0x2c409196, - 0x2c412e12, - 0x2c41ae25, - 0x2c42116f, - 0x2c42ae36, - 0x2c430720, - 0x2c43ad77, - 0x2c442ce8, - 0x30320000, - 0x30328015, - 0x3033001f, - 0x30338038, - 0x3034004a, - 0x30348064, - 0x3035006b, - 0x30358083, - 0x30360094, - 0x303680ac, - 0x303700b9, - 0x303780c8, - 0x303800ea, - 0x303880f7, - 0x3039010a, - 0x30398125, - 0x303a013a, - 0x303a814e, - 0x303b0162, - 0x303b8173, - 0x303c018c, - 0x303c81a9, - 0x303d01b7, - 0x303d81cb, - 0x303e01db, - 0x303e81f4, - 0x303f0204, - 0x303f8217, - 0x30400226, - 0x30408232, - 0x30410247, - 0x30418257, - 0x3042026e, - 0x3042827b, - 0x3043028e, - 0x3043829d, - 0x304402b2, - 0x304482d3, - 0x304502e6, - 0x304582f9, - 0x30460312, - 0x3046832d, - 0x3047034a, - 0x30478363, - 0x30480371, - 0x30488382, - 0x30490391, - 0x304983a9, - 0x304a03bb, - 0x304a83cf, - 0x304b03ee, - 0x304b8401, - 0x304c040c, - 0x304c841d, - 0x304d0429, - 0x304d843f, - 0x304e044d, - 0x304e8463, - 0x304f0475, - 0x304f8487, - 0x3050049a, - 0x305084ad, - 0x305104be, - 0x305184ce, - 0x305204e6, - 0x305284fb, - 0x30530513, - 0x30538527, - 0x3054053f, - 0x30548558, - 0x30550571, - 0x3055858e, - 0x30560599, - 0x305685b1, - 0x305705c1, - 0x305785d2, - 0x305805e5, - 0x305885fb, - 0x30590604, - 0x30598619, - 0x305a062c, - 0x305a863b, - 0x305b065b, - 0x305b866a, - 0x305c068b, - 0x305c86a7, - 0x305d06b3, - 0x305d86d3, - 0x305e06ef, - 0x305e8700, - 0x305f0716, - 0x305f8720, - 0x34320b63, - 0x34328b77, - 0x34330b94, - 0x34338ba7, - 0x34340bb6, - 0x34348bef, - 0x34350bd3, - 0x3c320083, - 0x3c328ca7, - 0x3c330cc0, - 0x3c338cdb, - 0x3c340cf8, - 0x3c348d22, - 0x3c350d3d, - 0x3c358d63, - 0x3c360d7c, - 0x3c368d94, - 0x3c370da5, - 0x3c378db3, - 0x3c380dc0, - 0x3c388dd4, - 0x3c390c6a, - 0x3c398de8, - 0x3c3a0dfc, - 0x3c3a890d, - 0x3c3b0e0c, - 0x3c3b8e27, - 0x3c3c0e39, - 0x3c3c8e6c, - 0x3c3d0e76, - 0x3c3d8e8a, - 0x3c3e0e98, - 0x3c3e8ebd, - 0x3c3f0c93, - 0x3c3f8ea6, - 0x3c4000ac, - 0x3c4080ea, - 0x3c410d13, - 0x3c418d52, - 0x3c420e4f, - 0x403218a4, - 0x403298ba, - 0x403318e8, - 0x403398f2, - 0x40341909, - 0x40349927, - 0x40351937, - 0x40359949, - 0x40361956, - 0x40369962, - 0x40371977, - 0x40379989, - 0x40381994, - 0x403899a6, - 0x40390eed, - 0x403999b6, - 0x403a19c9, - 0x403a99ea, - 0x403b19fb, - 0x403b9a0b, - 0x403c0064, - 0x403c8083, - 0x403d1a8f, - 0x403d9aa5, - 0x403e1ab4, - 0x403e9aec, - 0x403f1b06, - 0x403f9b14, - 0x40401b29, - 0x40409b3d, - 0x40411b5a, - 0x40419b75, - 0x40421b8e, - 0x40429ba1, - 0x40431bb5, - 0x40439bcd, - 0x40441be4, - 0x404480ac, - 0x40451bf9, - 0x40459c0b, - 0x40461c2f, - 0x40469c4f, - 0x40471c5d, - 0x40479c84, - 0x40481cc1, - 0x40489cda, - 0x40491cf1, - 0x40499d0b, - 0x404a1d22, - 0x404a9d40, - 0x404b1d58, - 0x404b9d6f, - 0x404c1d85, - 0x404c9d97, - 0x404d1db8, - 0x404d9dda, - 0x404e1dee, - 0x404e9dfb, - 0x404f1e28, - 0x404f9e51, - 0x40501e8c, - 0x40509ea0, - 0x40511ebb, - 0x40521ecb, - 0x40529eef, - 0x40531f07, - 0x40539f1a, - 0x40541f2f, - 0x40549f52, - 0x40551f60, - 0x40559f7d, - 0x40561f8a, - 0x40569fa3, - 0x40571fbb, - 0x40579fce, - 0x40581fe3, - 0x4058a00a, - 0x40592039, - 0x4059a066, - 0x405a207a, - 0x405aa08a, - 0x405b20a2, - 0x405ba0b3, - 0x405c20c6, - 0x405ca105, - 0x405d2112, - 0x405da129, - 0x405e2167, - 0x405e8ab1, - 0x405f2188, - 0x405fa195, - 0x406021a3, - 0x4060a1c5, - 0x40612209, - 0x4061a241, - 0x40622258, - 0x4062a269, - 0x4063227a, - 0x4063a28f, - 0x406422a6, - 0x4064a2d2, - 0x406522ed, - 0x4065a304, - 0x4066231c, - 0x4066a346, - 0x40672371, - 0x4067a392, - 0x406823b9, - 0x4068a3da, - 0x4069240c, - 0x4069a43a, - 0x406a245b, - 0x406aa47b, - 0x406b2603, - 0x406ba626, - 0x406c263c, - 0x406ca8b7, - 0x406d28e6, - 0x406da90e, - 0x406e293c, - 0x406ea989, - 0x406f29a8, - 0x406fa9e0, - 0x407029f3, - 0x4070aa10, - 0x40710800, - 0x4071aa22, - 0x40722a35, - 0x4072aa4e, - 0x40732a66, - 0x40739482, - 0x40742a7a, - 0x4074aa94, - 0x40752aa5, - 0x4075aab9, - 0x40762ac7, - 0x40769259, - 0x40772aec, - 0x4077ab0e, - 0x40782b29, - 0x4078ab62, - 0x40792b79, - 0x4079ab8f, - 0x407a2b9b, - 0x407aabae, - 0x407b2bc3, - 0x407babd5, - 0x407c2c06, - 0x407cac0f, - 0x407d23f5, - 0x407d9e61, - 0x407e2b3e, - 0x407ea01a, - 0x407f1c71, - 0x407f9a31, - 0x40801e38, - 0x40809c99, - 0x40811edd, - 0x40819e12, - 0x40822927, - 0x40829a17, - 0x40831ff5, - 0x4083a2b7, - 0x40841cad, - 0x4084a052, - 0x408520d7, - 0x4085a1ed, - 0x40862149, - 0x40869e7b, - 0x4087296d, - 0x4087a21e, - 0x40881a78, - 0x4088a3a5, - 0x40891ac7, - 0x40899a54, - 0x408a265c, - 0x408a9862, - 0x408b2bea, - 0x408ba9bd, - 0x408c20e7, - 0x408c987e, - 0x41f4252e, - 0x41f925c0, - 0x41fe24b3, - 0x41fea6a8, - 0x41ff2799, - 0x42032547, - 0x42082569, - 0x4208a5a5, - 0x42092497, - 0x4209a5df, - 0x420a24ee, - 0x420aa4ce, - 0x420b250e, - 0x420ba587, - 0x420c27b5, - 0x420ca675, - 0x420d268f, - 0x420da6c6, - 0x421226e0, - 0x4217277c, - 0x4217a722, - 0x421c2744, - 0x421f26ff, - 0x422127cc, - 0x4226275f, - 0x422b289b, - 0x422ba849, - 0x422c2883, - 0x422ca808, - 0x422d27e7, - 0x422da868, - 0x422e282e, - 0x422ea954, - 0x4432072b, - 0x4432873a, - 0x44330746, - 0x44338754, - 0x44340767, - 0x44348778, - 0x4435077f, - 0x44358789, - 0x4436079c, - 0x443687b2, - 0x443707c4, - 0x443787d1, - 0x443807e0, - 0x443887e8, - 0x44390800, - 0x4439880e, - 0x443a0821, - 0x48321283, - 0x48329295, - 0x483312ab, - 0x483392c4, - 0x4c3212e9, - 0x4c3292f9, - 0x4c33130c, - 0x4c33932c, - 0x4c3400ac, - 0x4c3480ea, - 0x4c351338, - 0x4c359346, - 0x4c361362, - 0x4c369375, - 0x4c371384, - 0x4c379392, - 0x4c3813a7, - 0x4c3893b3, - 0x4c3913d3, - 0x4c3993fd, - 0x4c3a1416, - 0x4c3a942f, - 0x4c3b05fb, - 0x4c3b9448, - 0x4c3c145a, - 0x4c3c9469, - 0x4c3d1482, - 0x4c3d8c45, - 0x4c3e14db, - 0x4c3e9491, - 0x4c3f14fd, - 0x4c3f9259, - 0x4c4014a7, - 0x4c4092d5, - 0x4c4114cb, - 0x50322e48, - 0x5032ae57, - 0x50332e62, - 0x5033ae72, - 0x50342e8b, - 0x5034aea5, - 0x50352eb3, - 0x5035aec9, - 0x50362edb, - 0x5036aef1, - 0x50372f0a, - 0x5037af1d, - 0x50382f35, - 0x5038af46, - 0x50392f5b, - 0x5039af6f, - 0x503a2f8f, - 0x503aafa5, - 0x503b2fbd, - 0x503bafcf, - 0x503c2feb, - 0x503cb002, - 0x503d301b, - 0x503db031, - 0x503e303e, - 0x503eb054, - 0x503f3066, - 0x503f8382, - 0x50403079, - 0x5040b089, - 0x504130a3, - 0x5041b0b2, - 0x504230cc, - 0x5042b0e9, - 0x504330f9, - 0x5043b109, - 0x50443118, - 0x5044843f, - 0x5045312c, - 0x5045b14a, - 0x5046315d, - 0x5046b173, - 0x50473185, - 0x5047b19a, - 0x504831c0, - 0x5048b1ce, - 0x504931e1, - 0x5049b1f6, - 0x504a320c, - 0x504ab21c, - 0x504b323c, - 0x504bb24f, - 0x504c3272, - 0x504cb2a0, - 0x504d32b2, - 0x504db2cf, - 0x504e32ea, - 0x504eb306, - 0x504f3318, - 0x504fb32f, - 0x5050333e, - 0x505086ef, - 0x50513351, - 0x58320f2b, - 0x68320eed, - 0x68328c6a, - 0x68330c7d, - 0x68338efb, - 0x68340f0b, - 0x683480ea, - 0x6c320ec9, - 0x6c328c34, - 0x6c330ed4, - 0x74320a19, - 0x743280ac, - 0x74330c45, - 0x7832097e, - 0x78328993, - 0x7833099f, - 0x78338083, - 0x783409ae, - 0x783489c3, - 0x783509e2, - 0x78358a04, - 0x78360a19, - 0x78368a2f, - 0x78370a3f, - 0x78378a60, - 0x78380a73, - 0x78388a85, - 0x78390a92, - 0x78398ab1, - 0x783a0ac6, - 0x783a8ad4, - 0x783b0ade, - 0x783b8af2, - 0x783c0b09, - 0x783c8b1e, - 0x783d0b35, - 0x783d8b4a, - 0x783e0aa0, - 0x783e8a52, - 0x7c321185, - }; + const uint32_t kOpenSSLReasonValues[] = { + 0xc320838, + 0xc328852, + 0xc330861, + 0xc338871, + 0xc340880, + 0xc348899, + 0xc3508a5, + 0xc3588c2, + 0xc3608e2, + 0xc3688f0, + 0xc370900, + 0xc37890d, + 0xc38091d, + 0xc388928, + 0xc39093e, + 0xc39894d, + 0xc3a0961, + 0xc3a8845, + 0xc3b00ea, + 0xc3b88d4, + 0x10320845, + 0x10329513, + 0x1033151f, + 0x10339538, + 0x1034154b, + 0x10348eed, + 0x10350c5e, + 0x1035955e, + 0x10361573, + 0x10369586, + 0x103715a5, + 0x103795be, + 0x103815d3, + 0x103895f1, + 0x10391600, + 0x1039961c, + 0x103a1637, + 0x103a9646, + 0x103b1662, + 0x103b967d, + 0x103c1694, + 0x103c80ea, + 0x103d16a5, + 0x103d96b9, + 0x103e16d8, + 0x103e96e7, + 0x103f16fe, + 0x103f9711, + 0x10400c22, + 0x10409724, + 0x10411742, + 0x10419755, + 0x1042176f, + 0x1042977f, + 0x10431793, + 0x104397a9, + 0x104417c1, + 0x104497d6, + 0x104517ea, + 0x104597fc, + 0x104605fb, + 0x1046894d, + 0x10471811, + 0x10479828, + 0x1048183d, + 0x1048984b, + 0x10490e4f, + 0x14320c05, + 0x14328c13, + 0x14330c22, + 0x14338c34, + 0x143400ac, + 0x143480ea, + 0x18320083, + 0x18328f43, + 0x183300ac, + 0x18338f59, + 0x18340f6d, + 0x183480ea, + 0x18350f82, + 0x18358f9a, + 0x18360faf, + 0x18368fc3, + 0x18370fe7, + 0x18378ffd, + 0x18381011, + 0x18389021, + 0x18390a73, + 0x18399031, + 0x183a1059, + 0x183a907f, + 0x183b0c6a, + 0x183b90b4, + 0x183c10c6, + 0x183c90d1, + 0x183d10e1, + 0x183d90f2, + 0x183e1103, + 0x183e9115, + 0x183f113e, + 0x183f9157, + 0x1840116f, + 0x184086d3, + 0x184110a2, + 0x1841906d, + 0x1842108c, + 0x18429046, + 0x20321196, + 0x243211a2, + 0x24328993, + 0x243311b4, + 0x243391c1, + 0x243411ce, + 0x243491e0, + 0x243511ef, + 0x2435920c, + 0x24361219, + 0x24369227, + 0x24371235, + 0x24379243, + 0x2438124c, + 0x24389259, + 0x2439126c, + 0x28320c52, + 0x28328c6a, + 0x28330c22, + 0x28338c7d, + 0x28340c5e, + 0x283480ac, + 0x283500ea, + 0x2c322c30, + 0x2c329283, + 0x2c332c3e, + 0x2c33ac50, + 0x2c342c64, + 0x2c34ac76, + 0x2c352c91, + 0x2c35aca3, + 0x2c362cb6, + 0x2c36832d, + 0x2c372cc3, + 0x2c37acd5, + 0x2c382cfa, + 0x2c38ad11, + 0x2c392d1f, + 0x2c39ad2f, + 0x2c3a2d41, + 0x2c3aad55, + 0x2c3b2d66, + 0x2c3bad85, + 0x2c3c1295, + 0x2c3c92ab, + 0x2c3d2d99, + 0x2c3d92c4, + 0x2c3e2db6, + 0x2c3eadc4, + 0x2c3f2ddc, + 0x2c3fadf4, + 0x2c402e01, + 0x2c409196, + 0x2c412e12, + 0x2c41ae25, + 0x2c42116f, + 0x2c42ae36, + 0x2c430720, + 0x2c43ad77, + 0x2c442ce8, + 0x30320000, + 0x30328015, + 0x3033001f, + 0x30338038, + 0x3034004a, + 0x30348064, + 0x3035006b, + 0x30358083, + 0x30360094, + 0x303680ac, + 0x303700b9, + 0x303780c8, + 0x303800ea, + 0x303880f7, + 0x3039010a, + 0x30398125, + 0x303a013a, + 0x303a814e, + 0x303b0162, + 0x303b8173, + 0x303c018c, + 0x303c81a9, + 0x303d01b7, + 0x303d81cb, + 0x303e01db, + 0x303e81f4, + 0x303f0204, + 0x303f8217, + 0x30400226, + 0x30408232, + 0x30410247, + 0x30418257, + 0x3042026e, + 0x3042827b, + 0x3043028e, + 0x3043829d, + 0x304402b2, + 0x304482d3, + 0x304502e6, + 0x304582f9, + 0x30460312, + 0x3046832d, + 0x3047034a, + 0x30478363, + 0x30480371, + 0x30488382, + 0x30490391, + 0x304983a9, + 0x304a03bb, + 0x304a83cf, + 0x304b03ee, + 0x304b8401, + 0x304c040c, + 0x304c841d, + 0x304d0429, + 0x304d843f, + 0x304e044d, + 0x304e8463, + 0x304f0475, + 0x304f8487, + 0x3050049a, + 0x305084ad, + 0x305104be, + 0x305184ce, + 0x305204e6, + 0x305284fb, + 0x30530513, + 0x30538527, + 0x3054053f, + 0x30548558, + 0x30550571, + 0x3055858e, + 0x30560599, + 0x305685b1, + 0x305705c1, + 0x305785d2, + 0x305805e5, + 0x305885fb, + 0x30590604, + 0x30598619, + 0x305a062c, + 0x305a863b, + 0x305b065b, + 0x305b866a, + 0x305c068b, + 0x305c86a7, + 0x305d06b3, + 0x305d86d3, + 0x305e06ef, + 0x305e8700, + 0x305f0716, + 0x305f8720, + 0x34320b63, + 0x34328b77, + 0x34330b94, + 0x34338ba7, + 0x34340bb6, + 0x34348bef, + 0x34350bd3, + 0x3c320083, + 0x3c328ca7, + 0x3c330cc0, + 0x3c338cdb, + 0x3c340cf8, + 0x3c348d22, + 0x3c350d3d, + 0x3c358d63, + 0x3c360d7c, + 0x3c368d94, + 0x3c370da5, + 0x3c378db3, + 0x3c380dc0, + 0x3c388dd4, + 0x3c390c6a, + 0x3c398de8, + 0x3c3a0dfc, + 0x3c3a890d, + 0x3c3b0e0c, + 0x3c3b8e27, + 0x3c3c0e39, + 0x3c3c8e6c, + 0x3c3d0e76, + 0x3c3d8e8a, + 0x3c3e0e98, + 0x3c3e8ebd, + 0x3c3f0c93, + 0x3c3f8ea6, + 0x3c4000ac, + 0x3c4080ea, + 0x3c410d13, + 0x3c418d52, + 0x3c420e4f, + 0x403218a4, + 0x403298ba, + 0x403318e8, + 0x403398f2, + 0x40341909, + 0x40349927, + 0x40351937, + 0x40359949, + 0x40361956, + 0x40369962, + 0x40371977, + 0x40379989, + 0x40381994, + 0x403899a6, + 0x40390eed, + 0x403999b6, + 0x403a19c9, + 0x403a99ea, + 0x403b19fb, + 0x403b9a0b, + 0x403c0064, + 0x403c8083, + 0x403d1a8f, + 0x403d9aa5, + 0x403e1ab4, + 0x403e9aec, + 0x403f1b06, + 0x403f9b14, + 0x40401b29, + 0x40409b3d, + 0x40411b5a, + 0x40419b75, + 0x40421b8e, + 0x40429ba1, + 0x40431bb5, + 0x40439bcd, + 0x40441be4, + 0x404480ac, + 0x40451bf9, + 0x40459c0b, + 0x40461c2f, + 0x40469c4f, + 0x40471c5d, + 0x40479c84, + 0x40481cc1, + 0x40489cda, + 0x40491cf1, + 0x40499d0b, + 0x404a1d22, + 0x404a9d40, + 0x404b1d58, + 0x404b9d6f, + 0x404c1d85, + 0x404c9d97, + 0x404d1db8, + 0x404d9dda, + 0x404e1dee, + 0x404e9dfb, + 0x404f1e28, + 0x404f9e51, + 0x40501e8c, + 0x40509ea0, + 0x40511ebb, + 0x40521ecb, + 0x40529eef, + 0x40531f07, + 0x40539f1a, + 0x40541f2f, + 0x40549f52, + 0x40551f60, + 0x40559f7d, + 0x40561f8a, + 0x40569fa3, + 0x40571fbb, + 0x40579fce, + 0x40581fe3, + 0x4058a00a, + 0x40592039, + 0x4059a066, + 0x405a207a, + 0x405aa08a, + 0x405b20a2, + 0x405ba0b3, + 0x405c20c6, + 0x405ca105, + 0x405d2112, + 0x405da129, + 0x405e2167, + 0x405e8ab1, + 0x405f2188, + 0x405fa195, + 0x406021a3, + 0x4060a1c5, + 0x40612209, + 0x4061a241, + 0x40622258, + 0x4062a269, + 0x4063227a, + 0x4063a28f, + 0x406422a6, + 0x4064a2d2, + 0x406522ed, + 0x4065a304, + 0x4066231c, + 0x4066a346, + 0x40672371, + 0x4067a392, + 0x406823b9, + 0x4068a3da, + 0x4069240c, + 0x4069a43a, + 0x406a245b, + 0x406aa47b, + 0x406b2603, + 0x406ba626, + 0x406c263c, + 0x406ca8b7, + 0x406d28e6, + 0x406da90e, + 0x406e293c, + 0x406ea989, + 0x406f29a8, + 0x406fa9e0, + 0x407029f3, + 0x4070aa10, + 0x40710800, + 0x4071aa22, + 0x40722a35, + 0x4072aa4e, + 0x40732a66, + 0x40739482, + 0x40742a7a, + 0x4074aa94, + 0x40752aa5, + 0x4075aab9, + 0x40762ac7, + 0x40769259, + 0x40772aec, + 0x4077ab0e, + 0x40782b29, + 0x4078ab62, + 0x40792b79, + 0x4079ab8f, + 0x407a2b9b, + 0x407aabae, + 0x407b2bc3, + 0x407babd5, + 0x407c2c06, + 0x407cac0f, + 0x407d23f5, + 0x407d9e61, + 0x407e2b3e, + 0x407ea01a, + 0x407f1c71, + 0x407f9a31, + 0x40801e38, + 0x40809c99, + 0x40811edd, + 0x40819e12, + 0x40822927, + 0x40829a17, + 0x40831ff5, + 0x4083a2b7, + 0x40841cad, + 0x4084a052, + 0x408520d7, + 0x4085a1ed, + 0x40862149, + 0x40869e7b, + 0x4087296d, + 0x4087a21e, + 0x40881a78, + 0x4088a3a5, + 0x40891ac7, + 0x40899a54, + 0x408a265c, + 0x408a9862, + 0x408b2bea, + 0x408ba9bd, + 0x408c20e7, + 0x408c987e, + 0x41f4252e, + 0x41f925c0, + 0x41fe24b3, + 0x41fea6a8, + 0x41ff2799, + 0x42032547, + 0x42082569, + 0x4208a5a5, + 0x42092497, + 0x4209a5df, + 0x420a24ee, + 0x420aa4ce, + 0x420b250e, + 0x420ba587, + 0x420c27b5, + 0x420ca675, + 0x420d268f, + 0x420da6c6, + 0x421226e0, + 0x4217277c, + 0x4217a722, + 0x421c2744, + 0x421f26ff, + 0x422127cc, + 0x4226275f, + 0x422b289b, + 0x422ba849, + 0x422c2883, + 0x422ca808, + 0x422d27e7, + 0x422da868, + 0x422e282e, + 0x422ea954, + 0x4432072b, + 0x4432873a, + 0x44330746, + 0x44338754, + 0x44340767, + 0x44348778, + 0x4435077f, + 0x44358789, + 0x4436079c, + 0x443687b2, + 0x443707c4, + 0x443787d1, + 0x443807e0, + 0x443887e8, + 0x44390800, + 0x4439880e, + 0x443a0821, + 0x48321283, + 0x48329295, + 0x483312ab, + 0x483392c4, + 0x4c3212e9, + 0x4c3292f9, + 0x4c33130c, + 0x4c33932c, + 0x4c3400ac, + 0x4c3480ea, + 0x4c351338, + 0x4c359346, + 0x4c361362, + 0x4c369375, + 0x4c371384, + 0x4c379392, + 0x4c3813a7, + 0x4c3893b3, + 0x4c3913d3, + 0x4c3993fd, + 0x4c3a1416, + 0x4c3a942f, + 0x4c3b05fb, + 0x4c3b9448, + 0x4c3c145a, + 0x4c3c9469, + 0x4c3d1482, + 0x4c3d8c45, + 0x4c3e14db, + 0x4c3e9491, + 0x4c3f14fd, + 0x4c3f9259, + 0x4c4014a7, + 0x4c4092d5, + 0x4c4114cb, + 0x50322e48, + 0x5032ae57, + 0x50332e62, + 0x5033ae72, + 0x50342e8b, + 0x5034aea5, + 0x50352eb3, + 0x5035aec9, + 0x50362edb, + 0x5036aef1, + 0x50372f0a, + 0x5037af1d, + 0x50382f35, + 0x5038af46, + 0x50392f5b, + 0x5039af6f, + 0x503a2f8f, + 0x503aafa5, + 0x503b2fbd, + 0x503bafcf, + 0x503c2feb, + 0x503cb002, + 0x503d301b, + 0x503db031, + 0x503e303e, + 0x503eb054, + 0x503f3066, + 0x503f8382, + 0x50403079, + 0x5040b089, + 0x504130a3, + 0x5041b0b2, + 0x504230cc, + 0x5042b0e9, + 0x504330f9, + 0x5043b109, + 0x50443118, + 0x5044843f, + 0x5045312c, + 0x5045b14a, + 0x5046315d, + 0x5046b173, + 0x50473185, + 0x5047b19a, + 0x504831c0, + 0x5048b1ce, + 0x504931e1, + 0x5049b1f6, + 0x504a320c, + 0x504ab21c, + 0x504b323c, + 0x504bb24f, + 0x504c3272, + 0x504cb2a0, + 0x504d32b2, + 0x504db2cf, + 0x504e32ea, + 0x504eb306, + 0x504f3318, + 0x504fb32f, + 0x5050333e, + 0x505086ef, + 0x50513351, + 0x58320f2b, + 0x68320eed, + 0x68328c6a, + 0x68330c7d, + 0x68338efb, + 0x68340f0b, + 0x683480ea, + 0x6c320ec9, + 0x6c328c34, + 0x6c330ed4, + 0x74320a19, + 0x743280ac, + 0x74330c45, + 0x7832097e, + 0x78328993, + 0x7833099f, + 0x78338083, + 0x783409ae, + 0x783489c3, + 0x783509e2, + 0x78358a04, + 0x78360a19, + 0x78368a2f, + 0x78370a3f, + 0x78378a60, + 0x78380a73, + 0x78388a85, + 0x78390a92, + 0x78398ab1, + 0x783a0ac6, + 0x783a8ad4, + 0x783b0ade, + 0x783b8af2, + 0x783c0b09, + 0x783c8b1e, + 0x783d0b35, + 0x783d8b4a, + 0x783e0aa0, + 0x783e8a52, + 0x7c321185, + }; - const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); + const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); - const char kOpenSSLReasonStringData[] = - "ASN1_LENGTH_MISMATCH\\0" - "AUX_ERROR\\0" - "BAD_GET_ASN1_OBJECT_CALL\\0" - "BAD_OBJECT_HEADER\\0" - "BMPSTRING_IS_WRONG_LENGTH\\0" - "BN_LIB\\0" - "BOOLEAN_IS_WRONG_LENGTH\\0" - "BUFFER_TOO_SMALL\\0" - "CONTEXT_NOT_INITIALISED\\0" - "DECODE_ERROR\\0" - "DEPTH_EXCEEDED\\0" - "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\\0" - "ENCODE_ERROR\\0" - "ERROR_GETTING_TIME\\0" - "EXPECTING_AN_ASN1_SEQUENCE\\0" - "EXPECTING_AN_INTEGER\\0" - "EXPECTING_AN_OBJECT\\0" - "EXPECTING_A_BOOLEAN\\0" - "EXPECTING_A_TIME\\0" - "EXPLICIT_LENGTH_MISMATCH\\0" - "EXPLICIT_TAG_NOT_CONSTRUCTED\\0" - "FIELD_MISSING\\0" - "FIRST_NUM_TOO_LARGE\\0" - "HEADER_TOO_LONG\\0" - "ILLEGAL_BITSTRING_FORMAT\\0" - "ILLEGAL_BOOLEAN\\0" - "ILLEGAL_CHARACTERS\\0" - "ILLEGAL_FORMAT\\0" - "ILLEGAL_HEX\\0" - "ILLEGAL_IMPLICIT_TAG\\0" - "ILLEGAL_INTEGER\\0" - "ILLEGAL_NESTED_TAGGING\\0" - "ILLEGAL_NULL\\0" - "ILLEGAL_NULL_VALUE\\0" - "ILLEGAL_OBJECT\\0" - "ILLEGAL_OPTIONAL_ANY\\0" - "ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE\\0" - "ILLEGAL_TAGGED_ANY\\0" - "ILLEGAL_TIME_VALUE\\0" - "INTEGER_NOT_ASCII_FORMAT\\0" - "INTEGER_TOO_LARGE_FOR_LONG\\0" - "INVALID_BIT_STRING_BITS_LEFT\\0" - "INVALID_BMPSTRING_LENGTH\\0" - "INVALID_DIGIT\\0" - "INVALID_MODIFIER\\0" - "INVALID_NUMBER\\0" - "INVALID_OBJECT_ENCODING\\0" - "INVALID_SEPARATOR\\0" - "INVALID_TIME_FORMAT\\0" - "INVALID_UNIVERSALSTRING_LENGTH\\0" - "INVALID_UTF8STRING\\0" - "LIST_ERROR\\0" - "MISSING_ASN1_EOS\\0" - "MISSING_EOC\\0" - "MISSING_SECOND_NUMBER\\0" - "MISSING_VALUE\\0" - "MSTRING_NOT_UNIVERSAL\\0" - "MSTRING_WRONG_TAG\\0" - "NESTED_ASN1_ERROR\\0" - "NESTED_ASN1_STRING\\0" - "NON_HEX_CHARACTERS\\0" - "NOT_ASCII_FORMAT\\0" - "NOT_ENOUGH_DATA\\0" - "NO_MATCHING_CHOICE_TYPE\\0" - "NULL_IS_WRONG_LENGTH\\0" - "OBJECT_NOT_ASCII_FORMAT\\0" - "ODD_NUMBER_OF_CHARS\\0" - "SECOND_NUMBER_TOO_LARGE\\0" - "SEQUENCE_LENGTH_MISMATCH\\0" - "SEQUENCE_NOT_CONSTRUCTED\\0" - "SEQUENCE_OR_SET_NEEDS_CONFIG\\0" - "SHORT_LINE\\0" - "STREAMING_NOT_SUPPORTED\\0" - "STRING_TOO_LONG\\0" - "STRING_TOO_SHORT\\0" - "TAG_VALUE_TOO_HIGH\\0" - "TIME_NOT_ASCII_FORMAT\\0" - "TOO_LONG\\0" - "TYPE_NOT_CONSTRUCTED\\0" - "TYPE_NOT_PRIMITIVE\\0" - "UNEXPECTED_EOC\\0" - "UNIVERSALSTRING_IS_WRONG_LENGTH\\0" - "UNKNOWN_FORMAT\\0" - "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\\0" - "UNKNOWN_SIGNATURE_ALGORITHM\\0" - "UNKNOWN_TAG\\0" - "UNSUPPORTED_ANY_DEFINED_BY_TYPE\\0" - "UNSUPPORTED_PUBLIC_KEY_TYPE\\0" - "UNSUPPORTED_TYPE\\0" - "WRONG_PUBLIC_KEY_TYPE\\0" - "WRONG_TAG\\0" - "WRONG_TYPE\\0" - "BAD_FOPEN_MODE\\0" - "BROKEN_PIPE\\0" - "CONNECT_ERROR\\0" - "ERROR_SETTING_NBIO\\0" - "INVALID_ARGUMENT\\0" - "IN_USE\\0" - "KEEPALIVE\\0" - "NBIO_CONNECT_ERROR\\0" - "NO_HOSTNAME_SPECIFIED\\0" - "NO_PORT_SPECIFIED\\0" - "NO_SUCH_FILE\\0" - "NULL_PARAMETER\\0" - "SYS_LIB\\0" - "UNABLE_TO_CREATE_SOCKET\\0" - "UNINITIALIZED\\0" - "UNSUPPORTED_METHOD\\0" - "WRITE_TO_READ_ONLY_BIO\\0" - "ARG2_LT_ARG3\\0" - "BAD_ENCODING\\0" - "BAD_RECIPROCAL\\0" - "BIGNUM_TOO_LONG\\0" - "BITS_TOO_SMALL\\0" - "CALLED_WITH_EVEN_MODULUS\\0" - "DIV_BY_ZERO\\0" - "EXPAND_ON_STATIC_BIGNUM_DATA\\0" - "INPUT_NOT_REDUCED\\0" - "INVALID_INPUT\\0" - "INVALID_RANGE\\0" - "NEGATIVE_NUMBER\\0" - "NOT_A_SQUARE\\0" - "NOT_INITIALIZED\\0" - "NO_INVERSE\\0" - "PRIVATE_KEY_TOO_LARGE\\0" - "P_IS_NOT_PRIME\\0" - "TOO_MANY_ITERATIONS\\0" - "TOO_MANY_TEMPORARY_VARIABLES\\0" - "AES_KEY_SETUP_FAILED\\0" - "BAD_DECRYPT\\0" - "BAD_KEY_LENGTH\\0" - "CTRL_NOT_IMPLEMENTED\\0" - "CTRL_OPERATION_NOT_IMPLEMENTED\\0" - "DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH\\0" - "INITIALIZATION_ERROR\\0" - "INPUT_NOT_INITIALIZED\\0" - "INVALID_AD_SIZE\\0" - "INVALID_KEY_LENGTH\\0" - "INVALID_NONCE\\0" - "INVALID_NONCE_SIZE\\0" - "INVALID_OPERATION\\0" - "IV_TOO_LARGE\\0" - "NO_CIPHER_SET\\0" - "NO_DIRECTION_SET\\0" - "OUTPUT_ALIASES_INPUT\\0" - "TAG_TOO_LARGE\\0" - "TOO_LARGE\\0" - "UNSUPPORTED_AD_SIZE\\0" - "UNSUPPORTED_INPUT_SIZE\\0" - "UNSUPPORTED_KEY_SIZE\\0" - "UNSUPPORTED_NONCE_SIZE\\0" - "UNSUPPORTED_TAG_SIZE\\0" - "WRONG_FINAL_BLOCK_LENGTH\\0" - "LIST_CANNOT_BE_NULL\\0" - "MISSING_CLOSE_SQUARE_BRACKET\\0" - "MISSING_EQUAL_SIGN\\0" - "NO_CLOSE_BRACE\\0" - "UNABLE_TO_CREATE_NEW_SECTION\\0" - "VARIABLE_EXPANSION_TOO_LONG\\0" - "VARIABLE_HAS_NO_VALUE\\0" - "BAD_GENERATOR\\0" - "INVALID_PUBKEY\\0" - "MODULUS_TOO_LARGE\\0" - "NO_PRIVATE_VALUE\\0" - "UNKNOWN_HASH\\0" - "BAD_Q_VALUE\\0" - "BAD_VERSION\\0" - "MISSING_PARAMETERS\\0" - "NEED_NEW_SETUP_VALUES\\0" - "BIGNUM_OUT_OF_RANGE\\0" - "COORDINATES_OUT_OF_RANGE\\0" - "D2I_ECPKPARAMETERS_FAILURE\\0" - "EC_GROUP_NEW_BY_NAME_FAILURE\\0" - "GROUP2PKPARAMETERS_FAILURE\\0" - "GROUP_MISMATCH\\0" - "I2D_ECPKPARAMETERS_FAILURE\\0" - "INCOMPATIBLE_OBJECTS\\0" - "INVALID_COFACTOR\\0" - "INVALID_COMPRESSED_POINT\\0" - "INVALID_COMPRESSION_BIT\\0" - "INVALID_ENCODING\\0" - "INVALID_FIELD\\0" - "INVALID_FORM\\0" - "INVALID_GROUP_ORDER\\0" - "INVALID_PRIVATE_KEY\\0" - "MISSING_PRIVATE_KEY\\0" - "NON_NAMED_CURVE\\0" - "PKPARAMETERS2GROUP_FAILURE\\0" - "POINT_AT_INFINITY\\0" - "POINT_IS_NOT_ON_CURVE\\0" - "PUBLIC_KEY_VALIDATION_FAILED\\0" - "SLOT_FULL\\0" - "UNDEFINED_GENERATOR\\0" - "UNKNOWN_GROUP\\0" - "UNKNOWN_ORDER\\0" - "WRONG_CURVE_PARAMETERS\\0" - "WRONG_ORDER\\0" - "KDF_FAILED\\0" - "POINT_ARITHMETIC_FAILURE\\0" - "BAD_SIGNATURE\\0" - "NOT_IMPLEMENTED\\0" - "RANDOM_NUMBER_GENERATION_FAILED\\0" - "OPERATION_NOT_SUPPORTED\\0" - "COMMAND_NOT_SUPPORTED\\0" - "DIFFERENT_KEY_TYPES\\0" - "DIFFERENT_PARAMETERS\\0" - "EXPECTING_AN_EC_KEY_KEY\\0" - "EXPECTING_AN_RSA_KEY\\0" - "EXPECTING_A_DSA_KEY\\0" - "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\\0" - "INVALID_DIGEST_LENGTH\\0" - "INVALID_DIGEST_TYPE\\0" - "INVALID_KEYBITS\\0" - "INVALID_MGF1_MD\\0" - "INVALID_PADDING_MODE\\0" - "INVALID_PARAMETERS\\0" - "INVALID_PSS_SALTLEN\\0" - "INVALID_SIGNATURE\\0" - "KEYS_NOT_SET\\0" - "MEMORY_LIMIT_EXCEEDED\\0" - "NOT_A_PRIVATE_KEY\\0" - "NO_DEFAULT_DIGEST\\0" - "NO_KEY_SET\\0" - "NO_MDC2_SUPPORT\\0" - "NO_NID_FOR_CURVE\\0" - "NO_OPERATION_SET\\0" - "NO_PARAMETERS_SET\\0" - "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\\0" - "OPERATON_NOT_INITIALIZED\\0" - "UNKNOWN_PUBLIC_KEY_TYPE\\0" - "UNSUPPORTED_ALGORITHM\\0" - "OUTPUT_TOO_LARGE\\0" - "UNKNOWN_NID\\0" - "BAD_BASE64_DECODE\\0" - "BAD_END_LINE\\0" - "BAD_IV_CHARS\\0" - "BAD_PASSWORD_READ\\0" - "CIPHER_IS_NULL\\0" - "ERROR_CONVERTING_PRIVATE_KEY\\0" - "NOT_DEK_INFO\\0" - "NOT_ENCRYPTED\\0" - "NOT_PROC_TYPE\\0" - "NO_START_LINE\\0" - "READ_KEY\\0" - "SHORT_HEADER\\0" - "UNSUPPORTED_CIPHER\\0" - "UNSUPPORTED_ENCRYPTION\\0" - "BAD_PKCS7_VERSION\\0" - "NOT_PKCS7_SIGNED_DATA\\0" - "NO_CERTIFICATES_INCLUDED\\0" - "NO_CRLS_INCLUDED\\0" - "BAD_ITERATION_COUNT\\0" - "BAD_PKCS12_DATA\\0" - "BAD_PKCS12_VERSION\\0" - "CIPHER_HAS_NO_OBJECT_IDENTIFIER\\0" - "CRYPT_ERROR\\0" - "ENCRYPT_ERROR\\0" - "ERROR_SETTING_CIPHER_PARAMS\\0" - "INCORRECT_PASSWORD\\0" - "KEYGEN_FAILURE\\0" - "KEY_GEN_ERROR\\0" - "METHOD_NOT_SUPPORTED\\0" - "MISSING_MAC\\0" - "MULTIPLE_PRIVATE_KEYS_IN_PKCS12\\0" - "PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED\\0" - "PKCS12_TOO_DEEPLY_NESTED\\0" - "PRIVATE_KEY_DECODE_ERROR\\0" - "PRIVATE_KEY_ENCODE_ERROR\\0" - "UNKNOWN_ALGORITHM\\0" - "UNKNOWN_CIPHER\\0" - "UNKNOWN_CIPHER_ALGORITHM\\0" - "UNKNOWN_DIGEST\\0" - "UNSUPPORTED_KEYLENGTH\\0" - "UNSUPPORTED_KEY_DERIVATION_FUNCTION\\0" - "UNSUPPORTED_PRF\\0" - "UNSUPPORTED_PRIVATE_KEY_ALGORITHM\\0" - "UNSUPPORTED_SALT_TYPE\\0" - "BAD_E_VALUE\\0" - "BAD_FIXED_HEADER_DECRYPT\\0" - "BAD_PAD_BYTE_COUNT\\0" - "BAD_RSA_PARAMETERS\\0" - "BLOCK_TYPE_IS_NOT_01\\0" - "BN_NOT_INITIALIZED\\0" - "CANNOT_RECOVER_MULTI_PRIME_KEY\\0" - "CRT_PARAMS_ALREADY_GIVEN\\0" - "CRT_VALUES_INCORRECT\\0" - "DATA_LEN_NOT_EQUAL_TO_MOD_LEN\\0" - "DATA_TOO_LARGE\\0" - "DATA_TOO_LARGE_FOR_KEY_SIZE\\0" - "DATA_TOO_LARGE_FOR_MODULUS\\0" - "DATA_TOO_SMALL\\0" - "DATA_TOO_SMALL_FOR_KEY_SIZE\\0" - "DIGEST_TOO_BIG_FOR_RSA_KEY\\0" - "D_E_NOT_CONGRUENT_TO_1\\0" - "EMPTY_PUBLIC_KEY\\0" - "FIRST_OCTET_INVALID\\0" - "INCONSISTENT_SET_OF_CRT_VALUES\\0" - "INTERNAL_ERROR\\0" - "INVALID_MESSAGE_LENGTH\\0" - "KEY_SIZE_TOO_SMALL\\0" - "LAST_OCTET_INVALID\\0" - "MUST_HAVE_AT_LEAST_TWO_PRIMES\\0" - "NO_PUBLIC_EXPONENT\\0" - "NULL_BEFORE_BLOCK_MISSING\\0" - "N_NOT_EQUAL_P_Q\\0" - "OAEP_DECODING_ERROR\\0" - "ONLY_ONE_OF_P_Q_GIVEN\\0" - "OUTPUT_BUFFER_TOO_SMALL\\0" - "PADDING_CHECK_FAILED\\0" - "PKCS_DECODING_ERROR\\0" - "SLEN_CHECK_FAILED\\0" - "SLEN_RECOVERY_FAILED\\0" - "UNKNOWN_ALGORITHM_TYPE\\0" - "UNKNOWN_PADDING_TYPE\\0" - "VALUE_MISSING\\0" - "WRONG_SIGNATURE_LENGTH\\0" - "ALPN_MISMATCH_ON_EARLY_DATA\\0" - "APPLICATION_DATA_INSTEAD_OF_HANDSHAKE\\0" - "APP_DATA_IN_HANDSHAKE\\0" - "ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT\\0" - "BAD_ALERT\\0" - "BAD_CHANGE_CIPHER_SPEC\\0" - "BAD_DATA_RETURNED_BY_CALLBACK\\0" - "BAD_DH_P_LENGTH\\0" - "BAD_DIGEST_LENGTH\\0" - "BAD_ECC_CERT\\0" - "BAD_ECPOINT\\0" - "BAD_HANDSHAKE_RECORD\\0" - "BAD_HELLO_REQUEST\\0" - "BAD_LENGTH\\0" - "BAD_PACKET_LENGTH\\0" - "BAD_RSA_ENCRYPT\\0" - "BAD_SRTP_MKI_VALUE\\0" - "BAD_SRTP_PROTECTION_PROFILE_LIST\\0" - "BAD_SSL_FILETYPE\\0" - "BAD_WRITE_RETRY\\0" - "BIO_NOT_SET\\0" - "BLOCK_CIPHER_PAD_IS_WRONG\\0" - "BUFFERED_MESSAGES_ON_CIPHER_CHANGE\\0" - "CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD\\0" - "CANNOT_PARSE_LEAF_CERT\\0" - "CA_DN_LENGTH_MISMATCH\\0" - "CA_DN_TOO_LONG\\0" - "CCS_RECEIVED_EARLY\\0" - "CERTIFICATE_AND_PRIVATE_KEY_MISMATCH\\0" - "CERTIFICATE_VERIFY_FAILED\\0" - "CERT_CB_ERROR\\0" - "CERT_LENGTH_MISMATCH\\0" - "CHANNEL_ID_NOT_P256\\0" - "CHANNEL_ID_SIGNATURE_INVALID\\0" - "CIPHER_OR_HASH_UNAVAILABLE\\0" - "CLIENTHELLO_PARSE_FAILED\\0" - "CLIENTHELLO_TLSEXT\\0" - "CONNECTION_REJECTED\\0" - "CONNECTION_TYPE_NOT_SET\\0" - "CUSTOM_EXTENSION_ERROR\\0" - "DATA_LENGTH_TOO_LONG\\0" - "DECRYPTION_FAILED\\0" - "DECRYPTION_FAILED_OR_BAD_RECORD_MAC\\0" - "DH_PUBLIC_VALUE_LENGTH_IS_WRONG\\0" - "DH_P_TOO_LONG\\0" - "DIGEST_CHECK_FAILED\\0" - "DOWNGRADE_DETECTED\\0" - "DTLS_MESSAGE_TOO_BIG\\0" - "DUPLICATE_EXTENSION\\0" - "DUPLICATE_KEY_SHARE\\0" - "ECC_CERT_NOT_FOR_SIGNING\\0" - "EMS_STATE_INCONSISTENT\\0" - "ENCRYPTED_LENGTH_TOO_LONG\\0" - "ERROR_ADDING_EXTENSION\\0" - "ERROR_IN_RECEIVED_CIPHER_LIST\\0" - "ERROR_PARSING_EXTENSION\\0" - "EXCESSIVE_MESSAGE_SIZE\\0" - "EXTRA_DATA_IN_MESSAGE\\0" - "FRAGMENT_MISMATCH\\0" - "GOT_NEXT_PROTO_WITHOUT_EXTENSION\\0" - "HANDSHAKE_FAILURE_ON_CLIENT_HELLO\\0" - "HTTPS_PROXY_REQUEST\\0" - "HTTP_REQUEST\\0" - "INAPPROPRIATE_FALLBACK\\0" - "INVALID_ALPN_PROTOCOL\\0" - "INVALID_COMMAND\\0" - "INVALID_COMPRESSION_LIST\\0" - "INVALID_MESSAGE\\0" - "INVALID_OUTER_RECORD_TYPE\\0" - "INVALID_SCT_LIST\\0" - "INVALID_SSL_SESSION\\0" - "INVALID_TICKET_KEYS_LENGTH\\0" - "LENGTH_MISMATCH\\0" - "MISSING_EXTENSION\\0" - "MISSING_KEY_SHARE\\0" - "MISSING_RSA_CERTIFICATE\\0" - "MISSING_TMP_DH_KEY\\0" - "MISSING_TMP_ECDH_KEY\\0" - "MIXED_SPECIAL_OPERATOR_WITH_GROUPS\\0" - "MTU_TOO_SMALL\\0" - "NEGOTIATED_BOTH_NPN_AND_ALPN\\0" - "NESTED_GROUP\\0" - "NO_CERTIFICATES_RETURNED\\0" - "NO_CERTIFICATE_ASSIGNED\\0" - "NO_CERTIFICATE_SET\\0" - "NO_CIPHERS_AVAILABLE\\0" - "NO_CIPHERS_PASSED\\0" - "NO_CIPHERS_SPECIFIED\\0" - "NO_CIPHER_MATCH\\0" - "NO_COMMON_SIGNATURE_ALGORITHMS\\0" - "NO_COMPRESSION_SPECIFIED\\0" - "NO_GROUPS_SPECIFIED\\0" - "NO_METHOD_SPECIFIED\\0" - "NO_P256_SUPPORT\\0" - "NO_PRIVATE_KEY_ASSIGNED\\0" - "NO_RENEGOTIATION\\0" - "NO_REQUIRED_DIGEST\\0" - "NO_SHARED_CIPHER\\0" - "NO_SHARED_GROUP\\0" - "NO_SUPPORTED_VERSIONS_ENABLED\\0" - "NULL_SSL_CTX\\0" - "NULL_SSL_METHOD_PASSED\\0" - "OLD_SESSION_CIPHER_NOT_RETURNED\\0" - "OLD_SESSION_PRF_HASH_MISMATCH\\0" - "OLD_SESSION_VERSION_NOT_RETURNED\\0" - "PARSE_TLSEXT\\0" - "PATH_TOO_LONG\\0" - "PEER_DID_NOT_RETURN_A_CERTIFICATE\\0" - "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\\0" - "PRE_SHARED_KEY_MUST_BE_LAST\\0" - "PROTOCOL_IS_SHUTDOWN\\0" - "PSK_IDENTITY_BINDER_COUNT_MISMATCH\\0" - "PSK_IDENTITY_NOT_FOUND\\0" - "PSK_NO_CLIENT_CB\\0" - "PSK_NO_SERVER_CB\\0" - "READ_TIMEOUT_EXPIRED\\0" - "RECORD_LENGTH_MISMATCH\\0" - "RECORD_TOO_LARGE\\0" - "RENEGOTIATION_EMS_MISMATCH\\0" - "RENEGOTIATION_ENCODING_ERR\\0" - "RENEGOTIATION_MISMATCH\\0" - "REQUIRED_CIPHER_MISSING\\0" - "RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION\\0" - "RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION\\0" - "SCSV_RECEIVED_WHEN_RENEGOTIATING\\0" - "SERVERHELLO_TLSEXT\\0" - "SERVER_CERT_CHANGED\\0" - "SESSION_ID_CONTEXT_UNINITIALIZED\\0" - "SESSION_MAY_NOT_BE_CREATED\\0" - "SHUTDOWN_WHILE_IN_INIT\\0" - "SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER\\0" - "SRTP_COULD_NOT_ALLOCATE_PROFILES\\0" - "SRTP_UNKNOWN_PROTECTION_PROFILE\\0" - "SSL3_EXT_INVALID_SERVERNAME\\0" - "SSLV3_ALERT_BAD_CERTIFICATE\\0" - "SSLV3_ALERT_BAD_RECORD_MAC\\0" - "SSLV3_ALERT_CERTIFICATE_EXPIRED\\0" - "SSLV3_ALERT_CERTIFICATE_REVOKED\\0" - "SSLV3_ALERT_CERTIFICATE_UNKNOWN\\0" - "SSLV3_ALERT_CLOSE_NOTIFY\\0" - "SSLV3_ALERT_DECOMPRESSION_FAILURE\\0" - "SSLV3_ALERT_HANDSHAKE_FAILURE\\0" - "SSLV3_ALERT_ILLEGAL_PARAMETER\\0" - "SSLV3_ALERT_NO_CERTIFICATE\\0" - "SSLV3_ALERT_UNEXPECTED_MESSAGE\\0" - "SSLV3_ALERT_UNSUPPORTED_CERTIFICATE\\0" - "SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION\\0" - "SSL_HANDSHAKE_FAILURE\\0" - "SSL_SESSION_ID_CONTEXT_TOO_LONG\\0" - "TICKET_ENCRYPTION_FAILED\\0" - "TLSV1_ALERT_ACCESS_DENIED\\0" - "TLSV1_ALERT_DECODE_ERROR\\0" - "TLSV1_ALERT_DECRYPTION_FAILED\\0" - "TLSV1_ALERT_DECRYPT_ERROR\\0" - "TLSV1_ALERT_EXPORT_RESTRICTION\\0" - "TLSV1_ALERT_INAPPROPRIATE_FALLBACK\\0" - "TLSV1_ALERT_INSUFFICIENT_SECURITY\\0" - "TLSV1_ALERT_INTERNAL_ERROR\\0" - "TLSV1_ALERT_NO_RENEGOTIATION\\0" - "TLSV1_ALERT_PROTOCOL_VERSION\\0" - "TLSV1_ALERT_RECORD_OVERFLOW\\0" - "TLSV1_ALERT_UNKNOWN_CA\\0" - "TLSV1_ALERT_USER_CANCELLED\\0" - "TLSV1_BAD_CERTIFICATE_HASH_VALUE\\0" - "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\\0" - "TLSV1_CERTIFICATE_REQUIRED\\0" - "TLSV1_CERTIFICATE_UNOBTAINABLE\\0" - "TLSV1_UNKNOWN_PSK_IDENTITY\\0" - "TLSV1_UNRECOGNIZED_NAME\\0" - "TLSV1_UNSUPPORTED_EXTENSION\\0" - "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\\0" - "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG\\0" - "TOO_MANY_EMPTY_FRAGMENTS\\0" - "TOO_MANY_KEY_UPDATES\\0" - "TOO_MANY_WARNING_ALERTS\\0" - "TOO_MUCH_READ_EARLY_DATA\\0" - "TOO_MUCH_SKIPPED_EARLY_DATA\\0" - "UNABLE_TO_FIND_ECDH_PARAMETERS\\0" - "UNEXPECTED_EXTENSION\\0" - "UNEXPECTED_EXTENSION_ON_EARLY_DATA\\0" - "UNEXPECTED_MESSAGE\\0" - "UNEXPECTED_OPERATOR_IN_GROUP\\0" - "UNEXPECTED_RECORD\\0" - "UNKNOWN_ALERT_TYPE\\0" - "UNKNOWN_CERTIFICATE_TYPE\\0" - "UNKNOWN_CIPHER_RETURNED\\0" - "UNKNOWN_CIPHER_TYPE\\0" - "UNKNOWN_KEY_EXCHANGE_TYPE\\0" - "UNKNOWN_PROTOCOL\\0" - "UNKNOWN_SSL_VERSION\\0" - "UNKNOWN_STATE\\0" - "UNSAFE_LEGACY_RENEGOTIATION_DISABLED\\0" - "UNSUPPORTED_COMPRESSION_ALGORITHM\\0" - "UNSUPPORTED_ELLIPTIC_CURVE\\0" - "UNSUPPORTED_PROTOCOL\\0" - "UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY\\0" - "WRONG_CERTIFICATE_TYPE\\0" - "WRONG_CIPHER_RETURNED\\0" - "WRONG_CURVE\\0" - "WRONG_MESSAGE_TYPE\\0" - "WRONG_SIGNATURE_TYPE\\0" - "WRONG_SSL_VERSION\\0" - "WRONG_VERSION_NUMBER\\0" - "WRONG_VERSION_ON_EARLY_DATA\\0" - "X509_LIB\\0" - "X509_VERIFICATION_SETUP_PROBLEMS\\0" - "AKID_MISMATCH\\0" - "BAD_X509_FILETYPE\\0" - "BASE64_DECODE_ERROR\\0" - "CANT_CHECK_DH_KEY\\0" - "CERT_ALREADY_IN_HASH_TABLE\\0" - "CRL_ALREADY_DELTA\\0" - "CRL_VERIFY_FAILURE\\0" - "IDP_MISMATCH\\0" - "INVALID_DIRECTORY\\0" - "INVALID_FIELD_NAME\\0" - "INVALID_PARAMETER\\0" - "INVALID_PSS_PARAMETERS\\0" - "INVALID_TRUST\\0" - "ISSUER_MISMATCH\\0" - "KEY_TYPE_MISMATCH\\0" - "KEY_VALUES_MISMATCH\\0" - "LOADING_CERT_DIR\\0" - "LOADING_DEFAULTS\\0" - "NAME_TOO_LONG\\0" - "NEWER_CRL_NOT_NEWER\\0" - "NO_CERT_SET_FOR_US_TO_VERIFY\\0" - "NO_CRL_NUMBER\\0" - "PUBLIC_KEY_DECODE_ERROR\\0" - "PUBLIC_KEY_ENCODE_ERROR\\0" - "SHOULD_RETRY\\0" - "UNKNOWN_KEY_TYPE\\0" - "UNKNOWN_PURPOSE_ID\\0" - "UNKNOWN_TRUST_ID\\0" - "WRONG_LOOKUP_TYPE\\0" - "BAD_IP_ADDRESS\\0" - "BAD_OBJECT\\0" - "BN_DEC2BN_ERROR\\0" - "BN_TO_ASN1_INTEGER_ERROR\\0" - "CANNOT_FIND_FREE_FUNCTION\\0" - "DIRNAME_ERROR\\0" - "DISTPOINT_ALREADY_SET\\0" - "DUPLICATE_ZONE_ID\\0" - "ERROR_CONVERTING_ZONE\\0" - "ERROR_CREATING_EXTENSION\\0" - "ERROR_IN_EXTENSION\\0" - "EXPECTED_A_SECTION_NAME\\0" - "EXTENSION_EXISTS\\0" - "EXTENSION_NAME_ERROR\\0" - "EXTENSION_NOT_FOUND\\0" - "EXTENSION_SETTING_NOT_SUPPORTED\\0" - "EXTENSION_VALUE_ERROR\\0" - "ILLEGAL_EMPTY_EXTENSION\\0" - "ILLEGAL_HEX_DIGIT\\0" - "INCORRECT_POLICY_SYNTAX_TAG\\0" - "INVALID_BOOLEAN_STRING\\0" - "INVALID_EXTENSION_STRING\\0" - "INVALID_MULTIPLE_RDNS\\0" - "INVALID_NAME\\0" - "INVALID_NULL_ARGUMENT\\0" - "INVALID_NULL_NAME\\0" - "INVALID_NULL_VALUE\\0" - "INVALID_NUMBERS\\0" - "INVALID_OBJECT_IDENTIFIER\\0" - "INVALID_OPTION\\0" - "INVALID_POLICY_IDENTIFIER\\0" - "INVALID_PROXY_POLICY_SETTING\\0" - "INVALID_PURPOSE\\0" - "INVALID_SECTION\\0" - "INVALID_SYNTAX\\0" - "ISSUER_DECODE_ERROR\\0" - "NEED_ORGANIZATION_AND_NUMBERS\\0" - "NO_CONFIG_DATABASE\\0" - "NO_ISSUER_CERTIFICATE\\0" - "NO_ISSUER_DETAILS\\0" - "NO_POLICY_IDENTIFIER\\0" - "NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED\\0" - "NO_PUBLIC_KEY\\0" - "NO_SUBJECT_DETAILS\\0" - "ODD_NUMBER_OF_DIGITS\\0" - "OPERATION_NOT_DEFINED\\0" - "OTHERNAME_ERROR\\0" - "POLICY_LANGUAGE_ALREADY_DEFINED\\0" - "POLICY_PATH_LENGTH\\0" - "POLICY_PATH_LENGTH_ALREADY_DEFINED\\0" - "POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY\\0" - "SECTION_NOT_FOUND\\0" - "UNABLE_TO_GET_ISSUER_DETAILS\\0" - "UNABLE_TO_GET_ISSUER_KEYID\\0" - "UNKNOWN_BIT_STRING_ARGUMENT\\0" - "UNKNOWN_EXTENSION\\0" - "UNKNOWN_EXTENSION_NAME\\0" - "UNKNOWN_OPTION\\0" - "UNSUPPORTED_OPTION\\0" - "USER_TOO_LONG\\0" - ""; - EOF + const char kOpenSSLReasonStringData[] = + "ASN1_LENGTH_MISMATCH\\0" + "AUX_ERROR\\0" + "BAD_GET_ASN1_OBJECT_CALL\\0" + "BAD_OBJECT_HEADER\\0" + "BMPSTRING_IS_WRONG_LENGTH\\0" + "BN_LIB\\0" + "BOOLEAN_IS_WRONG_LENGTH\\0" + "BUFFER_TOO_SMALL\\0" + "CONTEXT_NOT_INITIALISED\\0" + "DECODE_ERROR\\0" + "DEPTH_EXCEEDED\\0" + "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\\0" + "ENCODE_ERROR\\0" + "ERROR_GETTING_TIME\\0" + "EXPECTING_AN_ASN1_SEQUENCE\\0" + "EXPECTING_AN_INTEGER\\0" + "EXPECTING_AN_OBJECT\\0" + "EXPECTING_A_BOOLEAN\\0" + "EXPECTING_A_TIME\\0" + "EXPLICIT_LENGTH_MISMATCH\\0" + "EXPLICIT_TAG_NOT_CONSTRUCTED\\0" + "FIELD_MISSING\\0" + "FIRST_NUM_TOO_LARGE\\0" + "HEADER_TOO_LONG\\0" + "ILLEGAL_BITSTRING_FORMAT\\0" + "ILLEGAL_BOOLEAN\\0" + "ILLEGAL_CHARACTERS\\0" + "ILLEGAL_FORMAT\\0" + "ILLEGAL_HEX\\0" + "ILLEGAL_IMPLICIT_TAG\\0" + "ILLEGAL_INTEGER\\0" + "ILLEGAL_NESTED_TAGGING\\0" + "ILLEGAL_NULL\\0" + "ILLEGAL_NULL_VALUE\\0" + "ILLEGAL_OBJECT\\0" + "ILLEGAL_OPTIONAL_ANY\\0" + "ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE\\0" + "ILLEGAL_TAGGED_ANY\\0" + "ILLEGAL_TIME_VALUE\\0" + "INTEGER_NOT_ASCII_FORMAT\\0" + "INTEGER_TOO_LARGE_FOR_LONG\\0" + "INVALID_BIT_STRING_BITS_LEFT\\0" + "INVALID_BMPSTRING_LENGTH\\0" + "INVALID_DIGIT\\0" + "INVALID_MODIFIER\\0" + "INVALID_NUMBER\\0" + "INVALID_OBJECT_ENCODING\\0" + "INVALID_SEPARATOR\\0" + "INVALID_TIME_FORMAT\\0" + "INVALID_UNIVERSALSTRING_LENGTH\\0" + "INVALID_UTF8STRING\\0" + "LIST_ERROR\\0" + "MISSING_ASN1_EOS\\0" + "MISSING_EOC\\0" + "MISSING_SECOND_NUMBER\\0" + "MISSING_VALUE\\0" + "MSTRING_NOT_UNIVERSAL\\0" + "MSTRING_WRONG_TAG\\0" + "NESTED_ASN1_ERROR\\0" + "NESTED_ASN1_STRING\\0" + "NON_HEX_CHARACTERS\\0" + "NOT_ASCII_FORMAT\\0" + "NOT_ENOUGH_DATA\\0" + "NO_MATCHING_CHOICE_TYPE\\0" + "NULL_IS_WRONG_LENGTH\\0" + "OBJECT_NOT_ASCII_FORMAT\\0" + "ODD_NUMBER_OF_CHARS\\0" + "SECOND_NUMBER_TOO_LARGE\\0" + "SEQUENCE_LENGTH_MISMATCH\\0" + "SEQUENCE_NOT_CONSTRUCTED\\0" + "SEQUENCE_OR_SET_NEEDS_CONFIG\\0" + "SHORT_LINE\\0" + "STREAMING_NOT_SUPPORTED\\0" + "STRING_TOO_LONG\\0" + "STRING_TOO_SHORT\\0" + "TAG_VALUE_TOO_HIGH\\0" + "TIME_NOT_ASCII_FORMAT\\0" + "TOO_LONG\\0" + "TYPE_NOT_CONSTRUCTED\\0" + "TYPE_NOT_PRIMITIVE\\0" + "UNEXPECTED_EOC\\0" + "UNIVERSALSTRING_IS_WRONG_LENGTH\\0" + "UNKNOWN_FORMAT\\0" + "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\\0" + "UNKNOWN_SIGNATURE_ALGORITHM\\0" + "UNKNOWN_TAG\\0" + "UNSUPPORTED_ANY_DEFINED_BY_TYPE\\0" + "UNSUPPORTED_PUBLIC_KEY_TYPE\\0" + "UNSUPPORTED_TYPE\\0" + "WRONG_PUBLIC_KEY_TYPE\\0" + "WRONG_TAG\\0" + "WRONG_TYPE\\0" + "BAD_FOPEN_MODE\\0" + "BROKEN_PIPE\\0" + "CONNECT_ERROR\\0" + "ERROR_SETTING_NBIO\\0" + "INVALID_ARGUMENT\\0" + "IN_USE\\0" + "KEEPALIVE\\0" + "NBIO_CONNECT_ERROR\\0" + "NO_HOSTNAME_SPECIFIED\\0" + "NO_PORT_SPECIFIED\\0" + "NO_SUCH_FILE\\0" + "NULL_PARAMETER\\0" + "SYS_LIB\\0" + "UNABLE_TO_CREATE_SOCKET\\0" + "UNINITIALIZED\\0" + "UNSUPPORTED_METHOD\\0" + "WRITE_TO_READ_ONLY_BIO\\0" + "ARG2_LT_ARG3\\0" + "BAD_ENCODING\\0" + "BAD_RECIPROCAL\\0" + "BIGNUM_TOO_LONG\\0" + "BITS_TOO_SMALL\\0" + "CALLED_WITH_EVEN_MODULUS\\0" + "DIV_BY_ZERO\\0" + "EXPAND_ON_STATIC_BIGNUM_DATA\\0" + "INPUT_NOT_REDUCED\\0" + "INVALID_INPUT\\0" + "INVALID_RANGE\\0" + "NEGATIVE_NUMBER\\0" + "NOT_A_SQUARE\\0" + "NOT_INITIALIZED\\0" + "NO_INVERSE\\0" + "PRIVATE_KEY_TOO_LARGE\\0" + "P_IS_NOT_PRIME\\0" + "TOO_MANY_ITERATIONS\\0" + "TOO_MANY_TEMPORARY_VARIABLES\\0" + "AES_KEY_SETUP_FAILED\\0" + "BAD_DECRYPT\\0" + "BAD_KEY_LENGTH\\0" + "CTRL_NOT_IMPLEMENTED\\0" + "CTRL_OPERATION_NOT_IMPLEMENTED\\0" + "DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH\\0" + "INITIALIZATION_ERROR\\0" + "INPUT_NOT_INITIALIZED\\0" + "INVALID_AD_SIZE\\0" + "INVALID_KEY_LENGTH\\0" + "INVALID_NONCE\\0" + "INVALID_NONCE_SIZE\\0" + "INVALID_OPERATION\\0" + "IV_TOO_LARGE\\0" + "NO_CIPHER_SET\\0" + "NO_DIRECTION_SET\\0" + "OUTPUT_ALIASES_INPUT\\0" + "TAG_TOO_LARGE\\0" + "TOO_LARGE\\0" + "UNSUPPORTED_AD_SIZE\\0" + "UNSUPPORTED_INPUT_SIZE\\0" + "UNSUPPORTED_KEY_SIZE\\0" + "UNSUPPORTED_NONCE_SIZE\\0" + "UNSUPPORTED_TAG_SIZE\\0" + "WRONG_FINAL_BLOCK_LENGTH\\0" + "LIST_CANNOT_BE_NULL\\0" + "MISSING_CLOSE_SQUARE_BRACKET\\0" + "MISSING_EQUAL_SIGN\\0" + "NO_CLOSE_BRACE\\0" + "UNABLE_TO_CREATE_NEW_SECTION\\0" + "VARIABLE_EXPANSION_TOO_LONG\\0" + "VARIABLE_HAS_NO_VALUE\\0" + "BAD_GENERATOR\\0" + "INVALID_PUBKEY\\0" + "MODULUS_TOO_LARGE\\0" + "NO_PRIVATE_VALUE\\0" + "UNKNOWN_HASH\\0" + "BAD_Q_VALUE\\0" + "BAD_VERSION\\0" + "MISSING_PARAMETERS\\0" + "NEED_NEW_SETUP_VALUES\\0" + "BIGNUM_OUT_OF_RANGE\\0" + "COORDINATES_OUT_OF_RANGE\\0" + "D2I_ECPKPARAMETERS_FAILURE\\0" + "EC_GROUP_NEW_BY_NAME_FAILURE\\0" + "GROUP2PKPARAMETERS_FAILURE\\0" + "GROUP_MISMATCH\\0" + "I2D_ECPKPARAMETERS_FAILURE\\0" + "INCOMPATIBLE_OBJECTS\\0" + "INVALID_COFACTOR\\0" + "INVALID_COMPRESSED_POINT\\0" + "INVALID_COMPRESSION_BIT\\0" + "INVALID_ENCODING\\0" + "INVALID_FIELD\\0" + "INVALID_FORM\\0" + "INVALID_GROUP_ORDER\\0" + "INVALID_PRIVATE_KEY\\0" + "MISSING_PRIVATE_KEY\\0" + "NON_NAMED_CURVE\\0" + "PKPARAMETERS2GROUP_FAILURE\\0" + "POINT_AT_INFINITY\\0" + "POINT_IS_NOT_ON_CURVE\\0" + "PUBLIC_KEY_VALIDATION_FAILED\\0" + "SLOT_FULL\\0" + "UNDEFINED_GENERATOR\\0" + "UNKNOWN_GROUP\\0" + "UNKNOWN_ORDER\\0" + "WRONG_CURVE_PARAMETERS\\0" + "WRONG_ORDER\\0" + "KDF_FAILED\\0" + "POINT_ARITHMETIC_FAILURE\\0" + "BAD_SIGNATURE\\0" + "NOT_IMPLEMENTED\\0" + "RANDOM_NUMBER_GENERATION_FAILED\\0" + "OPERATION_NOT_SUPPORTED\\0" + "COMMAND_NOT_SUPPORTED\\0" + "DIFFERENT_KEY_TYPES\\0" + "DIFFERENT_PARAMETERS\\0" + "EXPECTING_AN_EC_KEY_KEY\\0" + "EXPECTING_AN_RSA_KEY\\0" + "EXPECTING_A_DSA_KEY\\0" + "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\\0" + "INVALID_DIGEST_LENGTH\\0" + "INVALID_DIGEST_TYPE\\0" + "INVALID_KEYBITS\\0" + "INVALID_MGF1_MD\\0" + "INVALID_PADDING_MODE\\0" + "INVALID_PARAMETERS\\0" + "INVALID_PSS_SALTLEN\\0" + "INVALID_SIGNATURE\\0" + "KEYS_NOT_SET\\0" + "MEMORY_LIMIT_EXCEEDED\\0" + "NOT_A_PRIVATE_KEY\\0" + "NO_DEFAULT_DIGEST\\0" + "NO_KEY_SET\\0" + "NO_MDC2_SUPPORT\\0" + "NO_NID_FOR_CURVE\\0" + "NO_OPERATION_SET\\0" + "NO_PARAMETERS_SET\\0" + "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\\0" + "OPERATON_NOT_INITIALIZED\\0" + "UNKNOWN_PUBLIC_KEY_TYPE\\0" + "UNSUPPORTED_ALGORITHM\\0" + "OUTPUT_TOO_LARGE\\0" + "UNKNOWN_NID\\0" + "BAD_BASE64_DECODE\\0" + "BAD_END_LINE\\0" + "BAD_IV_CHARS\\0" + "BAD_PASSWORD_READ\\0" + "CIPHER_IS_NULL\\0" + "ERROR_CONVERTING_PRIVATE_KEY\\0" + "NOT_DEK_INFO\\0" + "NOT_ENCRYPTED\\0" + "NOT_PROC_TYPE\\0" + "NO_START_LINE\\0" + "READ_KEY\\0" + "SHORT_HEADER\\0" + "UNSUPPORTED_CIPHER\\0" + "UNSUPPORTED_ENCRYPTION\\0" + "BAD_PKCS7_VERSION\\0" + "NOT_PKCS7_SIGNED_DATA\\0" + "NO_CERTIFICATES_INCLUDED\\0" + "NO_CRLS_INCLUDED\\0" + "BAD_ITERATION_COUNT\\0" + "BAD_PKCS12_DATA\\0" + "BAD_PKCS12_VERSION\\0" + "CIPHER_HAS_NO_OBJECT_IDENTIFIER\\0" + "CRYPT_ERROR\\0" + "ENCRYPT_ERROR\\0" + "ERROR_SETTING_CIPHER_PARAMS\\0" + "INCORRECT_PASSWORD\\0" + "KEYGEN_FAILURE\\0" + "KEY_GEN_ERROR\\0" + "METHOD_NOT_SUPPORTED\\0" + "MISSING_MAC\\0" + "MULTIPLE_PRIVATE_KEYS_IN_PKCS12\\0" + "PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED\\0" + "PKCS12_TOO_DEEPLY_NESTED\\0" + "PRIVATE_KEY_DECODE_ERROR\\0" + "PRIVATE_KEY_ENCODE_ERROR\\0" + "UNKNOWN_ALGORITHM\\0" + "UNKNOWN_CIPHER\\0" + "UNKNOWN_CIPHER_ALGORITHM\\0" + "UNKNOWN_DIGEST\\0" + "UNSUPPORTED_KEYLENGTH\\0" + "UNSUPPORTED_KEY_DERIVATION_FUNCTION\\0" + "UNSUPPORTED_PRF\\0" + "UNSUPPORTED_PRIVATE_KEY_ALGORITHM\\0" + "UNSUPPORTED_SALT_TYPE\\0" + "BAD_E_VALUE\\0" + "BAD_FIXED_HEADER_DECRYPT\\0" + "BAD_PAD_BYTE_COUNT\\0" + "BAD_RSA_PARAMETERS\\0" + "BLOCK_TYPE_IS_NOT_01\\0" + "BN_NOT_INITIALIZED\\0" + "CANNOT_RECOVER_MULTI_PRIME_KEY\\0" + "CRT_PARAMS_ALREADY_GIVEN\\0" + "CRT_VALUES_INCORRECT\\0" + "DATA_LEN_NOT_EQUAL_TO_MOD_LEN\\0" + "DATA_TOO_LARGE\\0" + "DATA_TOO_LARGE_FOR_KEY_SIZE\\0" + "DATA_TOO_LARGE_FOR_MODULUS\\0" + "DATA_TOO_SMALL\\0" + "DATA_TOO_SMALL_FOR_KEY_SIZE\\0" + "DIGEST_TOO_BIG_FOR_RSA_KEY\\0" + "D_E_NOT_CONGRUENT_TO_1\\0" + "EMPTY_PUBLIC_KEY\\0" + "FIRST_OCTET_INVALID\\0" + "INCONSISTENT_SET_OF_CRT_VALUES\\0" + "INTERNAL_ERROR\\0" + "INVALID_MESSAGE_LENGTH\\0" + "KEY_SIZE_TOO_SMALL\\0" + "LAST_OCTET_INVALID\\0" + "MUST_HAVE_AT_LEAST_TWO_PRIMES\\0" + "NO_PUBLIC_EXPONENT\\0" + "NULL_BEFORE_BLOCK_MISSING\\0" + "N_NOT_EQUAL_P_Q\\0" + "OAEP_DECODING_ERROR\\0" + "ONLY_ONE_OF_P_Q_GIVEN\\0" + "OUTPUT_BUFFER_TOO_SMALL\\0" + "PADDING_CHECK_FAILED\\0" + "PKCS_DECODING_ERROR\\0" + "SLEN_CHECK_FAILED\\0" + "SLEN_RECOVERY_FAILED\\0" + "UNKNOWN_ALGORITHM_TYPE\\0" + "UNKNOWN_PADDING_TYPE\\0" + "VALUE_MISSING\\0" + "WRONG_SIGNATURE_LENGTH\\0" + "ALPN_MISMATCH_ON_EARLY_DATA\\0" + "APPLICATION_DATA_INSTEAD_OF_HANDSHAKE\\0" + "APP_DATA_IN_HANDSHAKE\\0" + "ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT\\0" + "BAD_ALERT\\0" + "BAD_CHANGE_CIPHER_SPEC\\0" + "BAD_DATA_RETURNED_BY_CALLBACK\\0" + "BAD_DH_P_LENGTH\\0" + "BAD_DIGEST_LENGTH\\0" + "BAD_ECC_CERT\\0" + "BAD_ECPOINT\\0" + "BAD_HANDSHAKE_RECORD\\0" + "BAD_HELLO_REQUEST\\0" + "BAD_LENGTH\\0" + "BAD_PACKET_LENGTH\\0" + "BAD_RSA_ENCRYPT\\0" + "BAD_SRTP_MKI_VALUE\\0" + "BAD_SRTP_PROTECTION_PROFILE_LIST\\0" + "BAD_SSL_FILETYPE\\0" + "BAD_WRITE_RETRY\\0" + "BIO_NOT_SET\\0" + "BLOCK_CIPHER_PAD_IS_WRONG\\0" + "BUFFERED_MESSAGES_ON_CIPHER_CHANGE\\0" + "CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD\\0" + "CANNOT_PARSE_LEAF_CERT\\0" + "CA_DN_LENGTH_MISMATCH\\0" + "CA_DN_TOO_LONG\\0" + "CCS_RECEIVED_EARLY\\0" + "CERTIFICATE_AND_PRIVATE_KEY_MISMATCH\\0" + "CERTIFICATE_VERIFY_FAILED\\0" + "CERT_CB_ERROR\\0" + "CERT_LENGTH_MISMATCH\\0" + "CHANNEL_ID_NOT_P256\\0" + "CHANNEL_ID_SIGNATURE_INVALID\\0" + "CIPHER_OR_HASH_UNAVAILABLE\\0" + "CLIENTHELLO_PARSE_FAILED\\0" + "CLIENTHELLO_TLSEXT\\0" + "CONNECTION_REJECTED\\0" + "CONNECTION_TYPE_NOT_SET\\0" + "CUSTOM_EXTENSION_ERROR\\0" + "DATA_LENGTH_TOO_LONG\\0" + "DECRYPTION_FAILED\\0" + "DECRYPTION_FAILED_OR_BAD_RECORD_MAC\\0" + "DH_PUBLIC_VALUE_LENGTH_IS_WRONG\\0" + "DH_P_TOO_LONG\\0" + "DIGEST_CHECK_FAILED\\0" + "DOWNGRADE_DETECTED\\0" + "DTLS_MESSAGE_TOO_BIG\\0" + "DUPLICATE_EXTENSION\\0" + "DUPLICATE_KEY_SHARE\\0" + "ECC_CERT_NOT_FOR_SIGNING\\0" + "EMS_STATE_INCONSISTENT\\0" + "ENCRYPTED_LENGTH_TOO_LONG\\0" + "ERROR_ADDING_EXTENSION\\0" + "ERROR_IN_RECEIVED_CIPHER_LIST\\0" + "ERROR_PARSING_EXTENSION\\0" + "EXCESSIVE_MESSAGE_SIZE\\0" + "EXTRA_DATA_IN_MESSAGE\\0" + "FRAGMENT_MISMATCH\\0" + "GOT_NEXT_PROTO_WITHOUT_EXTENSION\\0" + "HANDSHAKE_FAILURE_ON_CLIENT_HELLO\\0" + "HTTPS_PROXY_REQUEST\\0" + "HTTP_REQUEST\\0" + "INAPPROPRIATE_FALLBACK\\0" + "INVALID_ALPN_PROTOCOL\\0" + "INVALID_COMMAND\\0" + "INVALID_COMPRESSION_LIST\\0" + "INVALID_MESSAGE\\0" + "INVALID_OUTER_RECORD_TYPE\\0" + "INVALID_SCT_LIST\\0" + "INVALID_SSL_SESSION\\0" + "INVALID_TICKET_KEYS_LENGTH\\0" + "LENGTH_MISMATCH\\0" + "MISSING_EXTENSION\\0" + "MISSING_KEY_SHARE\\0" + "MISSING_RSA_CERTIFICATE\\0" + "MISSING_TMP_DH_KEY\\0" + "MISSING_TMP_ECDH_KEY\\0" + "MIXED_SPECIAL_OPERATOR_WITH_GROUPS\\0" + "MTU_TOO_SMALL\\0" + "NEGOTIATED_BOTH_NPN_AND_ALPN\\0" + "NESTED_GROUP\\0" + "NO_CERTIFICATES_RETURNED\\0" + "NO_CERTIFICATE_ASSIGNED\\0" + "NO_CERTIFICATE_SET\\0" + "NO_CIPHERS_AVAILABLE\\0" + "NO_CIPHERS_PASSED\\0" + "NO_CIPHERS_SPECIFIED\\0" + "NO_CIPHER_MATCH\\0" + "NO_COMMON_SIGNATURE_ALGORITHMS\\0" + "NO_COMPRESSION_SPECIFIED\\0" + "NO_GROUPS_SPECIFIED\\0" + "NO_METHOD_SPECIFIED\\0" + "NO_P256_SUPPORT\\0" + "NO_PRIVATE_KEY_ASSIGNED\\0" + "NO_RENEGOTIATION\\0" + "NO_REQUIRED_DIGEST\\0" + "NO_SHARED_CIPHER\\0" + "NO_SHARED_GROUP\\0" + "NO_SUPPORTED_VERSIONS_ENABLED\\0" + "NULL_SSL_CTX\\0" + "NULL_SSL_METHOD_PASSED\\0" + "OLD_SESSION_CIPHER_NOT_RETURNED\\0" + "OLD_SESSION_PRF_HASH_MISMATCH\\0" + "OLD_SESSION_VERSION_NOT_RETURNED\\0" + "PARSE_TLSEXT\\0" + "PATH_TOO_LONG\\0" + "PEER_DID_NOT_RETURN_A_CERTIFICATE\\0" + "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\\0" + "PRE_SHARED_KEY_MUST_BE_LAST\\0" + "PROTOCOL_IS_SHUTDOWN\\0" + "PSK_IDENTITY_BINDER_COUNT_MISMATCH\\0" + "PSK_IDENTITY_NOT_FOUND\\0" + "PSK_NO_CLIENT_CB\\0" + "PSK_NO_SERVER_CB\\0" + "READ_TIMEOUT_EXPIRED\\0" + "RECORD_LENGTH_MISMATCH\\0" + "RECORD_TOO_LARGE\\0" + "RENEGOTIATION_EMS_MISMATCH\\0" + "RENEGOTIATION_ENCODING_ERR\\0" + "RENEGOTIATION_MISMATCH\\0" + "REQUIRED_CIPHER_MISSING\\0" + "RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION\\0" + "RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION\\0" + "SCSV_RECEIVED_WHEN_RENEGOTIATING\\0" + "SERVERHELLO_TLSEXT\\0" + "SERVER_CERT_CHANGED\\0" + "SESSION_ID_CONTEXT_UNINITIALIZED\\0" + "SESSION_MAY_NOT_BE_CREATED\\0" + "SHUTDOWN_WHILE_IN_INIT\\0" + "SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER\\0" + "SRTP_COULD_NOT_ALLOCATE_PROFILES\\0" + "SRTP_UNKNOWN_PROTECTION_PROFILE\\0" + "SSL3_EXT_INVALID_SERVERNAME\\0" + "SSLV3_ALERT_BAD_CERTIFICATE\\0" + "SSLV3_ALERT_BAD_RECORD_MAC\\0" + "SSLV3_ALERT_CERTIFICATE_EXPIRED\\0" + "SSLV3_ALERT_CERTIFICATE_REVOKED\\0" + "SSLV3_ALERT_CERTIFICATE_UNKNOWN\\0" + "SSLV3_ALERT_CLOSE_NOTIFY\\0" + "SSLV3_ALERT_DECOMPRESSION_FAILURE\\0" + "SSLV3_ALERT_HANDSHAKE_FAILURE\\0" + "SSLV3_ALERT_ILLEGAL_PARAMETER\\0" + "SSLV3_ALERT_NO_CERTIFICATE\\0" + "SSLV3_ALERT_UNEXPECTED_MESSAGE\\0" + "SSLV3_ALERT_UNSUPPORTED_CERTIFICATE\\0" + "SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION\\0" + "SSL_HANDSHAKE_FAILURE\\0" + "SSL_SESSION_ID_CONTEXT_TOO_LONG\\0" + "TICKET_ENCRYPTION_FAILED\\0" + "TLSV1_ALERT_ACCESS_DENIED\\0" + "TLSV1_ALERT_DECODE_ERROR\\0" + "TLSV1_ALERT_DECRYPTION_FAILED\\0" + "TLSV1_ALERT_DECRYPT_ERROR\\0" + "TLSV1_ALERT_EXPORT_RESTRICTION\\0" + "TLSV1_ALERT_INAPPROPRIATE_FALLBACK\\0" + "TLSV1_ALERT_INSUFFICIENT_SECURITY\\0" + "TLSV1_ALERT_INTERNAL_ERROR\\0" + "TLSV1_ALERT_NO_RENEGOTIATION\\0" + "TLSV1_ALERT_PROTOCOL_VERSION\\0" + "TLSV1_ALERT_RECORD_OVERFLOW\\0" + "TLSV1_ALERT_UNKNOWN_CA\\0" + "TLSV1_ALERT_USER_CANCELLED\\0" + "TLSV1_BAD_CERTIFICATE_HASH_VALUE\\0" + "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\\0" + "TLSV1_CERTIFICATE_REQUIRED\\0" + "TLSV1_CERTIFICATE_UNOBTAINABLE\\0" + "TLSV1_UNKNOWN_PSK_IDENTITY\\0" + "TLSV1_UNRECOGNIZED_NAME\\0" + "TLSV1_UNSUPPORTED_EXTENSION\\0" + "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\\0" + "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG\\0" + "TOO_MANY_EMPTY_FRAGMENTS\\0" + "TOO_MANY_KEY_UPDATES\\0" + "TOO_MANY_WARNING_ALERTS\\0" + "TOO_MUCH_READ_EARLY_DATA\\0" + "TOO_MUCH_SKIPPED_EARLY_DATA\\0" + "UNABLE_TO_FIND_ECDH_PARAMETERS\\0" + "UNEXPECTED_EXTENSION\\0" + "UNEXPECTED_EXTENSION_ON_EARLY_DATA\\0" + "UNEXPECTED_MESSAGE\\0" + "UNEXPECTED_OPERATOR_IN_GROUP\\0" + "UNEXPECTED_RECORD\\0" + "UNKNOWN_ALERT_TYPE\\0" + "UNKNOWN_CERTIFICATE_TYPE\\0" + "UNKNOWN_CIPHER_RETURNED\\0" + "UNKNOWN_CIPHER_TYPE\\0" + "UNKNOWN_KEY_EXCHANGE_TYPE\\0" + "UNKNOWN_PROTOCOL\\0" + "UNKNOWN_SSL_VERSION\\0" + "UNKNOWN_STATE\\0" + "UNSAFE_LEGACY_RENEGOTIATION_DISABLED\\0" + "UNSUPPORTED_COMPRESSION_ALGORITHM\\0" + "UNSUPPORTED_ELLIPTIC_CURVE\\0" + "UNSUPPORTED_PROTOCOL\\0" + "UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY\\0" + "WRONG_CERTIFICATE_TYPE\\0" + "WRONG_CIPHER_RETURNED\\0" + "WRONG_CURVE\\0" + "WRONG_MESSAGE_TYPE\\0" + "WRONG_SIGNATURE_TYPE\\0" + "WRONG_SSL_VERSION\\0" + "WRONG_VERSION_NUMBER\\0" + "WRONG_VERSION_ON_EARLY_DATA\\0" + "X509_LIB\\0" + "X509_VERIFICATION_SETUP_PROBLEMS\\0" + "AKID_MISMATCH\\0" + "BAD_X509_FILETYPE\\0" + "BASE64_DECODE_ERROR\\0" + "CANT_CHECK_DH_KEY\\0" + "CERT_ALREADY_IN_HASH_TABLE\\0" + "CRL_ALREADY_DELTA\\0" + "CRL_VERIFY_FAILURE\\0" + "IDP_MISMATCH\\0" + "INVALID_DIRECTORY\\0" + "INVALID_FIELD_NAME\\0" + "INVALID_PARAMETER\\0" + "INVALID_PSS_PARAMETERS\\0" + "INVALID_TRUST\\0" + "ISSUER_MISMATCH\\0" + "KEY_TYPE_MISMATCH\\0" + "KEY_VALUES_MISMATCH\\0" + "LOADING_CERT_DIR\\0" + "LOADING_DEFAULTS\\0" + "NAME_TOO_LONG\\0" + "NEWER_CRL_NOT_NEWER\\0" + "NO_CERT_SET_FOR_US_TO_VERIFY\\0" + "NO_CRL_NUMBER\\0" + "PUBLIC_KEY_DECODE_ERROR\\0" + "PUBLIC_KEY_ENCODE_ERROR\\0" + "SHOULD_RETRY\\0" + "UNKNOWN_KEY_TYPE\\0" + "UNKNOWN_PURPOSE_ID\\0" + "UNKNOWN_TRUST_ID\\0" + "WRONG_LOOKUP_TYPE\\0" + "BAD_IP_ADDRESS\\0" + "BAD_OBJECT\\0" + "BN_DEC2BN_ERROR\\0" + "BN_TO_ASN1_INTEGER_ERROR\\0" + "CANNOT_FIND_FREE_FUNCTION\\0" + "DIRNAME_ERROR\\0" + "DISTPOINT_ALREADY_SET\\0" + "DUPLICATE_ZONE_ID\\0" + "ERROR_CONVERTING_ZONE\\0" + "ERROR_CREATING_EXTENSION\\0" + "ERROR_IN_EXTENSION\\0" + "EXPECTED_A_SECTION_NAME\\0" + "EXTENSION_EXISTS\\0" + "EXTENSION_NAME_ERROR\\0" + "EXTENSION_NOT_FOUND\\0" + "EXTENSION_SETTING_NOT_SUPPORTED\\0" + "EXTENSION_VALUE_ERROR\\0" + "ILLEGAL_EMPTY_EXTENSION\\0" + "ILLEGAL_HEX_DIGIT\\0" + "INCORRECT_POLICY_SYNTAX_TAG\\0" + "INVALID_BOOLEAN_STRING\\0" + "INVALID_EXTENSION_STRING\\0" + "INVALID_MULTIPLE_RDNS\\0" + "INVALID_NAME\\0" + "INVALID_NULL_ARGUMENT\\0" + "INVALID_NULL_NAME\\0" + "INVALID_NULL_VALUE\\0" + "INVALID_NUMBERS\\0" + "INVALID_OBJECT_IDENTIFIER\\0" + "INVALID_OPTION\\0" + "INVALID_POLICY_IDENTIFIER\\0" + "INVALID_PROXY_POLICY_SETTING\\0" + "INVALID_PURPOSE\\0" + "INVALID_SECTION\\0" + "INVALID_SYNTAX\\0" + "ISSUER_DECODE_ERROR\\0" + "NEED_ORGANIZATION_AND_NUMBERS\\0" + "NO_CONFIG_DATABASE\\0" + "NO_ISSUER_CERTIFICATE\\0" + "NO_ISSUER_DETAILS\\0" + "NO_POLICY_IDENTIFIER\\0" + "NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED\\0" + "NO_PUBLIC_KEY\\0" + "NO_SUBJECT_DETAILS\\0" + "ODD_NUMBER_OF_DIGITS\\0" + "OPERATION_NOT_DEFINED\\0" + "OTHERNAME_ERROR\\0" + "POLICY_LANGUAGE_ALREADY_DEFINED\\0" + "POLICY_PATH_LENGTH\\0" + "POLICY_PATH_LENGTH_ALREADY_DEFINED\\0" + "POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY\\0" + "SECTION_NOT_FOUND\\0" + "UNABLE_TO_GET_ISSUER_DETAILS\\0" + "UNABLE_TO_GET_ISSUER_KEYID\\0" + "UNKNOWN_BIT_STRING_ARGUMENT\\0" + "UNKNOWN_EXTENSION\\0" + "UNKNOWN_EXTENSION_NAME\\0" + "UNKNOWN_OPTION\\0" + "UNSUPPORTED_OPTION\\0" + "USER_TOO_LONG\\0" + ""; + EOF - sed -i'.back' '/^#define \\([A-Za-z0-9_]*\\) \\1/d' include/openssl/ssl.h - sed -i'.back' 'N;/^#define \\([A-Za-z0-9_]*\\) *\\\\\\n *\\1/d' include/openssl/ssl.h - sed -i'.back' 's/#ifndef md5_block_data_order/#ifndef GRPC_SHADOW_md5_block_data_order/g' crypto/fipsmodule/md5/md5.c - find . -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include Date: Thu, 17 Jan 2019 13:37:26 -0800 Subject: [PATCH 017/218] fix indent in template --- .../BoringSSL-GRPC.podspec.template | 8998 ++++++++--------- 1 file changed, 4499 insertions(+), 4499 deletions(-) diff --git a/templates/src/objective-c/BoringSSL-GRPC.podspec.template b/templates/src/objective-c/BoringSSL-GRPC.podspec.template index 42e3c7a82ea..8b2a23ae0c5 100644 --- a/templates/src/objective-c/BoringSSL-GRPC.podspec.template +++ b/templates/src/objective-c/BoringSSL-GRPC.podspec.template @@ -5,4531 +5,4531 @@ return ',\n '.join("'#define %s GRPC_SHADOW_%s'" % (symbol, symbol) for symbol in symbol_list) %> -# This file has been automatically generated from a template file. -# Please make modifications to -# `templates/src/objective-c/BoringSSL-GRPC.podspec.template` instead. This -# file can be regenerated from the template by running -# `tools/buildgen/generate_projects.sh`. + # This file has been automatically generated from a template file. + # Please make modifications to + # `templates/src/objective-c/BoringSSL-GRPC.podspec.template` instead. This + # file can be regenerated from the template by running + # `tools/buildgen/generate_projects.sh`. -# BoringSSL CocoaPods podspec + # BoringSSL CocoaPods podspec -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # Copyright 2015, Google Inc. + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions are + # met: + # + # * Redistributions of source code must retain the above copyright + # notice, this list of conditions and the following disclaimer. + # * Redistributions in binary form must reproduce the above + # copyright notice, this list of conditions and the following disclaimer + # in the documentation and/or other materials provided with the + # distribution. + # * Neither the name of Google Inc. nor the names of its + # contributors may be used to endorse or promote products derived from + # this software without specific prior written permission. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Pod::Spec.new do |s| - s.name = 'BoringSSL-GRPC' - version = '0.0.2' - s.version = version - s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.' - # Adapted from the homepage: - s.description = <<-DESC - BoringSSL is a fork of OpenSSL that is designed to meet Google's needs. + Pod::Spec.new do |s| + s.name = 'BoringSSL-GRPC' + version = '0.0.2' + s.version = version + s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.' + # Adapted from the homepage: + s.description = <<-DESC + BoringSSL is a fork of OpenSSL that is designed to meet Google's needs. - Although BoringSSL is an open source project, it is not intended for general use, as OpenSSL is. - We don't recommend that third parties depend upon it. Doing so is likely to be frustrating - because there are no guarantees of API stability. Only the latest version of this pod is - supported, and every new version is a new major version. + Although BoringSSL is an open source project, it is not intended for general use, as OpenSSL is. + We don't recommend that third parties depend upon it. Doing so is likely to be frustrating + because there are no guarantees of API stability. Only the latest version of this pod is + supported, and every new version is a new major version. - We update Google libraries and programs that use BoringSSL as needed when deciding to make API - changes. This allows us to mostly avoid compromises in the name of compatibility. It works for - us, but it may not work for you. + We update Google libraries and programs that use BoringSSL as needed when deciding to make API + changes. This allows us to mostly avoid compromises in the name of compatibility. It works for + us, but it may not work for you. - As a Cocoapods pod, it has the advantage over OpenSSL's pods that the library doesn't need to - be precompiled. This eliminates the 10 - 20 minutes of wait the first time a user does "pod - install", lets it be used as a dynamic framework (pending solution of Cocoapods' issue #4605), - and works with bitcode automatically. It's also thought to be smaller than OpenSSL (which takes - 1MB - 2MB per ARM architecture), but we don't have specific numbers yet. + As a Cocoapods pod, it has the advantage over OpenSSL's pods that the library doesn't need to + be precompiled. This eliminates the 10 - 20 minutes of wait the first time a user does "pod + install", lets it be used as a dynamic framework (pending solution of Cocoapods' issue #4605), + and works with bitcode automatically. It's also thought to be smaller than OpenSSL (which takes + 1MB - 2MB per ARM architecture), but we don't have specific numbers yet. - BoringSSL arose because Google used OpenSSL for many years in various ways and, over time, built - up a large number of patches that were maintained while tracking upstream OpenSSL. As Google's - product portfolio became more complex, more copies of OpenSSL sprung up and the effort involved - in maintaining all these patches in multiple places was growing steadily. + BoringSSL arose because Google used OpenSSL for many years in various ways and, over time, built + up a large number of patches that were maintained while tracking upstream OpenSSL. As Google's + product portfolio became more complex, more copies of OpenSSL sprung up and the effort involved + in maintaining all these patches in multiple places was growing steadily. - Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it's not part of the - NDK) and a number of other apps/programs. - DESC - s.homepage = 'https://github.com/google/boringssl' - s.license = { :type => 'Mixed', :file => 'LICENSE' } - # "The name and email addresses of the library maintainers, not the Podspec maintainer." - s.authors = 'Adam Langley', 'David Benjamin', 'Matt Braithwaite' + Currently BoringSSL is the SSL library in Chrome/Chromium, Android (but it's not part of the + NDK) and a number of other apps/programs. + DESC + s.homepage = 'https://github.com/google/boringssl' + s.license = { :type => 'Mixed', :file => 'LICENSE' } + # "The name and email addresses of the library maintainers, not the Podspec maintainer." + s.authors = 'Adam Langley', 'David Benjamin', 'Matt Braithwaite' - s.source = { - :git => 'https://github.com/google/boringssl.git', - :commit => "b29b21a81b32ec273f118f589f46d56ad3332420", - } + s.source = { + :git => 'https://github.com/google/boringssl.git', + :commit => "b29b21a81b32ec273f118f589f46d56ad3332420", + } - s.ios.deployment_target = '5.0' - s.osx.deployment_target = '10.7' - s.tvos.deployment_target = '10.0' + s.ios.deployment_target = '5.0' + s.osx.deployment_target = '10.7' + s.tvos.deployment_target = '10.0' - name = 'openssl_grpc' + name = 'openssl_grpc' - # When creating a dynamic framework, name it openssl.framework instead of BoringSSL.framework. - # This lets users write their includes like `#include ` as opposed to `#include - # `. - s.module_name = name + # When creating a dynamic framework, name it openssl.framework instead of BoringSSL.framework. + # This lets users write their includes like `#include ` as opposed to `#include + # `. + s.module_name = name - # When creating a dynamic framework, copy the headers under `include/openssl/` into the root of - # the `Headers/` directory of the framework (i.e., not under `Headers/include/openssl`). - # - # TODO(jcanizales): Debug why this doesn't work on macOS. - s.header_mappings_dir = 'include/openssl' + # When creating a dynamic framework, copy the headers under `include/openssl/` into the root of + # the `Headers/` directory of the framework (i.e., not under `Headers/include/openssl`). + # + # TODO(jcanizales): Debug why this doesn't work on macOS. + s.header_mappings_dir = 'include/openssl' - # The above has an undesired effect when creating a static library: It forces users to write - # includes like `#include `. `s.header_dir` adds a path prefix to that, and - # because Cocoapods lets omit the pod name when including headers of static libraries, the - # following lets users write `#include `. - s.header_dir = name + # The above has an undesired effect when creating a static library: It forces users to write + # includes like `#include `. `s.header_dir` adds a path prefix to that, and + # because Cocoapods lets omit the pod name when including headers of static libraries, the + # following lets users write `#include `. + s.header_dir = name - # The module map and umbrella header created automatically by Cocoapods don't work for C libraries - # like this one. The following file, and a correct umbrella header, are created on the fly by the - # `prepare_command` of this pod. - s.module_map = 'include/openssl/BoringSSL.modulemap' + # The module map and umbrella header created automatically by Cocoapods don't work for C libraries + # like this one. The following file, and a correct umbrella header, are created on the fly by the + # `prepare_command` of this pod. + s.module_map = 'include/openssl/BoringSSL.modulemap' - # We don't need to inhibit all warnings; only -Wno-shorten-64-to-32. But Cocoapods' linter doesn't - # want that for some reason. - s.compiler_flags = '-DOPENSSL_NO_ASM', '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w' - s.requires_arc = false + # We don't need to inhibit all warnings; only -Wno-shorten-64-to-32. But Cocoapods' linter doesn't + # want that for some reason. + s.compiler_flags = '-DOPENSSL_NO_ASM', '-GCC_WARN_INHIBIT_ALL_WARNINGS', '-w' + s.requires_arc = false - # Like many other C libraries, BoringSSL has its public headers under `include//` and its - # sources and private headers in other directories outside `include/`. Cocoapods' linter doesn't - # allow any header to be listed outside the `header_mappings_dir` (even though doing so works in - # practice). Because we need our `header_mappings_dir` to be `include/openssl/` for the reason - # mentioned above, we work around the linter limitation by dividing the pod into two subspecs, one - # for public headers and the other for implementation. Each gets its own `header_mappings_dir`, - # making the linter happy. - s.subspec 'Interface' do |ss| - ss.header_mappings_dir = 'include/openssl' - ss.source_files = 'include/openssl/*.h' - end - s.subspec 'Implementation' do |ss| - ss.header_mappings_dir = '.' - ss.source_files = 'ssl/*.{h,cc}', - 'ssl/**/*.{h,cc}', - '*.{h,c}', - 'crypto/*.{h,c}', - 'crypto/**/*.{h,c}', - 'third_party/fiat/*.{h,c}' - ss.private_header_files = 'ssl/*.h', - 'ssl/**/*.h', - '*.h', - 'crypto/*.h', - 'crypto/**/*.h' - # bcm.c includes other source files, creating duplicated symbols. Since it is not used, we - # explicitly exclude it from the pod. - # TODO (mxyan): Work with BoringSSL team to remove this hack. - ss.exclude_files = 'crypto/fipsmodule/bcm.c', - '**/*_test.*', - '**/test_*.*', - '**/test/*.*' + # Like many other C libraries, BoringSSL has its public headers under `include//` and its + # sources and private headers in other directories outside `include/`. Cocoapods' linter doesn't + # allow any header to be listed outside the `header_mappings_dir` (even though doing so works in + # practice). Because we need our `header_mappings_dir` to be `include/openssl/` for the reason + # mentioned above, we work around the linter limitation by dividing the pod into two subspecs, one + # for public headers and the other for implementation. Each gets its own `header_mappings_dir`, + # making the linter happy. + s.subspec 'Interface' do |ss| + ss.header_mappings_dir = 'include/openssl' + ss.source_files = 'include/openssl/*.h' + end + s.subspec 'Implementation' do |ss| + ss.header_mappings_dir = '.' + ss.source_files = 'ssl/*.{h,cc}', + 'ssl/**/*.{h,cc}', + '*.{h,c}', + 'crypto/*.{h,c}', + 'crypto/**/*.{h,c}', + 'third_party/fiat/*.{h,c}' + ss.private_header_files = 'ssl/*.h', + 'ssl/**/*.h', + '*.h', + 'crypto/*.h', + 'crypto/**/*.h' + # bcm.c includes other source files, creating duplicated symbols. Since it is not used, we + # explicitly exclude it from the pod. + # TODO (mxyan): Work with BoringSSL team to remove this hack. + ss.exclude_files = 'crypto/fipsmodule/bcm.c', + '**/*_test.*', + '**/test_*.*', + '**/test/*.*' - ss.dependency "#{s.name}/Interface", version - end + ss.dependency "#{s.name}/Interface", version + end - s.prepare_command = <<-END_OF_COMMAND - # Add a module map and an umbrella header - cat > include/openssl/umbrella.h < include/openssl/BoringSSL.modulemap < include/openssl/umbrella.h < include/openssl/BoringSSL.modulemap < err_data.c < err_data.c < - #include - #include + #include + #include + #include - OPENSSL_COMPILE_ASSERT(ERR_LIB_NONE == 1, library_values_changed_1); - OPENSSL_COMPILE_ASSERT(ERR_LIB_SYS == 2, library_values_changed_2); - OPENSSL_COMPILE_ASSERT(ERR_LIB_BN == 3, library_values_changed_3); - OPENSSL_COMPILE_ASSERT(ERR_LIB_RSA == 4, library_values_changed_4); - OPENSSL_COMPILE_ASSERT(ERR_LIB_DH == 5, library_values_changed_5); - OPENSSL_COMPILE_ASSERT(ERR_LIB_EVP == 6, library_values_changed_6); - OPENSSL_COMPILE_ASSERT(ERR_LIB_BUF == 7, library_values_changed_7); - OPENSSL_COMPILE_ASSERT(ERR_LIB_OBJ == 8, library_values_changed_8); - OPENSSL_COMPILE_ASSERT(ERR_LIB_PEM == 9, library_values_changed_9); - OPENSSL_COMPILE_ASSERT(ERR_LIB_DSA == 10, library_values_changed_10); - OPENSSL_COMPILE_ASSERT(ERR_LIB_X509 == 11, library_values_changed_11); - OPENSSL_COMPILE_ASSERT(ERR_LIB_ASN1 == 12, library_values_changed_12); - OPENSSL_COMPILE_ASSERT(ERR_LIB_CONF == 13, library_values_changed_13); - OPENSSL_COMPILE_ASSERT(ERR_LIB_CRYPTO == 14, library_values_changed_14); - OPENSSL_COMPILE_ASSERT(ERR_LIB_EC == 15, library_values_changed_15); - OPENSSL_COMPILE_ASSERT(ERR_LIB_SSL == 16, library_values_changed_16); - OPENSSL_COMPILE_ASSERT(ERR_LIB_BIO == 17, library_values_changed_17); - OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS7 == 18, library_values_changed_18); - OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS8 == 19, library_values_changed_19); - OPENSSL_COMPILE_ASSERT(ERR_LIB_X509V3 == 20, library_values_changed_20); - OPENSSL_COMPILE_ASSERT(ERR_LIB_RAND == 21, library_values_changed_21); - OPENSSL_COMPILE_ASSERT(ERR_LIB_ENGINE == 22, library_values_changed_22); - OPENSSL_COMPILE_ASSERT(ERR_LIB_OCSP == 23, library_values_changed_23); - OPENSSL_COMPILE_ASSERT(ERR_LIB_UI == 24, library_values_changed_24); - OPENSSL_COMPILE_ASSERT(ERR_LIB_COMP == 25, library_values_changed_25); - OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDSA == 26, library_values_changed_26); - OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDH == 27, library_values_changed_27); - OPENSSL_COMPILE_ASSERT(ERR_LIB_HMAC == 28, library_values_changed_28); - OPENSSL_COMPILE_ASSERT(ERR_LIB_DIGEST == 29, library_values_changed_29); - OPENSSL_COMPILE_ASSERT(ERR_LIB_CIPHER == 30, library_values_changed_30); - OPENSSL_COMPILE_ASSERT(ERR_LIB_HKDF == 31, library_values_changed_31); - OPENSSL_COMPILE_ASSERT(ERR_LIB_USER == 32, library_values_changed_32); - OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num); + OPENSSL_COMPILE_ASSERT(ERR_LIB_NONE == 1, library_values_changed_1); + OPENSSL_COMPILE_ASSERT(ERR_LIB_SYS == 2, library_values_changed_2); + OPENSSL_COMPILE_ASSERT(ERR_LIB_BN == 3, library_values_changed_3); + OPENSSL_COMPILE_ASSERT(ERR_LIB_RSA == 4, library_values_changed_4); + OPENSSL_COMPILE_ASSERT(ERR_LIB_DH == 5, library_values_changed_5); + OPENSSL_COMPILE_ASSERT(ERR_LIB_EVP == 6, library_values_changed_6); + OPENSSL_COMPILE_ASSERT(ERR_LIB_BUF == 7, library_values_changed_7); + OPENSSL_COMPILE_ASSERT(ERR_LIB_OBJ == 8, library_values_changed_8); + OPENSSL_COMPILE_ASSERT(ERR_LIB_PEM == 9, library_values_changed_9); + OPENSSL_COMPILE_ASSERT(ERR_LIB_DSA == 10, library_values_changed_10); + OPENSSL_COMPILE_ASSERT(ERR_LIB_X509 == 11, library_values_changed_11); + OPENSSL_COMPILE_ASSERT(ERR_LIB_ASN1 == 12, library_values_changed_12); + OPENSSL_COMPILE_ASSERT(ERR_LIB_CONF == 13, library_values_changed_13); + OPENSSL_COMPILE_ASSERT(ERR_LIB_CRYPTO == 14, library_values_changed_14); + OPENSSL_COMPILE_ASSERT(ERR_LIB_EC == 15, library_values_changed_15); + OPENSSL_COMPILE_ASSERT(ERR_LIB_SSL == 16, library_values_changed_16); + OPENSSL_COMPILE_ASSERT(ERR_LIB_BIO == 17, library_values_changed_17); + OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS7 == 18, library_values_changed_18); + OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS8 == 19, library_values_changed_19); + OPENSSL_COMPILE_ASSERT(ERR_LIB_X509V3 == 20, library_values_changed_20); + OPENSSL_COMPILE_ASSERT(ERR_LIB_RAND == 21, library_values_changed_21); + OPENSSL_COMPILE_ASSERT(ERR_LIB_ENGINE == 22, library_values_changed_22); + OPENSSL_COMPILE_ASSERT(ERR_LIB_OCSP == 23, library_values_changed_23); + OPENSSL_COMPILE_ASSERT(ERR_LIB_UI == 24, library_values_changed_24); + OPENSSL_COMPILE_ASSERT(ERR_LIB_COMP == 25, library_values_changed_25); + OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDSA == 26, library_values_changed_26); + OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDH == 27, library_values_changed_27); + OPENSSL_COMPILE_ASSERT(ERR_LIB_HMAC == 28, library_values_changed_28); + OPENSSL_COMPILE_ASSERT(ERR_LIB_DIGEST == 29, library_values_changed_29); + OPENSSL_COMPILE_ASSERT(ERR_LIB_CIPHER == 30, library_values_changed_30); + OPENSSL_COMPILE_ASSERT(ERR_LIB_HKDF == 31, library_values_changed_31); + OPENSSL_COMPILE_ASSERT(ERR_LIB_USER == 32, library_values_changed_32); + OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num); - const uint32_t kOpenSSLReasonValues[] = { - 0xc320838, - 0xc328852, - 0xc330861, - 0xc338871, - 0xc340880, - 0xc348899, - 0xc3508a5, - 0xc3588c2, - 0xc3608e2, - 0xc3688f0, - 0xc370900, - 0xc37890d, - 0xc38091d, - 0xc388928, - 0xc39093e, - 0xc39894d, - 0xc3a0961, - 0xc3a8845, - 0xc3b00ea, - 0xc3b88d4, - 0x10320845, - 0x10329513, - 0x1033151f, - 0x10339538, - 0x1034154b, - 0x10348eed, - 0x10350c5e, - 0x1035955e, - 0x10361573, - 0x10369586, - 0x103715a5, - 0x103795be, - 0x103815d3, - 0x103895f1, - 0x10391600, - 0x1039961c, - 0x103a1637, - 0x103a9646, - 0x103b1662, - 0x103b967d, - 0x103c1694, - 0x103c80ea, - 0x103d16a5, - 0x103d96b9, - 0x103e16d8, - 0x103e96e7, - 0x103f16fe, - 0x103f9711, - 0x10400c22, - 0x10409724, - 0x10411742, - 0x10419755, - 0x1042176f, - 0x1042977f, - 0x10431793, - 0x104397a9, - 0x104417c1, - 0x104497d6, - 0x104517ea, - 0x104597fc, - 0x104605fb, - 0x1046894d, - 0x10471811, - 0x10479828, - 0x1048183d, - 0x1048984b, - 0x10490e4f, - 0x14320c05, - 0x14328c13, - 0x14330c22, - 0x14338c34, - 0x143400ac, - 0x143480ea, - 0x18320083, - 0x18328f43, - 0x183300ac, - 0x18338f59, - 0x18340f6d, - 0x183480ea, - 0x18350f82, - 0x18358f9a, - 0x18360faf, - 0x18368fc3, - 0x18370fe7, - 0x18378ffd, - 0x18381011, - 0x18389021, - 0x18390a73, - 0x18399031, - 0x183a1059, - 0x183a907f, - 0x183b0c6a, - 0x183b90b4, - 0x183c10c6, - 0x183c90d1, - 0x183d10e1, - 0x183d90f2, - 0x183e1103, - 0x183e9115, - 0x183f113e, - 0x183f9157, - 0x1840116f, - 0x184086d3, - 0x184110a2, - 0x1841906d, - 0x1842108c, - 0x18429046, - 0x20321196, - 0x243211a2, - 0x24328993, - 0x243311b4, - 0x243391c1, - 0x243411ce, - 0x243491e0, - 0x243511ef, - 0x2435920c, - 0x24361219, - 0x24369227, - 0x24371235, - 0x24379243, - 0x2438124c, - 0x24389259, - 0x2439126c, - 0x28320c52, - 0x28328c6a, - 0x28330c22, - 0x28338c7d, - 0x28340c5e, - 0x283480ac, - 0x283500ea, - 0x2c322c30, - 0x2c329283, - 0x2c332c3e, - 0x2c33ac50, - 0x2c342c64, - 0x2c34ac76, - 0x2c352c91, - 0x2c35aca3, - 0x2c362cb6, - 0x2c36832d, - 0x2c372cc3, - 0x2c37acd5, - 0x2c382cfa, - 0x2c38ad11, - 0x2c392d1f, - 0x2c39ad2f, - 0x2c3a2d41, - 0x2c3aad55, - 0x2c3b2d66, - 0x2c3bad85, - 0x2c3c1295, - 0x2c3c92ab, - 0x2c3d2d99, - 0x2c3d92c4, - 0x2c3e2db6, - 0x2c3eadc4, - 0x2c3f2ddc, - 0x2c3fadf4, - 0x2c402e01, - 0x2c409196, - 0x2c412e12, - 0x2c41ae25, - 0x2c42116f, - 0x2c42ae36, - 0x2c430720, - 0x2c43ad77, - 0x2c442ce8, - 0x30320000, - 0x30328015, - 0x3033001f, - 0x30338038, - 0x3034004a, - 0x30348064, - 0x3035006b, - 0x30358083, - 0x30360094, - 0x303680ac, - 0x303700b9, - 0x303780c8, - 0x303800ea, - 0x303880f7, - 0x3039010a, - 0x30398125, - 0x303a013a, - 0x303a814e, - 0x303b0162, - 0x303b8173, - 0x303c018c, - 0x303c81a9, - 0x303d01b7, - 0x303d81cb, - 0x303e01db, - 0x303e81f4, - 0x303f0204, - 0x303f8217, - 0x30400226, - 0x30408232, - 0x30410247, - 0x30418257, - 0x3042026e, - 0x3042827b, - 0x3043028e, - 0x3043829d, - 0x304402b2, - 0x304482d3, - 0x304502e6, - 0x304582f9, - 0x30460312, - 0x3046832d, - 0x3047034a, - 0x30478363, - 0x30480371, - 0x30488382, - 0x30490391, - 0x304983a9, - 0x304a03bb, - 0x304a83cf, - 0x304b03ee, - 0x304b8401, - 0x304c040c, - 0x304c841d, - 0x304d0429, - 0x304d843f, - 0x304e044d, - 0x304e8463, - 0x304f0475, - 0x304f8487, - 0x3050049a, - 0x305084ad, - 0x305104be, - 0x305184ce, - 0x305204e6, - 0x305284fb, - 0x30530513, - 0x30538527, - 0x3054053f, - 0x30548558, - 0x30550571, - 0x3055858e, - 0x30560599, - 0x305685b1, - 0x305705c1, - 0x305785d2, - 0x305805e5, - 0x305885fb, - 0x30590604, - 0x30598619, - 0x305a062c, - 0x305a863b, - 0x305b065b, - 0x305b866a, - 0x305c068b, - 0x305c86a7, - 0x305d06b3, - 0x305d86d3, - 0x305e06ef, - 0x305e8700, - 0x305f0716, - 0x305f8720, - 0x34320b63, - 0x34328b77, - 0x34330b94, - 0x34338ba7, - 0x34340bb6, - 0x34348bef, - 0x34350bd3, - 0x3c320083, - 0x3c328ca7, - 0x3c330cc0, - 0x3c338cdb, - 0x3c340cf8, - 0x3c348d22, - 0x3c350d3d, - 0x3c358d63, - 0x3c360d7c, - 0x3c368d94, - 0x3c370da5, - 0x3c378db3, - 0x3c380dc0, - 0x3c388dd4, - 0x3c390c6a, - 0x3c398de8, - 0x3c3a0dfc, - 0x3c3a890d, - 0x3c3b0e0c, - 0x3c3b8e27, - 0x3c3c0e39, - 0x3c3c8e6c, - 0x3c3d0e76, - 0x3c3d8e8a, - 0x3c3e0e98, - 0x3c3e8ebd, - 0x3c3f0c93, - 0x3c3f8ea6, - 0x3c4000ac, - 0x3c4080ea, - 0x3c410d13, - 0x3c418d52, - 0x3c420e4f, - 0x403218a4, - 0x403298ba, - 0x403318e8, - 0x403398f2, - 0x40341909, - 0x40349927, - 0x40351937, - 0x40359949, - 0x40361956, - 0x40369962, - 0x40371977, - 0x40379989, - 0x40381994, - 0x403899a6, - 0x40390eed, - 0x403999b6, - 0x403a19c9, - 0x403a99ea, - 0x403b19fb, - 0x403b9a0b, - 0x403c0064, - 0x403c8083, - 0x403d1a8f, - 0x403d9aa5, - 0x403e1ab4, - 0x403e9aec, - 0x403f1b06, - 0x403f9b14, - 0x40401b29, - 0x40409b3d, - 0x40411b5a, - 0x40419b75, - 0x40421b8e, - 0x40429ba1, - 0x40431bb5, - 0x40439bcd, - 0x40441be4, - 0x404480ac, - 0x40451bf9, - 0x40459c0b, - 0x40461c2f, - 0x40469c4f, - 0x40471c5d, - 0x40479c84, - 0x40481cc1, - 0x40489cda, - 0x40491cf1, - 0x40499d0b, - 0x404a1d22, - 0x404a9d40, - 0x404b1d58, - 0x404b9d6f, - 0x404c1d85, - 0x404c9d97, - 0x404d1db8, - 0x404d9dda, - 0x404e1dee, - 0x404e9dfb, - 0x404f1e28, - 0x404f9e51, - 0x40501e8c, - 0x40509ea0, - 0x40511ebb, - 0x40521ecb, - 0x40529eef, - 0x40531f07, - 0x40539f1a, - 0x40541f2f, - 0x40549f52, - 0x40551f60, - 0x40559f7d, - 0x40561f8a, - 0x40569fa3, - 0x40571fbb, - 0x40579fce, - 0x40581fe3, - 0x4058a00a, - 0x40592039, - 0x4059a066, - 0x405a207a, - 0x405aa08a, - 0x405b20a2, - 0x405ba0b3, - 0x405c20c6, - 0x405ca105, - 0x405d2112, - 0x405da129, - 0x405e2167, - 0x405e8ab1, - 0x405f2188, - 0x405fa195, - 0x406021a3, - 0x4060a1c5, - 0x40612209, - 0x4061a241, - 0x40622258, - 0x4062a269, - 0x4063227a, - 0x4063a28f, - 0x406422a6, - 0x4064a2d2, - 0x406522ed, - 0x4065a304, - 0x4066231c, - 0x4066a346, - 0x40672371, - 0x4067a392, - 0x406823b9, - 0x4068a3da, - 0x4069240c, - 0x4069a43a, - 0x406a245b, - 0x406aa47b, - 0x406b2603, - 0x406ba626, - 0x406c263c, - 0x406ca8b7, - 0x406d28e6, - 0x406da90e, - 0x406e293c, - 0x406ea989, - 0x406f29a8, - 0x406fa9e0, - 0x407029f3, - 0x4070aa10, - 0x40710800, - 0x4071aa22, - 0x40722a35, - 0x4072aa4e, - 0x40732a66, - 0x40739482, - 0x40742a7a, - 0x4074aa94, - 0x40752aa5, - 0x4075aab9, - 0x40762ac7, - 0x40769259, - 0x40772aec, - 0x4077ab0e, - 0x40782b29, - 0x4078ab62, - 0x40792b79, - 0x4079ab8f, - 0x407a2b9b, - 0x407aabae, - 0x407b2bc3, - 0x407babd5, - 0x407c2c06, - 0x407cac0f, - 0x407d23f5, - 0x407d9e61, - 0x407e2b3e, - 0x407ea01a, - 0x407f1c71, - 0x407f9a31, - 0x40801e38, - 0x40809c99, - 0x40811edd, - 0x40819e12, - 0x40822927, - 0x40829a17, - 0x40831ff5, - 0x4083a2b7, - 0x40841cad, - 0x4084a052, - 0x408520d7, - 0x4085a1ed, - 0x40862149, - 0x40869e7b, - 0x4087296d, - 0x4087a21e, - 0x40881a78, - 0x4088a3a5, - 0x40891ac7, - 0x40899a54, - 0x408a265c, - 0x408a9862, - 0x408b2bea, - 0x408ba9bd, - 0x408c20e7, - 0x408c987e, - 0x41f4252e, - 0x41f925c0, - 0x41fe24b3, - 0x41fea6a8, - 0x41ff2799, - 0x42032547, - 0x42082569, - 0x4208a5a5, - 0x42092497, - 0x4209a5df, - 0x420a24ee, - 0x420aa4ce, - 0x420b250e, - 0x420ba587, - 0x420c27b5, - 0x420ca675, - 0x420d268f, - 0x420da6c6, - 0x421226e0, - 0x4217277c, - 0x4217a722, - 0x421c2744, - 0x421f26ff, - 0x422127cc, - 0x4226275f, - 0x422b289b, - 0x422ba849, - 0x422c2883, - 0x422ca808, - 0x422d27e7, - 0x422da868, - 0x422e282e, - 0x422ea954, - 0x4432072b, - 0x4432873a, - 0x44330746, - 0x44338754, - 0x44340767, - 0x44348778, - 0x4435077f, - 0x44358789, - 0x4436079c, - 0x443687b2, - 0x443707c4, - 0x443787d1, - 0x443807e0, - 0x443887e8, - 0x44390800, - 0x4439880e, - 0x443a0821, - 0x48321283, - 0x48329295, - 0x483312ab, - 0x483392c4, - 0x4c3212e9, - 0x4c3292f9, - 0x4c33130c, - 0x4c33932c, - 0x4c3400ac, - 0x4c3480ea, - 0x4c351338, - 0x4c359346, - 0x4c361362, - 0x4c369375, - 0x4c371384, - 0x4c379392, - 0x4c3813a7, - 0x4c3893b3, - 0x4c3913d3, - 0x4c3993fd, - 0x4c3a1416, - 0x4c3a942f, - 0x4c3b05fb, - 0x4c3b9448, - 0x4c3c145a, - 0x4c3c9469, - 0x4c3d1482, - 0x4c3d8c45, - 0x4c3e14db, - 0x4c3e9491, - 0x4c3f14fd, - 0x4c3f9259, - 0x4c4014a7, - 0x4c4092d5, - 0x4c4114cb, - 0x50322e48, - 0x5032ae57, - 0x50332e62, - 0x5033ae72, - 0x50342e8b, - 0x5034aea5, - 0x50352eb3, - 0x5035aec9, - 0x50362edb, - 0x5036aef1, - 0x50372f0a, - 0x5037af1d, - 0x50382f35, - 0x5038af46, - 0x50392f5b, - 0x5039af6f, - 0x503a2f8f, - 0x503aafa5, - 0x503b2fbd, - 0x503bafcf, - 0x503c2feb, - 0x503cb002, - 0x503d301b, - 0x503db031, - 0x503e303e, - 0x503eb054, - 0x503f3066, - 0x503f8382, - 0x50403079, - 0x5040b089, - 0x504130a3, - 0x5041b0b2, - 0x504230cc, - 0x5042b0e9, - 0x504330f9, - 0x5043b109, - 0x50443118, - 0x5044843f, - 0x5045312c, - 0x5045b14a, - 0x5046315d, - 0x5046b173, - 0x50473185, - 0x5047b19a, - 0x504831c0, - 0x5048b1ce, - 0x504931e1, - 0x5049b1f6, - 0x504a320c, - 0x504ab21c, - 0x504b323c, - 0x504bb24f, - 0x504c3272, - 0x504cb2a0, - 0x504d32b2, - 0x504db2cf, - 0x504e32ea, - 0x504eb306, - 0x504f3318, - 0x504fb32f, - 0x5050333e, - 0x505086ef, - 0x50513351, - 0x58320f2b, - 0x68320eed, - 0x68328c6a, - 0x68330c7d, - 0x68338efb, - 0x68340f0b, - 0x683480ea, - 0x6c320ec9, - 0x6c328c34, - 0x6c330ed4, - 0x74320a19, - 0x743280ac, - 0x74330c45, - 0x7832097e, - 0x78328993, - 0x7833099f, - 0x78338083, - 0x783409ae, - 0x783489c3, - 0x783509e2, - 0x78358a04, - 0x78360a19, - 0x78368a2f, - 0x78370a3f, - 0x78378a60, - 0x78380a73, - 0x78388a85, - 0x78390a92, - 0x78398ab1, - 0x783a0ac6, - 0x783a8ad4, - 0x783b0ade, - 0x783b8af2, - 0x783c0b09, - 0x783c8b1e, - 0x783d0b35, - 0x783d8b4a, - 0x783e0aa0, - 0x783e8a52, - 0x7c321185, - }; + const uint32_t kOpenSSLReasonValues[] = { + 0xc320838, + 0xc328852, + 0xc330861, + 0xc338871, + 0xc340880, + 0xc348899, + 0xc3508a5, + 0xc3588c2, + 0xc3608e2, + 0xc3688f0, + 0xc370900, + 0xc37890d, + 0xc38091d, + 0xc388928, + 0xc39093e, + 0xc39894d, + 0xc3a0961, + 0xc3a8845, + 0xc3b00ea, + 0xc3b88d4, + 0x10320845, + 0x10329513, + 0x1033151f, + 0x10339538, + 0x1034154b, + 0x10348eed, + 0x10350c5e, + 0x1035955e, + 0x10361573, + 0x10369586, + 0x103715a5, + 0x103795be, + 0x103815d3, + 0x103895f1, + 0x10391600, + 0x1039961c, + 0x103a1637, + 0x103a9646, + 0x103b1662, + 0x103b967d, + 0x103c1694, + 0x103c80ea, + 0x103d16a5, + 0x103d96b9, + 0x103e16d8, + 0x103e96e7, + 0x103f16fe, + 0x103f9711, + 0x10400c22, + 0x10409724, + 0x10411742, + 0x10419755, + 0x1042176f, + 0x1042977f, + 0x10431793, + 0x104397a9, + 0x104417c1, + 0x104497d6, + 0x104517ea, + 0x104597fc, + 0x104605fb, + 0x1046894d, + 0x10471811, + 0x10479828, + 0x1048183d, + 0x1048984b, + 0x10490e4f, + 0x14320c05, + 0x14328c13, + 0x14330c22, + 0x14338c34, + 0x143400ac, + 0x143480ea, + 0x18320083, + 0x18328f43, + 0x183300ac, + 0x18338f59, + 0x18340f6d, + 0x183480ea, + 0x18350f82, + 0x18358f9a, + 0x18360faf, + 0x18368fc3, + 0x18370fe7, + 0x18378ffd, + 0x18381011, + 0x18389021, + 0x18390a73, + 0x18399031, + 0x183a1059, + 0x183a907f, + 0x183b0c6a, + 0x183b90b4, + 0x183c10c6, + 0x183c90d1, + 0x183d10e1, + 0x183d90f2, + 0x183e1103, + 0x183e9115, + 0x183f113e, + 0x183f9157, + 0x1840116f, + 0x184086d3, + 0x184110a2, + 0x1841906d, + 0x1842108c, + 0x18429046, + 0x20321196, + 0x243211a2, + 0x24328993, + 0x243311b4, + 0x243391c1, + 0x243411ce, + 0x243491e0, + 0x243511ef, + 0x2435920c, + 0x24361219, + 0x24369227, + 0x24371235, + 0x24379243, + 0x2438124c, + 0x24389259, + 0x2439126c, + 0x28320c52, + 0x28328c6a, + 0x28330c22, + 0x28338c7d, + 0x28340c5e, + 0x283480ac, + 0x283500ea, + 0x2c322c30, + 0x2c329283, + 0x2c332c3e, + 0x2c33ac50, + 0x2c342c64, + 0x2c34ac76, + 0x2c352c91, + 0x2c35aca3, + 0x2c362cb6, + 0x2c36832d, + 0x2c372cc3, + 0x2c37acd5, + 0x2c382cfa, + 0x2c38ad11, + 0x2c392d1f, + 0x2c39ad2f, + 0x2c3a2d41, + 0x2c3aad55, + 0x2c3b2d66, + 0x2c3bad85, + 0x2c3c1295, + 0x2c3c92ab, + 0x2c3d2d99, + 0x2c3d92c4, + 0x2c3e2db6, + 0x2c3eadc4, + 0x2c3f2ddc, + 0x2c3fadf4, + 0x2c402e01, + 0x2c409196, + 0x2c412e12, + 0x2c41ae25, + 0x2c42116f, + 0x2c42ae36, + 0x2c430720, + 0x2c43ad77, + 0x2c442ce8, + 0x30320000, + 0x30328015, + 0x3033001f, + 0x30338038, + 0x3034004a, + 0x30348064, + 0x3035006b, + 0x30358083, + 0x30360094, + 0x303680ac, + 0x303700b9, + 0x303780c8, + 0x303800ea, + 0x303880f7, + 0x3039010a, + 0x30398125, + 0x303a013a, + 0x303a814e, + 0x303b0162, + 0x303b8173, + 0x303c018c, + 0x303c81a9, + 0x303d01b7, + 0x303d81cb, + 0x303e01db, + 0x303e81f4, + 0x303f0204, + 0x303f8217, + 0x30400226, + 0x30408232, + 0x30410247, + 0x30418257, + 0x3042026e, + 0x3042827b, + 0x3043028e, + 0x3043829d, + 0x304402b2, + 0x304482d3, + 0x304502e6, + 0x304582f9, + 0x30460312, + 0x3046832d, + 0x3047034a, + 0x30478363, + 0x30480371, + 0x30488382, + 0x30490391, + 0x304983a9, + 0x304a03bb, + 0x304a83cf, + 0x304b03ee, + 0x304b8401, + 0x304c040c, + 0x304c841d, + 0x304d0429, + 0x304d843f, + 0x304e044d, + 0x304e8463, + 0x304f0475, + 0x304f8487, + 0x3050049a, + 0x305084ad, + 0x305104be, + 0x305184ce, + 0x305204e6, + 0x305284fb, + 0x30530513, + 0x30538527, + 0x3054053f, + 0x30548558, + 0x30550571, + 0x3055858e, + 0x30560599, + 0x305685b1, + 0x305705c1, + 0x305785d2, + 0x305805e5, + 0x305885fb, + 0x30590604, + 0x30598619, + 0x305a062c, + 0x305a863b, + 0x305b065b, + 0x305b866a, + 0x305c068b, + 0x305c86a7, + 0x305d06b3, + 0x305d86d3, + 0x305e06ef, + 0x305e8700, + 0x305f0716, + 0x305f8720, + 0x34320b63, + 0x34328b77, + 0x34330b94, + 0x34338ba7, + 0x34340bb6, + 0x34348bef, + 0x34350bd3, + 0x3c320083, + 0x3c328ca7, + 0x3c330cc0, + 0x3c338cdb, + 0x3c340cf8, + 0x3c348d22, + 0x3c350d3d, + 0x3c358d63, + 0x3c360d7c, + 0x3c368d94, + 0x3c370da5, + 0x3c378db3, + 0x3c380dc0, + 0x3c388dd4, + 0x3c390c6a, + 0x3c398de8, + 0x3c3a0dfc, + 0x3c3a890d, + 0x3c3b0e0c, + 0x3c3b8e27, + 0x3c3c0e39, + 0x3c3c8e6c, + 0x3c3d0e76, + 0x3c3d8e8a, + 0x3c3e0e98, + 0x3c3e8ebd, + 0x3c3f0c93, + 0x3c3f8ea6, + 0x3c4000ac, + 0x3c4080ea, + 0x3c410d13, + 0x3c418d52, + 0x3c420e4f, + 0x403218a4, + 0x403298ba, + 0x403318e8, + 0x403398f2, + 0x40341909, + 0x40349927, + 0x40351937, + 0x40359949, + 0x40361956, + 0x40369962, + 0x40371977, + 0x40379989, + 0x40381994, + 0x403899a6, + 0x40390eed, + 0x403999b6, + 0x403a19c9, + 0x403a99ea, + 0x403b19fb, + 0x403b9a0b, + 0x403c0064, + 0x403c8083, + 0x403d1a8f, + 0x403d9aa5, + 0x403e1ab4, + 0x403e9aec, + 0x403f1b06, + 0x403f9b14, + 0x40401b29, + 0x40409b3d, + 0x40411b5a, + 0x40419b75, + 0x40421b8e, + 0x40429ba1, + 0x40431bb5, + 0x40439bcd, + 0x40441be4, + 0x404480ac, + 0x40451bf9, + 0x40459c0b, + 0x40461c2f, + 0x40469c4f, + 0x40471c5d, + 0x40479c84, + 0x40481cc1, + 0x40489cda, + 0x40491cf1, + 0x40499d0b, + 0x404a1d22, + 0x404a9d40, + 0x404b1d58, + 0x404b9d6f, + 0x404c1d85, + 0x404c9d97, + 0x404d1db8, + 0x404d9dda, + 0x404e1dee, + 0x404e9dfb, + 0x404f1e28, + 0x404f9e51, + 0x40501e8c, + 0x40509ea0, + 0x40511ebb, + 0x40521ecb, + 0x40529eef, + 0x40531f07, + 0x40539f1a, + 0x40541f2f, + 0x40549f52, + 0x40551f60, + 0x40559f7d, + 0x40561f8a, + 0x40569fa3, + 0x40571fbb, + 0x40579fce, + 0x40581fe3, + 0x4058a00a, + 0x40592039, + 0x4059a066, + 0x405a207a, + 0x405aa08a, + 0x405b20a2, + 0x405ba0b3, + 0x405c20c6, + 0x405ca105, + 0x405d2112, + 0x405da129, + 0x405e2167, + 0x405e8ab1, + 0x405f2188, + 0x405fa195, + 0x406021a3, + 0x4060a1c5, + 0x40612209, + 0x4061a241, + 0x40622258, + 0x4062a269, + 0x4063227a, + 0x4063a28f, + 0x406422a6, + 0x4064a2d2, + 0x406522ed, + 0x4065a304, + 0x4066231c, + 0x4066a346, + 0x40672371, + 0x4067a392, + 0x406823b9, + 0x4068a3da, + 0x4069240c, + 0x4069a43a, + 0x406a245b, + 0x406aa47b, + 0x406b2603, + 0x406ba626, + 0x406c263c, + 0x406ca8b7, + 0x406d28e6, + 0x406da90e, + 0x406e293c, + 0x406ea989, + 0x406f29a8, + 0x406fa9e0, + 0x407029f3, + 0x4070aa10, + 0x40710800, + 0x4071aa22, + 0x40722a35, + 0x4072aa4e, + 0x40732a66, + 0x40739482, + 0x40742a7a, + 0x4074aa94, + 0x40752aa5, + 0x4075aab9, + 0x40762ac7, + 0x40769259, + 0x40772aec, + 0x4077ab0e, + 0x40782b29, + 0x4078ab62, + 0x40792b79, + 0x4079ab8f, + 0x407a2b9b, + 0x407aabae, + 0x407b2bc3, + 0x407babd5, + 0x407c2c06, + 0x407cac0f, + 0x407d23f5, + 0x407d9e61, + 0x407e2b3e, + 0x407ea01a, + 0x407f1c71, + 0x407f9a31, + 0x40801e38, + 0x40809c99, + 0x40811edd, + 0x40819e12, + 0x40822927, + 0x40829a17, + 0x40831ff5, + 0x4083a2b7, + 0x40841cad, + 0x4084a052, + 0x408520d7, + 0x4085a1ed, + 0x40862149, + 0x40869e7b, + 0x4087296d, + 0x4087a21e, + 0x40881a78, + 0x4088a3a5, + 0x40891ac7, + 0x40899a54, + 0x408a265c, + 0x408a9862, + 0x408b2bea, + 0x408ba9bd, + 0x408c20e7, + 0x408c987e, + 0x41f4252e, + 0x41f925c0, + 0x41fe24b3, + 0x41fea6a8, + 0x41ff2799, + 0x42032547, + 0x42082569, + 0x4208a5a5, + 0x42092497, + 0x4209a5df, + 0x420a24ee, + 0x420aa4ce, + 0x420b250e, + 0x420ba587, + 0x420c27b5, + 0x420ca675, + 0x420d268f, + 0x420da6c6, + 0x421226e0, + 0x4217277c, + 0x4217a722, + 0x421c2744, + 0x421f26ff, + 0x422127cc, + 0x4226275f, + 0x422b289b, + 0x422ba849, + 0x422c2883, + 0x422ca808, + 0x422d27e7, + 0x422da868, + 0x422e282e, + 0x422ea954, + 0x4432072b, + 0x4432873a, + 0x44330746, + 0x44338754, + 0x44340767, + 0x44348778, + 0x4435077f, + 0x44358789, + 0x4436079c, + 0x443687b2, + 0x443707c4, + 0x443787d1, + 0x443807e0, + 0x443887e8, + 0x44390800, + 0x4439880e, + 0x443a0821, + 0x48321283, + 0x48329295, + 0x483312ab, + 0x483392c4, + 0x4c3212e9, + 0x4c3292f9, + 0x4c33130c, + 0x4c33932c, + 0x4c3400ac, + 0x4c3480ea, + 0x4c351338, + 0x4c359346, + 0x4c361362, + 0x4c369375, + 0x4c371384, + 0x4c379392, + 0x4c3813a7, + 0x4c3893b3, + 0x4c3913d3, + 0x4c3993fd, + 0x4c3a1416, + 0x4c3a942f, + 0x4c3b05fb, + 0x4c3b9448, + 0x4c3c145a, + 0x4c3c9469, + 0x4c3d1482, + 0x4c3d8c45, + 0x4c3e14db, + 0x4c3e9491, + 0x4c3f14fd, + 0x4c3f9259, + 0x4c4014a7, + 0x4c4092d5, + 0x4c4114cb, + 0x50322e48, + 0x5032ae57, + 0x50332e62, + 0x5033ae72, + 0x50342e8b, + 0x5034aea5, + 0x50352eb3, + 0x5035aec9, + 0x50362edb, + 0x5036aef1, + 0x50372f0a, + 0x5037af1d, + 0x50382f35, + 0x5038af46, + 0x50392f5b, + 0x5039af6f, + 0x503a2f8f, + 0x503aafa5, + 0x503b2fbd, + 0x503bafcf, + 0x503c2feb, + 0x503cb002, + 0x503d301b, + 0x503db031, + 0x503e303e, + 0x503eb054, + 0x503f3066, + 0x503f8382, + 0x50403079, + 0x5040b089, + 0x504130a3, + 0x5041b0b2, + 0x504230cc, + 0x5042b0e9, + 0x504330f9, + 0x5043b109, + 0x50443118, + 0x5044843f, + 0x5045312c, + 0x5045b14a, + 0x5046315d, + 0x5046b173, + 0x50473185, + 0x5047b19a, + 0x504831c0, + 0x5048b1ce, + 0x504931e1, + 0x5049b1f6, + 0x504a320c, + 0x504ab21c, + 0x504b323c, + 0x504bb24f, + 0x504c3272, + 0x504cb2a0, + 0x504d32b2, + 0x504db2cf, + 0x504e32ea, + 0x504eb306, + 0x504f3318, + 0x504fb32f, + 0x5050333e, + 0x505086ef, + 0x50513351, + 0x58320f2b, + 0x68320eed, + 0x68328c6a, + 0x68330c7d, + 0x68338efb, + 0x68340f0b, + 0x683480ea, + 0x6c320ec9, + 0x6c328c34, + 0x6c330ed4, + 0x74320a19, + 0x743280ac, + 0x74330c45, + 0x7832097e, + 0x78328993, + 0x7833099f, + 0x78338083, + 0x783409ae, + 0x783489c3, + 0x783509e2, + 0x78358a04, + 0x78360a19, + 0x78368a2f, + 0x78370a3f, + 0x78378a60, + 0x78380a73, + 0x78388a85, + 0x78390a92, + 0x78398ab1, + 0x783a0ac6, + 0x783a8ad4, + 0x783b0ade, + 0x783b8af2, + 0x783c0b09, + 0x783c8b1e, + 0x783d0b35, + 0x783d8b4a, + 0x783e0aa0, + 0x783e8a52, + 0x7c321185, + }; - const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); + const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); - const char kOpenSSLReasonStringData[] = - "ASN1_LENGTH_MISMATCH\\0" - "AUX_ERROR\\0" - "BAD_GET_ASN1_OBJECT_CALL\\0" - "BAD_OBJECT_HEADER\\0" - "BMPSTRING_IS_WRONG_LENGTH\\0" - "BN_LIB\\0" - "BOOLEAN_IS_WRONG_LENGTH\\0" - "BUFFER_TOO_SMALL\\0" - "CONTEXT_NOT_INITIALISED\\0" - "DECODE_ERROR\\0" - "DEPTH_EXCEEDED\\0" - "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\\0" - "ENCODE_ERROR\\0" - "ERROR_GETTING_TIME\\0" - "EXPECTING_AN_ASN1_SEQUENCE\\0" - "EXPECTING_AN_INTEGER\\0" - "EXPECTING_AN_OBJECT\\0" - "EXPECTING_A_BOOLEAN\\0" - "EXPECTING_A_TIME\\0" - "EXPLICIT_LENGTH_MISMATCH\\0" - "EXPLICIT_TAG_NOT_CONSTRUCTED\\0" - "FIELD_MISSING\\0" - "FIRST_NUM_TOO_LARGE\\0" - "HEADER_TOO_LONG\\0" - "ILLEGAL_BITSTRING_FORMAT\\0" - "ILLEGAL_BOOLEAN\\0" - "ILLEGAL_CHARACTERS\\0" - "ILLEGAL_FORMAT\\0" - "ILLEGAL_HEX\\0" - "ILLEGAL_IMPLICIT_TAG\\0" - "ILLEGAL_INTEGER\\0" - "ILLEGAL_NESTED_TAGGING\\0" - "ILLEGAL_NULL\\0" - "ILLEGAL_NULL_VALUE\\0" - "ILLEGAL_OBJECT\\0" - "ILLEGAL_OPTIONAL_ANY\\0" - "ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE\\0" - "ILLEGAL_TAGGED_ANY\\0" - "ILLEGAL_TIME_VALUE\\0" - "INTEGER_NOT_ASCII_FORMAT\\0" - "INTEGER_TOO_LARGE_FOR_LONG\\0" - "INVALID_BIT_STRING_BITS_LEFT\\0" - "INVALID_BMPSTRING_LENGTH\\0" - "INVALID_DIGIT\\0" - "INVALID_MODIFIER\\0" - "INVALID_NUMBER\\0" - "INVALID_OBJECT_ENCODING\\0" - "INVALID_SEPARATOR\\0" - "INVALID_TIME_FORMAT\\0" - "INVALID_UNIVERSALSTRING_LENGTH\\0" - "INVALID_UTF8STRING\\0" - "LIST_ERROR\\0" - "MISSING_ASN1_EOS\\0" - "MISSING_EOC\\0" - "MISSING_SECOND_NUMBER\\0" - "MISSING_VALUE\\0" - "MSTRING_NOT_UNIVERSAL\\0" - "MSTRING_WRONG_TAG\\0" - "NESTED_ASN1_ERROR\\0" - "NESTED_ASN1_STRING\\0" - "NON_HEX_CHARACTERS\\0" - "NOT_ASCII_FORMAT\\0" - "NOT_ENOUGH_DATA\\0" - "NO_MATCHING_CHOICE_TYPE\\0" - "NULL_IS_WRONG_LENGTH\\0" - "OBJECT_NOT_ASCII_FORMAT\\0" - "ODD_NUMBER_OF_CHARS\\0" - "SECOND_NUMBER_TOO_LARGE\\0" - "SEQUENCE_LENGTH_MISMATCH\\0" - "SEQUENCE_NOT_CONSTRUCTED\\0" - "SEQUENCE_OR_SET_NEEDS_CONFIG\\0" - "SHORT_LINE\\0" - "STREAMING_NOT_SUPPORTED\\0" - "STRING_TOO_LONG\\0" - "STRING_TOO_SHORT\\0" - "TAG_VALUE_TOO_HIGH\\0" - "TIME_NOT_ASCII_FORMAT\\0" - "TOO_LONG\\0" - "TYPE_NOT_CONSTRUCTED\\0" - "TYPE_NOT_PRIMITIVE\\0" - "UNEXPECTED_EOC\\0" - "UNIVERSALSTRING_IS_WRONG_LENGTH\\0" - "UNKNOWN_FORMAT\\0" - "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\\0" - "UNKNOWN_SIGNATURE_ALGORITHM\\0" - "UNKNOWN_TAG\\0" - "UNSUPPORTED_ANY_DEFINED_BY_TYPE\\0" - "UNSUPPORTED_PUBLIC_KEY_TYPE\\0" - "UNSUPPORTED_TYPE\\0" - "WRONG_PUBLIC_KEY_TYPE\\0" - "WRONG_TAG\\0" - "WRONG_TYPE\\0" - "BAD_FOPEN_MODE\\0" - "BROKEN_PIPE\\0" - "CONNECT_ERROR\\0" - "ERROR_SETTING_NBIO\\0" - "INVALID_ARGUMENT\\0" - "IN_USE\\0" - "KEEPALIVE\\0" - "NBIO_CONNECT_ERROR\\0" - "NO_HOSTNAME_SPECIFIED\\0" - "NO_PORT_SPECIFIED\\0" - "NO_SUCH_FILE\\0" - "NULL_PARAMETER\\0" - "SYS_LIB\\0" - "UNABLE_TO_CREATE_SOCKET\\0" - "UNINITIALIZED\\0" - "UNSUPPORTED_METHOD\\0" - "WRITE_TO_READ_ONLY_BIO\\0" - "ARG2_LT_ARG3\\0" - "BAD_ENCODING\\0" - "BAD_RECIPROCAL\\0" - "BIGNUM_TOO_LONG\\0" - "BITS_TOO_SMALL\\0" - "CALLED_WITH_EVEN_MODULUS\\0" - "DIV_BY_ZERO\\0" - "EXPAND_ON_STATIC_BIGNUM_DATA\\0" - "INPUT_NOT_REDUCED\\0" - "INVALID_INPUT\\0" - "INVALID_RANGE\\0" - "NEGATIVE_NUMBER\\0" - "NOT_A_SQUARE\\0" - "NOT_INITIALIZED\\0" - "NO_INVERSE\\0" - "PRIVATE_KEY_TOO_LARGE\\0" - "P_IS_NOT_PRIME\\0" - "TOO_MANY_ITERATIONS\\0" - "TOO_MANY_TEMPORARY_VARIABLES\\0" - "AES_KEY_SETUP_FAILED\\0" - "BAD_DECRYPT\\0" - "BAD_KEY_LENGTH\\0" - "CTRL_NOT_IMPLEMENTED\\0" - "CTRL_OPERATION_NOT_IMPLEMENTED\\0" - "DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH\\0" - "INITIALIZATION_ERROR\\0" - "INPUT_NOT_INITIALIZED\\0" - "INVALID_AD_SIZE\\0" - "INVALID_KEY_LENGTH\\0" - "INVALID_NONCE\\0" - "INVALID_NONCE_SIZE\\0" - "INVALID_OPERATION\\0" - "IV_TOO_LARGE\\0" - "NO_CIPHER_SET\\0" - "NO_DIRECTION_SET\\0" - "OUTPUT_ALIASES_INPUT\\0" - "TAG_TOO_LARGE\\0" - "TOO_LARGE\\0" - "UNSUPPORTED_AD_SIZE\\0" - "UNSUPPORTED_INPUT_SIZE\\0" - "UNSUPPORTED_KEY_SIZE\\0" - "UNSUPPORTED_NONCE_SIZE\\0" - "UNSUPPORTED_TAG_SIZE\\0" - "WRONG_FINAL_BLOCK_LENGTH\\0" - "LIST_CANNOT_BE_NULL\\0" - "MISSING_CLOSE_SQUARE_BRACKET\\0" - "MISSING_EQUAL_SIGN\\0" - "NO_CLOSE_BRACE\\0" - "UNABLE_TO_CREATE_NEW_SECTION\\0" - "VARIABLE_EXPANSION_TOO_LONG\\0" - "VARIABLE_HAS_NO_VALUE\\0" - "BAD_GENERATOR\\0" - "INVALID_PUBKEY\\0" - "MODULUS_TOO_LARGE\\0" - "NO_PRIVATE_VALUE\\0" - "UNKNOWN_HASH\\0" - "BAD_Q_VALUE\\0" - "BAD_VERSION\\0" - "MISSING_PARAMETERS\\0" - "NEED_NEW_SETUP_VALUES\\0" - "BIGNUM_OUT_OF_RANGE\\0" - "COORDINATES_OUT_OF_RANGE\\0" - "D2I_ECPKPARAMETERS_FAILURE\\0" - "EC_GROUP_NEW_BY_NAME_FAILURE\\0" - "GROUP2PKPARAMETERS_FAILURE\\0" - "GROUP_MISMATCH\\0" - "I2D_ECPKPARAMETERS_FAILURE\\0" - "INCOMPATIBLE_OBJECTS\\0" - "INVALID_COFACTOR\\0" - "INVALID_COMPRESSED_POINT\\0" - "INVALID_COMPRESSION_BIT\\0" - "INVALID_ENCODING\\0" - "INVALID_FIELD\\0" - "INVALID_FORM\\0" - "INVALID_GROUP_ORDER\\0" - "INVALID_PRIVATE_KEY\\0" - "MISSING_PRIVATE_KEY\\0" - "NON_NAMED_CURVE\\0" - "PKPARAMETERS2GROUP_FAILURE\\0" - "POINT_AT_INFINITY\\0" - "POINT_IS_NOT_ON_CURVE\\0" - "PUBLIC_KEY_VALIDATION_FAILED\\0" - "SLOT_FULL\\0" - "UNDEFINED_GENERATOR\\0" - "UNKNOWN_GROUP\\0" - "UNKNOWN_ORDER\\0" - "WRONG_CURVE_PARAMETERS\\0" - "WRONG_ORDER\\0" - "KDF_FAILED\\0" - "POINT_ARITHMETIC_FAILURE\\0" - "BAD_SIGNATURE\\0" - "NOT_IMPLEMENTED\\0" - "RANDOM_NUMBER_GENERATION_FAILED\\0" - "OPERATION_NOT_SUPPORTED\\0" - "COMMAND_NOT_SUPPORTED\\0" - "DIFFERENT_KEY_TYPES\\0" - "DIFFERENT_PARAMETERS\\0" - "EXPECTING_AN_EC_KEY_KEY\\0" - "EXPECTING_AN_RSA_KEY\\0" - "EXPECTING_A_DSA_KEY\\0" - "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\\0" - "INVALID_DIGEST_LENGTH\\0" - "INVALID_DIGEST_TYPE\\0" - "INVALID_KEYBITS\\0" - "INVALID_MGF1_MD\\0" - "INVALID_PADDING_MODE\\0" - "INVALID_PARAMETERS\\0" - "INVALID_PSS_SALTLEN\\0" - "INVALID_SIGNATURE\\0" - "KEYS_NOT_SET\\0" - "MEMORY_LIMIT_EXCEEDED\\0" - "NOT_A_PRIVATE_KEY\\0" - "NO_DEFAULT_DIGEST\\0" - "NO_KEY_SET\\0" - "NO_MDC2_SUPPORT\\0" - "NO_NID_FOR_CURVE\\0" - "NO_OPERATION_SET\\0" - "NO_PARAMETERS_SET\\0" - "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\\0" - "OPERATON_NOT_INITIALIZED\\0" - "UNKNOWN_PUBLIC_KEY_TYPE\\0" - "UNSUPPORTED_ALGORITHM\\0" - "OUTPUT_TOO_LARGE\\0" - "UNKNOWN_NID\\0" - "BAD_BASE64_DECODE\\0" - "BAD_END_LINE\\0" - "BAD_IV_CHARS\\0" - "BAD_PASSWORD_READ\\0" - "CIPHER_IS_NULL\\0" - "ERROR_CONVERTING_PRIVATE_KEY\\0" - "NOT_DEK_INFO\\0" - "NOT_ENCRYPTED\\0" - "NOT_PROC_TYPE\\0" - "NO_START_LINE\\0" - "READ_KEY\\0" - "SHORT_HEADER\\0" - "UNSUPPORTED_CIPHER\\0" - "UNSUPPORTED_ENCRYPTION\\0" - "BAD_PKCS7_VERSION\\0" - "NOT_PKCS7_SIGNED_DATA\\0" - "NO_CERTIFICATES_INCLUDED\\0" - "NO_CRLS_INCLUDED\\0" - "BAD_ITERATION_COUNT\\0" - "BAD_PKCS12_DATA\\0" - "BAD_PKCS12_VERSION\\0" - "CIPHER_HAS_NO_OBJECT_IDENTIFIER\\0" - "CRYPT_ERROR\\0" - "ENCRYPT_ERROR\\0" - "ERROR_SETTING_CIPHER_PARAMS\\0" - "INCORRECT_PASSWORD\\0" - "KEYGEN_FAILURE\\0" - "KEY_GEN_ERROR\\0" - "METHOD_NOT_SUPPORTED\\0" - "MISSING_MAC\\0" - "MULTIPLE_PRIVATE_KEYS_IN_PKCS12\\0" - "PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED\\0" - "PKCS12_TOO_DEEPLY_NESTED\\0" - "PRIVATE_KEY_DECODE_ERROR\\0" - "PRIVATE_KEY_ENCODE_ERROR\\0" - "UNKNOWN_ALGORITHM\\0" - "UNKNOWN_CIPHER\\0" - "UNKNOWN_CIPHER_ALGORITHM\\0" - "UNKNOWN_DIGEST\\0" - "UNSUPPORTED_KEYLENGTH\\0" - "UNSUPPORTED_KEY_DERIVATION_FUNCTION\\0" - "UNSUPPORTED_PRF\\0" - "UNSUPPORTED_PRIVATE_KEY_ALGORITHM\\0" - "UNSUPPORTED_SALT_TYPE\\0" - "BAD_E_VALUE\\0" - "BAD_FIXED_HEADER_DECRYPT\\0" - "BAD_PAD_BYTE_COUNT\\0" - "BAD_RSA_PARAMETERS\\0" - "BLOCK_TYPE_IS_NOT_01\\0" - "BN_NOT_INITIALIZED\\0" - "CANNOT_RECOVER_MULTI_PRIME_KEY\\0" - "CRT_PARAMS_ALREADY_GIVEN\\0" - "CRT_VALUES_INCORRECT\\0" - "DATA_LEN_NOT_EQUAL_TO_MOD_LEN\\0" - "DATA_TOO_LARGE\\0" - "DATA_TOO_LARGE_FOR_KEY_SIZE\\0" - "DATA_TOO_LARGE_FOR_MODULUS\\0" - "DATA_TOO_SMALL\\0" - "DATA_TOO_SMALL_FOR_KEY_SIZE\\0" - "DIGEST_TOO_BIG_FOR_RSA_KEY\\0" - "D_E_NOT_CONGRUENT_TO_1\\0" - "EMPTY_PUBLIC_KEY\\0" - "FIRST_OCTET_INVALID\\0" - "INCONSISTENT_SET_OF_CRT_VALUES\\0" - "INTERNAL_ERROR\\0" - "INVALID_MESSAGE_LENGTH\\0" - "KEY_SIZE_TOO_SMALL\\0" - "LAST_OCTET_INVALID\\0" - "MUST_HAVE_AT_LEAST_TWO_PRIMES\\0" - "NO_PUBLIC_EXPONENT\\0" - "NULL_BEFORE_BLOCK_MISSING\\0" - "N_NOT_EQUAL_P_Q\\0" - "OAEP_DECODING_ERROR\\0" - "ONLY_ONE_OF_P_Q_GIVEN\\0" - "OUTPUT_BUFFER_TOO_SMALL\\0" - "PADDING_CHECK_FAILED\\0" - "PKCS_DECODING_ERROR\\0" - "SLEN_CHECK_FAILED\\0" - "SLEN_RECOVERY_FAILED\\0" - "UNKNOWN_ALGORITHM_TYPE\\0" - "UNKNOWN_PADDING_TYPE\\0" - "VALUE_MISSING\\0" - "WRONG_SIGNATURE_LENGTH\\0" - "ALPN_MISMATCH_ON_EARLY_DATA\\0" - "APPLICATION_DATA_INSTEAD_OF_HANDSHAKE\\0" - "APP_DATA_IN_HANDSHAKE\\0" - "ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT\\0" - "BAD_ALERT\\0" - "BAD_CHANGE_CIPHER_SPEC\\0" - "BAD_DATA_RETURNED_BY_CALLBACK\\0" - "BAD_DH_P_LENGTH\\0" - "BAD_DIGEST_LENGTH\\0" - "BAD_ECC_CERT\\0" - "BAD_ECPOINT\\0" - "BAD_HANDSHAKE_RECORD\\0" - "BAD_HELLO_REQUEST\\0" - "BAD_LENGTH\\0" - "BAD_PACKET_LENGTH\\0" - "BAD_RSA_ENCRYPT\\0" - "BAD_SRTP_MKI_VALUE\\0" - "BAD_SRTP_PROTECTION_PROFILE_LIST\\0" - "BAD_SSL_FILETYPE\\0" - "BAD_WRITE_RETRY\\0" - "BIO_NOT_SET\\0" - "BLOCK_CIPHER_PAD_IS_WRONG\\0" - "BUFFERED_MESSAGES_ON_CIPHER_CHANGE\\0" - "CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD\\0" - "CANNOT_PARSE_LEAF_CERT\\0" - "CA_DN_LENGTH_MISMATCH\\0" - "CA_DN_TOO_LONG\\0" - "CCS_RECEIVED_EARLY\\0" - "CERTIFICATE_AND_PRIVATE_KEY_MISMATCH\\0" - "CERTIFICATE_VERIFY_FAILED\\0" - "CERT_CB_ERROR\\0" - "CERT_LENGTH_MISMATCH\\0" - "CHANNEL_ID_NOT_P256\\0" - "CHANNEL_ID_SIGNATURE_INVALID\\0" - "CIPHER_OR_HASH_UNAVAILABLE\\0" - "CLIENTHELLO_PARSE_FAILED\\0" - "CLIENTHELLO_TLSEXT\\0" - "CONNECTION_REJECTED\\0" - "CONNECTION_TYPE_NOT_SET\\0" - "CUSTOM_EXTENSION_ERROR\\0" - "DATA_LENGTH_TOO_LONG\\0" - "DECRYPTION_FAILED\\0" - "DECRYPTION_FAILED_OR_BAD_RECORD_MAC\\0" - "DH_PUBLIC_VALUE_LENGTH_IS_WRONG\\0" - "DH_P_TOO_LONG\\0" - "DIGEST_CHECK_FAILED\\0" - "DOWNGRADE_DETECTED\\0" - "DTLS_MESSAGE_TOO_BIG\\0" - "DUPLICATE_EXTENSION\\0" - "DUPLICATE_KEY_SHARE\\0" - "ECC_CERT_NOT_FOR_SIGNING\\0" - "EMS_STATE_INCONSISTENT\\0" - "ENCRYPTED_LENGTH_TOO_LONG\\0" - "ERROR_ADDING_EXTENSION\\0" - "ERROR_IN_RECEIVED_CIPHER_LIST\\0" - "ERROR_PARSING_EXTENSION\\0" - "EXCESSIVE_MESSAGE_SIZE\\0" - "EXTRA_DATA_IN_MESSAGE\\0" - "FRAGMENT_MISMATCH\\0" - "GOT_NEXT_PROTO_WITHOUT_EXTENSION\\0" - "HANDSHAKE_FAILURE_ON_CLIENT_HELLO\\0" - "HTTPS_PROXY_REQUEST\\0" - "HTTP_REQUEST\\0" - "INAPPROPRIATE_FALLBACK\\0" - "INVALID_ALPN_PROTOCOL\\0" - "INVALID_COMMAND\\0" - "INVALID_COMPRESSION_LIST\\0" - "INVALID_MESSAGE\\0" - "INVALID_OUTER_RECORD_TYPE\\0" - "INVALID_SCT_LIST\\0" - "INVALID_SSL_SESSION\\0" - "INVALID_TICKET_KEYS_LENGTH\\0" - "LENGTH_MISMATCH\\0" - "MISSING_EXTENSION\\0" - "MISSING_KEY_SHARE\\0" - "MISSING_RSA_CERTIFICATE\\0" - "MISSING_TMP_DH_KEY\\0" - "MISSING_TMP_ECDH_KEY\\0" - "MIXED_SPECIAL_OPERATOR_WITH_GROUPS\\0" - "MTU_TOO_SMALL\\0" - "NEGOTIATED_BOTH_NPN_AND_ALPN\\0" - "NESTED_GROUP\\0" - "NO_CERTIFICATES_RETURNED\\0" - "NO_CERTIFICATE_ASSIGNED\\0" - "NO_CERTIFICATE_SET\\0" - "NO_CIPHERS_AVAILABLE\\0" - "NO_CIPHERS_PASSED\\0" - "NO_CIPHERS_SPECIFIED\\0" - "NO_CIPHER_MATCH\\0" - "NO_COMMON_SIGNATURE_ALGORITHMS\\0" - "NO_COMPRESSION_SPECIFIED\\0" - "NO_GROUPS_SPECIFIED\\0" - "NO_METHOD_SPECIFIED\\0" - "NO_P256_SUPPORT\\0" - "NO_PRIVATE_KEY_ASSIGNED\\0" - "NO_RENEGOTIATION\\0" - "NO_REQUIRED_DIGEST\\0" - "NO_SHARED_CIPHER\\0" - "NO_SHARED_GROUP\\0" - "NO_SUPPORTED_VERSIONS_ENABLED\\0" - "NULL_SSL_CTX\\0" - "NULL_SSL_METHOD_PASSED\\0" - "OLD_SESSION_CIPHER_NOT_RETURNED\\0" - "OLD_SESSION_PRF_HASH_MISMATCH\\0" - "OLD_SESSION_VERSION_NOT_RETURNED\\0" - "PARSE_TLSEXT\\0" - "PATH_TOO_LONG\\0" - "PEER_DID_NOT_RETURN_A_CERTIFICATE\\0" - "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\\0" - "PRE_SHARED_KEY_MUST_BE_LAST\\0" - "PROTOCOL_IS_SHUTDOWN\\0" - "PSK_IDENTITY_BINDER_COUNT_MISMATCH\\0" - "PSK_IDENTITY_NOT_FOUND\\0" - "PSK_NO_CLIENT_CB\\0" - "PSK_NO_SERVER_CB\\0" - "READ_TIMEOUT_EXPIRED\\0" - "RECORD_LENGTH_MISMATCH\\0" - "RECORD_TOO_LARGE\\0" - "RENEGOTIATION_EMS_MISMATCH\\0" - "RENEGOTIATION_ENCODING_ERR\\0" - "RENEGOTIATION_MISMATCH\\0" - "REQUIRED_CIPHER_MISSING\\0" - "RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION\\0" - "RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION\\0" - "SCSV_RECEIVED_WHEN_RENEGOTIATING\\0" - "SERVERHELLO_TLSEXT\\0" - "SERVER_CERT_CHANGED\\0" - "SESSION_ID_CONTEXT_UNINITIALIZED\\0" - "SESSION_MAY_NOT_BE_CREATED\\0" - "SHUTDOWN_WHILE_IN_INIT\\0" - "SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER\\0" - "SRTP_COULD_NOT_ALLOCATE_PROFILES\\0" - "SRTP_UNKNOWN_PROTECTION_PROFILE\\0" - "SSL3_EXT_INVALID_SERVERNAME\\0" - "SSLV3_ALERT_BAD_CERTIFICATE\\0" - "SSLV3_ALERT_BAD_RECORD_MAC\\0" - "SSLV3_ALERT_CERTIFICATE_EXPIRED\\0" - "SSLV3_ALERT_CERTIFICATE_REVOKED\\0" - "SSLV3_ALERT_CERTIFICATE_UNKNOWN\\0" - "SSLV3_ALERT_CLOSE_NOTIFY\\0" - "SSLV3_ALERT_DECOMPRESSION_FAILURE\\0" - "SSLV3_ALERT_HANDSHAKE_FAILURE\\0" - "SSLV3_ALERT_ILLEGAL_PARAMETER\\0" - "SSLV3_ALERT_NO_CERTIFICATE\\0" - "SSLV3_ALERT_UNEXPECTED_MESSAGE\\0" - "SSLV3_ALERT_UNSUPPORTED_CERTIFICATE\\0" - "SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION\\0" - "SSL_HANDSHAKE_FAILURE\\0" - "SSL_SESSION_ID_CONTEXT_TOO_LONG\\0" - "TICKET_ENCRYPTION_FAILED\\0" - "TLSV1_ALERT_ACCESS_DENIED\\0" - "TLSV1_ALERT_DECODE_ERROR\\0" - "TLSV1_ALERT_DECRYPTION_FAILED\\0" - "TLSV1_ALERT_DECRYPT_ERROR\\0" - "TLSV1_ALERT_EXPORT_RESTRICTION\\0" - "TLSV1_ALERT_INAPPROPRIATE_FALLBACK\\0" - "TLSV1_ALERT_INSUFFICIENT_SECURITY\\0" - "TLSV1_ALERT_INTERNAL_ERROR\\0" - "TLSV1_ALERT_NO_RENEGOTIATION\\0" - "TLSV1_ALERT_PROTOCOL_VERSION\\0" - "TLSV1_ALERT_RECORD_OVERFLOW\\0" - "TLSV1_ALERT_UNKNOWN_CA\\0" - "TLSV1_ALERT_USER_CANCELLED\\0" - "TLSV1_BAD_CERTIFICATE_HASH_VALUE\\0" - "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\\0" - "TLSV1_CERTIFICATE_REQUIRED\\0" - "TLSV1_CERTIFICATE_UNOBTAINABLE\\0" - "TLSV1_UNKNOWN_PSK_IDENTITY\\0" - "TLSV1_UNRECOGNIZED_NAME\\0" - "TLSV1_UNSUPPORTED_EXTENSION\\0" - "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\\0" - "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG\\0" - "TOO_MANY_EMPTY_FRAGMENTS\\0" - "TOO_MANY_KEY_UPDATES\\0" - "TOO_MANY_WARNING_ALERTS\\0" - "TOO_MUCH_READ_EARLY_DATA\\0" - "TOO_MUCH_SKIPPED_EARLY_DATA\\0" - "UNABLE_TO_FIND_ECDH_PARAMETERS\\0" - "UNEXPECTED_EXTENSION\\0" - "UNEXPECTED_EXTENSION_ON_EARLY_DATA\\0" - "UNEXPECTED_MESSAGE\\0" - "UNEXPECTED_OPERATOR_IN_GROUP\\0" - "UNEXPECTED_RECORD\\0" - "UNKNOWN_ALERT_TYPE\\0" - "UNKNOWN_CERTIFICATE_TYPE\\0" - "UNKNOWN_CIPHER_RETURNED\\0" - "UNKNOWN_CIPHER_TYPE\\0" - "UNKNOWN_KEY_EXCHANGE_TYPE\\0" - "UNKNOWN_PROTOCOL\\0" - "UNKNOWN_SSL_VERSION\\0" - "UNKNOWN_STATE\\0" - "UNSAFE_LEGACY_RENEGOTIATION_DISABLED\\0" - "UNSUPPORTED_COMPRESSION_ALGORITHM\\0" - "UNSUPPORTED_ELLIPTIC_CURVE\\0" - "UNSUPPORTED_PROTOCOL\\0" - "UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY\\0" - "WRONG_CERTIFICATE_TYPE\\0" - "WRONG_CIPHER_RETURNED\\0" - "WRONG_CURVE\\0" - "WRONG_MESSAGE_TYPE\\0" - "WRONG_SIGNATURE_TYPE\\0" - "WRONG_SSL_VERSION\\0" - "WRONG_VERSION_NUMBER\\0" - "WRONG_VERSION_ON_EARLY_DATA\\0" - "X509_LIB\\0" - "X509_VERIFICATION_SETUP_PROBLEMS\\0" - "AKID_MISMATCH\\0" - "BAD_X509_FILETYPE\\0" - "BASE64_DECODE_ERROR\\0" - "CANT_CHECK_DH_KEY\\0" - "CERT_ALREADY_IN_HASH_TABLE\\0" - "CRL_ALREADY_DELTA\\0" - "CRL_VERIFY_FAILURE\\0" - "IDP_MISMATCH\\0" - "INVALID_DIRECTORY\\0" - "INVALID_FIELD_NAME\\0" - "INVALID_PARAMETER\\0" - "INVALID_PSS_PARAMETERS\\0" - "INVALID_TRUST\\0" - "ISSUER_MISMATCH\\0" - "KEY_TYPE_MISMATCH\\0" - "KEY_VALUES_MISMATCH\\0" - "LOADING_CERT_DIR\\0" - "LOADING_DEFAULTS\\0" - "NAME_TOO_LONG\\0" - "NEWER_CRL_NOT_NEWER\\0" - "NO_CERT_SET_FOR_US_TO_VERIFY\\0" - "NO_CRL_NUMBER\\0" - "PUBLIC_KEY_DECODE_ERROR\\0" - "PUBLIC_KEY_ENCODE_ERROR\\0" - "SHOULD_RETRY\\0" - "UNKNOWN_KEY_TYPE\\0" - "UNKNOWN_PURPOSE_ID\\0" - "UNKNOWN_TRUST_ID\\0" - "WRONG_LOOKUP_TYPE\\0" - "BAD_IP_ADDRESS\\0" - "BAD_OBJECT\\0" - "BN_DEC2BN_ERROR\\0" - "BN_TO_ASN1_INTEGER_ERROR\\0" - "CANNOT_FIND_FREE_FUNCTION\\0" - "DIRNAME_ERROR\\0" - "DISTPOINT_ALREADY_SET\\0" - "DUPLICATE_ZONE_ID\\0" - "ERROR_CONVERTING_ZONE\\0" - "ERROR_CREATING_EXTENSION\\0" - "ERROR_IN_EXTENSION\\0" - "EXPECTED_A_SECTION_NAME\\0" - "EXTENSION_EXISTS\\0" - "EXTENSION_NAME_ERROR\\0" - "EXTENSION_NOT_FOUND\\0" - "EXTENSION_SETTING_NOT_SUPPORTED\\0" - "EXTENSION_VALUE_ERROR\\0" - "ILLEGAL_EMPTY_EXTENSION\\0" - "ILLEGAL_HEX_DIGIT\\0" - "INCORRECT_POLICY_SYNTAX_TAG\\0" - "INVALID_BOOLEAN_STRING\\0" - "INVALID_EXTENSION_STRING\\0" - "INVALID_MULTIPLE_RDNS\\0" - "INVALID_NAME\\0" - "INVALID_NULL_ARGUMENT\\0" - "INVALID_NULL_NAME\\0" - "INVALID_NULL_VALUE\\0" - "INVALID_NUMBERS\\0" - "INVALID_OBJECT_IDENTIFIER\\0" - "INVALID_OPTION\\0" - "INVALID_POLICY_IDENTIFIER\\0" - "INVALID_PROXY_POLICY_SETTING\\0" - "INVALID_PURPOSE\\0" - "INVALID_SECTION\\0" - "INVALID_SYNTAX\\0" - "ISSUER_DECODE_ERROR\\0" - "NEED_ORGANIZATION_AND_NUMBERS\\0" - "NO_CONFIG_DATABASE\\0" - "NO_ISSUER_CERTIFICATE\\0" - "NO_ISSUER_DETAILS\\0" - "NO_POLICY_IDENTIFIER\\0" - "NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED\\0" - "NO_PUBLIC_KEY\\0" - "NO_SUBJECT_DETAILS\\0" - "ODD_NUMBER_OF_DIGITS\\0" - "OPERATION_NOT_DEFINED\\0" - "OTHERNAME_ERROR\\0" - "POLICY_LANGUAGE_ALREADY_DEFINED\\0" - "POLICY_PATH_LENGTH\\0" - "POLICY_PATH_LENGTH_ALREADY_DEFINED\\0" - "POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY\\0" - "SECTION_NOT_FOUND\\0" - "UNABLE_TO_GET_ISSUER_DETAILS\\0" - "UNABLE_TO_GET_ISSUER_KEYID\\0" - "UNKNOWN_BIT_STRING_ARGUMENT\\0" - "UNKNOWN_EXTENSION\\0" - "UNKNOWN_EXTENSION_NAME\\0" - "UNKNOWN_OPTION\\0" - "UNSUPPORTED_OPTION\\0" - "USER_TOO_LONG\\0" - ""; - EOF + const char kOpenSSLReasonStringData[] = + "ASN1_LENGTH_MISMATCH\\0" + "AUX_ERROR\\0" + "BAD_GET_ASN1_OBJECT_CALL\\0" + "BAD_OBJECT_HEADER\\0" + "BMPSTRING_IS_WRONG_LENGTH\\0" + "BN_LIB\\0" + "BOOLEAN_IS_WRONG_LENGTH\\0" + "BUFFER_TOO_SMALL\\0" + "CONTEXT_NOT_INITIALISED\\0" + "DECODE_ERROR\\0" + "DEPTH_EXCEEDED\\0" + "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\\0" + "ENCODE_ERROR\\0" + "ERROR_GETTING_TIME\\0" + "EXPECTING_AN_ASN1_SEQUENCE\\0" + "EXPECTING_AN_INTEGER\\0" + "EXPECTING_AN_OBJECT\\0" + "EXPECTING_A_BOOLEAN\\0" + "EXPECTING_A_TIME\\0" + "EXPLICIT_LENGTH_MISMATCH\\0" + "EXPLICIT_TAG_NOT_CONSTRUCTED\\0" + "FIELD_MISSING\\0" + "FIRST_NUM_TOO_LARGE\\0" + "HEADER_TOO_LONG\\0" + "ILLEGAL_BITSTRING_FORMAT\\0" + "ILLEGAL_BOOLEAN\\0" + "ILLEGAL_CHARACTERS\\0" + "ILLEGAL_FORMAT\\0" + "ILLEGAL_HEX\\0" + "ILLEGAL_IMPLICIT_TAG\\0" + "ILLEGAL_INTEGER\\0" + "ILLEGAL_NESTED_TAGGING\\0" + "ILLEGAL_NULL\\0" + "ILLEGAL_NULL_VALUE\\0" + "ILLEGAL_OBJECT\\0" + "ILLEGAL_OPTIONAL_ANY\\0" + "ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE\\0" + "ILLEGAL_TAGGED_ANY\\0" + "ILLEGAL_TIME_VALUE\\0" + "INTEGER_NOT_ASCII_FORMAT\\0" + "INTEGER_TOO_LARGE_FOR_LONG\\0" + "INVALID_BIT_STRING_BITS_LEFT\\0" + "INVALID_BMPSTRING_LENGTH\\0" + "INVALID_DIGIT\\0" + "INVALID_MODIFIER\\0" + "INVALID_NUMBER\\0" + "INVALID_OBJECT_ENCODING\\0" + "INVALID_SEPARATOR\\0" + "INVALID_TIME_FORMAT\\0" + "INVALID_UNIVERSALSTRING_LENGTH\\0" + "INVALID_UTF8STRING\\0" + "LIST_ERROR\\0" + "MISSING_ASN1_EOS\\0" + "MISSING_EOC\\0" + "MISSING_SECOND_NUMBER\\0" + "MISSING_VALUE\\0" + "MSTRING_NOT_UNIVERSAL\\0" + "MSTRING_WRONG_TAG\\0" + "NESTED_ASN1_ERROR\\0" + "NESTED_ASN1_STRING\\0" + "NON_HEX_CHARACTERS\\0" + "NOT_ASCII_FORMAT\\0" + "NOT_ENOUGH_DATA\\0" + "NO_MATCHING_CHOICE_TYPE\\0" + "NULL_IS_WRONG_LENGTH\\0" + "OBJECT_NOT_ASCII_FORMAT\\0" + "ODD_NUMBER_OF_CHARS\\0" + "SECOND_NUMBER_TOO_LARGE\\0" + "SEQUENCE_LENGTH_MISMATCH\\0" + "SEQUENCE_NOT_CONSTRUCTED\\0" + "SEQUENCE_OR_SET_NEEDS_CONFIG\\0" + "SHORT_LINE\\0" + "STREAMING_NOT_SUPPORTED\\0" + "STRING_TOO_LONG\\0" + "STRING_TOO_SHORT\\0" + "TAG_VALUE_TOO_HIGH\\0" + "TIME_NOT_ASCII_FORMAT\\0" + "TOO_LONG\\0" + "TYPE_NOT_CONSTRUCTED\\0" + "TYPE_NOT_PRIMITIVE\\0" + "UNEXPECTED_EOC\\0" + "UNIVERSALSTRING_IS_WRONG_LENGTH\\0" + "UNKNOWN_FORMAT\\0" + "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\\0" + "UNKNOWN_SIGNATURE_ALGORITHM\\0" + "UNKNOWN_TAG\\0" + "UNSUPPORTED_ANY_DEFINED_BY_TYPE\\0" + "UNSUPPORTED_PUBLIC_KEY_TYPE\\0" + "UNSUPPORTED_TYPE\\0" + "WRONG_PUBLIC_KEY_TYPE\\0" + "WRONG_TAG\\0" + "WRONG_TYPE\\0" + "BAD_FOPEN_MODE\\0" + "BROKEN_PIPE\\0" + "CONNECT_ERROR\\0" + "ERROR_SETTING_NBIO\\0" + "INVALID_ARGUMENT\\0" + "IN_USE\\0" + "KEEPALIVE\\0" + "NBIO_CONNECT_ERROR\\0" + "NO_HOSTNAME_SPECIFIED\\0" + "NO_PORT_SPECIFIED\\0" + "NO_SUCH_FILE\\0" + "NULL_PARAMETER\\0" + "SYS_LIB\\0" + "UNABLE_TO_CREATE_SOCKET\\0" + "UNINITIALIZED\\0" + "UNSUPPORTED_METHOD\\0" + "WRITE_TO_READ_ONLY_BIO\\0" + "ARG2_LT_ARG3\\0" + "BAD_ENCODING\\0" + "BAD_RECIPROCAL\\0" + "BIGNUM_TOO_LONG\\0" + "BITS_TOO_SMALL\\0" + "CALLED_WITH_EVEN_MODULUS\\0" + "DIV_BY_ZERO\\0" + "EXPAND_ON_STATIC_BIGNUM_DATA\\0" + "INPUT_NOT_REDUCED\\0" + "INVALID_INPUT\\0" + "INVALID_RANGE\\0" + "NEGATIVE_NUMBER\\0" + "NOT_A_SQUARE\\0" + "NOT_INITIALIZED\\0" + "NO_INVERSE\\0" + "PRIVATE_KEY_TOO_LARGE\\0" + "P_IS_NOT_PRIME\\0" + "TOO_MANY_ITERATIONS\\0" + "TOO_MANY_TEMPORARY_VARIABLES\\0" + "AES_KEY_SETUP_FAILED\\0" + "BAD_DECRYPT\\0" + "BAD_KEY_LENGTH\\0" + "CTRL_NOT_IMPLEMENTED\\0" + "CTRL_OPERATION_NOT_IMPLEMENTED\\0" + "DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH\\0" + "INITIALIZATION_ERROR\\0" + "INPUT_NOT_INITIALIZED\\0" + "INVALID_AD_SIZE\\0" + "INVALID_KEY_LENGTH\\0" + "INVALID_NONCE\\0" + "INVALID_NONCE_SIZE\\0" + "INVALID_OPERATION\\0" + "IV_TOO_LARGE\\0" + "NO_CIPHER_SET\\0" + "NO_DIRECTION_SET\\0" + "OUTPUT_ALIASES_INPUT\\0" + "TAG_TOO_LARGE\\0" + "TOO_LARGE\\0" + "UNSUPPORTED_AD_SIZE\\0" + "UNSUPPORTED_INPUT_SIZE\\0" + "UNSUPPORTED_KEY_SIZE\\0" + "UNSUPPORTED_NONCE_SIZE\\0" + "UNSUPPORTED_TAG_SIZE\\0" + "WRONG_FINAL_BLOCK_LENGTH\\0" + "LIST_CANNOT_BE_NULL\\0" + "MISSING_CLOSE_SQUARE_BRACKET\\0" + "MISSING_EQUAL_SIGN\\0" + "NO_CLOSE_BRACE\\0" + "UNABLE_TO_CREATE_NEW_SECTION\\0" + "VARIABLE_EXPANSION_TOO_LONG\\0" + "VARIABLE_HAS_NO_VALUE\\0" + "BAD_GENERATOR\\0" + "INVALID_PUBKEY\\0" + "MODULUS_TOO_LARGE\\0" + "NO_PRIVATE_VALUE\\0" + "UNKNOWN_HASH\\0" + "BAD_Q_VALUE\\0" + "BAD_VERSION\\0" + "MISSING_PARAMETERS\\0" + "NEED_NEW_SETUP_VALUES\\0" + "BIGNUM_OUT_OF_RANGE\\0" + "COORDINATES_OUT_OF_RANGE\\0" + "D2I_ECPKPARAMETERS_FAILURE\\0" + "EC_GROUP_NEW_BY_NAME_FAILURE\\0" + "GROUP2PKPARAMETERS_FAILURE\\0" + "GROUP_MISMATCH\\0" + "I2D_ECPKPARAMETERS_FAILURE\\0" + "INCOMPATIBLE_OBJECTS\\0" + "INVALID_COFACTOR\\0" + "INVALID_COMPRESSED_POINT\\0" + "INVALID_COMPRESSION_BIT\\0" + "INVALID_ENCODING\\0" + "INVALID_FIELD\\0" + "INVALID_FORM\\0" + "INVALID_GROUP_ORDER\\0" + "INVALID_PRIVATE_KEY\\0" + "MISSING_PRIVATE_KEY\\0" + "NON_NAMED_CURVE\\0" + "PKPARAMETERS2GROUP_FAILURE\\0" + "POINT_AT_INFINITY\\0" + "POINT_IS_NOT_ON_CURVE\\0" + "PUBLIC_KEY_VALIDATION_FAILED\\0" + "SLOT_FULL\\0" + "UNDEFINED_GENERATOR\\0" + "UNKNOWN_GROUP\\0" + "UNKNOWN_ORDER\\0" + "WRONG_CURVE_PARAMETERS\\0" + "WRONG_ORDER\\0" + "KDF_FAILED\\0" + "POINT_ARITHMETIC_FAILURE\\0" + "BAD_SIGNATURE\\0" + "NOT_IMPLEMENTED\\0" + "RANDOM_NUMBER_GENERATION_FAILED\\0" + "OPERATION_NOT_SUPPORTED\\0" + "COMMAND_NOT_SUPPORTED\\0" + "DIFFERENT_KEY_TYPES\\0" + "DIFFERENT_PARAMETERS\\0" + "EXPECTING_AN_EC_KEY_KEY\\0" + "EXPECTING_AN_RSA_KEY\\0" + "EXPECTING_A_DSA_KEY\\0" + "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\\0" + "INVALID_DIGEST_LENGTH\\0" + "INVALID_DIGEST_TYPE\\0" + "INVALID_KEYBITS\\0" + "INVALID_MGF1_MD\\0" + "INVALID_PADDING_MODE\\0" + "INVALID_PARAMETERS\\0" + "INVALID_PSS_SALTLEN\\0" + "INVALID_SIGNATURE\\0" + "KEYS_NOT_SET\\0" + "MEMORY_LIMIT_EXCEEDED\\0" + "NOT_A_PRIVATE_KEY\\0" + "NO_DEFAULT_DIGEST\\0" + "NO_KEY_SET\\0" + "NO_MDC2_SUPPORT\\0" + "NO_NID_FOR_CURVE\\0" + "NO_OPERATION_SET\\0" + "NO_PARAMETERS_SET\\0" + "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\\0" + "OPERATON_NOT_INITIALIZED\\0" + "UNKNOWN_PUBLIC_KEY_TYPE\\0" + "UNSUPPORTED_ALGORITHM\\0" + "OUTPUT_TOO_LARGE\\0" + "UNKNOWN_NID\\0" + "BAD_BASE64_DECODE\\0" + "BAD_END_LINE\\0" + "BAD_IV_CHARS\\0" + "BAD_PASSWORD_READ\\0" + "CIPHER_IS_NULL\\0" + "ERROR_CONVERTING_PRIVATE_KEY\\0" + "NOT_DEK_INFO\\0" + "NOT_ENCRYPTED\\0" + "NOT_PROC_TYPE\\0" + "NO_START_LINE\\0" + "READ_KEY\\0" + "SHORT_HEADER\\0" + "UNSUPPORTED_CIPHER\\0" + "UNSUPPORTED_ENCRYPTION\\0" + "BAD_PKCS7_VERSION\\0" + "NOT_PKCS7_SIGNED_DATA\\0" + "NO_CERTIFICATES_INCLUDED\\0" + "NO_CRLS_INCLUDED\\0" + "BAD_ITERATION_COUNT\\0" + "BAD_PKCS12_DATA\\0" + "BAD_PKCS12_VERSION\\0" + "CIPHER_HAS_NO_OBJECT_IDENTIFIER\\0" + "CRYPT_ERROR\\0" + "ENCRYPT_ERROR\\0" + "ERROR_SETTING_CIPHER_PARAMS\\0" + "INCORRECT_PASSWORD\\0" + "KEYGEN_FAILURE\\0" + "KEY_GEN_ERROR\\0" + "METHOD_NOT_SUPPORTED\\0" + "MISSING_MAC\\0" + "MULTIPLE_PRIVATE_KEYS_IN_PKCS12\\0" + "PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED\\0" + "PKCS12_TOO_DEEPLY_NESTED\\0" + "PRIVATE_KEY_DECODE_ERROR\\0" + "PRIVATE_KEY_ENCODE_ERROR\\0" + "UNKNOWN_ALGORITHM\\0" + "UNKNOWN_CIPHER\\0" + "UNKNOWN_CIPHER_ALGORITHM\\0" + "UNKNOWN_DIGEST\\0" + "UNSUPPORTED_KEYLENGTH\\0" + "UNSUPPORTED_KEY_DERIVATION_FUNCTION\\0" + "UNSUPPORTED_PRF\\0" + "UNSUPPORTED_PRIVATE_KEY_ALGORITHM\\0" + "UNSUPPORTED_SALT_TYPE\\0" + "BAD_E_VALUE\\0" + "BAD_FIXED_HEADER_DECRYPT\\0" + "BAD_PAD_BYTE_COUNT\\0" + "BAD_RSA_PARAMETERS\\0" + "BLOCK_TYPE_IS_NOT_01\\0" + "BN_NOT_INITIALIZED\\0" + "CANNOT_RECOVER_MULTI_PRIME_KEY\\0" + "CRT_PARAMS_ALREADY_GIVEN\\0" + "CRT_VALUES_INCORRECT\\0" + "DATA_LEN_NOT_EQUAL_TO_MOD_LEN\\0" + "DATA_TOO_LARGE\\0" + "DATA_TOO_LARGE_FOR_KEY_SIZE\\0" + "DATA_TOO_LARGE_FOR_MODULUS\\0" + "DATA_TOO_SMALL\\0" + "DATA_TOO_SMALL_FOR_KEY_SIZE\\0" + "DIGEST_TOO_BIG_FOR_RSA_KEY\\0" + "D_E_NOT_CONGRUENT_TO_1\\0" + "EMPTY_PUBLIC_KEY\\0" + "FIRST_OCTET_INVALID\\0" + "INCONSISTENT_SET_OF_CRT_VALUES\\0" + "INTERNAL_ERROR\\0" + "INVALID_MESSAGE_LENGTH\\0" + "KEY_SIZE_TOO_SMALL\\0" + "LAST_OCTET_INVALID\\0" + "MUST_HAVE_AT_LEAST_TWO_PRIMES\\0" + "NO_PUBLIC_EXPONENT\\0" + "NULL_BEFORE_BLOCK_MISSING\\0" + "N_NOT_EQUAL_P_Q\\0" + "OAEP_DECODING_ERROR\\0" + "ONLY_ONE_OF_P_Q_GIVEN\\0" + "OUTPUT_BUFFER_TOO_SMALL\\0" + "PADDING_CHECK_FAILED\\0" + "PKCS_DECODING_ERROR\\0" + "SLEN_CHECK_FAILED\\0" + "SLEN_RECOVERY_FAILED\\0" + "UNKNOWN_ALGORITHM_TYPE\\0" + "UNKNOWN_PADDING_TYPE\\0" + "VALUE_MISSING\\0" + "WRONG_SIGNATURE_LENGTH\\0" + "ALPN_MISMATCH_ON_EARLY_DATA\\0" + "APPLICATION_DATA_INSTEAD_OF_HANDSHAKE\\0" + "APP_DATA_IN_HANDSHAKE\\0" + "ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT\\0" + "BAD_ALERT\\0" + "BAD_CHANGE_CIPHER_SPEC\\0" + "BAD_DATA_RETURNED_BY_CALLBACK\\0" + "BAD_DH_P_LENGTH\\0" + "BAD_DIGEST_LENGTH\\0" + "BAD_ECC_CERT\\0" + "BAD_ECPOINT\\0" + "BAD_HANDSHAKE_RECORD\\0" + "BAD_HELLO_REQUEST\\0" + "BAD_LENGTH\\0" + "BAD_PACKET_LENGTH\\0" + "BAD_RSA_ENCRYPT\\0" + "BAD_SRTP_MKI_VALUE\\0" + "BAD_SRTP_PROTECTION_PROFILE_LIST\\0" + "BAD_SSL_FILETYPE\\0" + "BAD_WRITE_RETRY\\0" + "BIO_NOT_SET\\0" + "BLOCK_CIPHER_PAD_IS_WRONG\\0" + "BUFFERED_MESSAGES_ON_CIPHER_CHANGE\\0" + "CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD\\0" + "CANNOT_PARSE_LEAF_CERT\\0" + "CA_DN_LENGTH_MISMATCH\\0" + "CA_DN_TOO_LONG\\0" + "CCS_RECEIVED_EARLY\\0" + "CERTIFICATE_AND_PRIVATE_KEY_MISMATCH\\0" + "CERTIFICATE_VERIFY_FAILED\\0" + "CERT_CB_ERROR\\0" + "CERT_LENGTH_MISMATCH\\0" + "CHANNEL_ID_NOT_P256\\0" + "CHANNEL_ID_SIGNATURE_INVALID\\0" + "CIPHER_OR_HASH_UNAVAILABLE\\0" + "CLIENTHELLO_PARSE_FAILED\\0" + "CLIENTHELLO_TLSEXT\\0" + "CONNECTION_REJECTED\\0" + "CONNECTION_TYPE_NOT_SET\\0" + "CUSTOM_EXTENSION_ERROR\\0" + "DATA_LENGTH_TOO_LONG\\0" + "DECRYPTION_FAILED\\0" + "DECRYPTION_FAILED_OR_BAD_RECORD_MAC\\0" + "DH_PUBLIC_VALUE_LENGTH_IS_WRONG\\0" + "DH_P_TOO_LONG\\0" + "DIGEST_CHECK_FAILED\\0" + "DOWNGRADE_DETECTED\\0" + "DTLS_MESSAGE_TOO_BIG\\0" + "DUPLICATE_EXTENSION\\0" + "DUPLICATE_KEY_SHARE\\0" + "ECC_CERT_NOT_FOR_SIGNING\\0" + "EMS_STATE_INCONSISTENT\\0" + "ENCRYPTED_LENGTH_TOO_LONG\\0" + "ERROR_ADDING_EXTENSION\\0" + "ERROR_IN_RECEIVED_CIPHER_LIST\\0" + "ERROR_PARSING_EXTENSION\\0" + "EXCESSIVE_MESSAGE_SIZE\\0" + "EXTRA_DATA_IN_MESSAGE\\0" + "FRAGMENT_MISMATCH\\0" + "GOT_NEXT_PROTO_WITHOUT_EXTENSION\\0" + "HANDSHAKE_FAILURE_ON_CLIENT_HELLO\\0" + "HTTPS_PROXY_REQUEST\\0" + "HTTP_REQUEST\\0" + "INAPPROPRIATE_FALLBACK\\0" + "INVALID_ALPN_PROTOCOL\\0" + "INVALID_COMMAND\\0" + "INVALID_COMPRESSION_LIST\\0" + "INVALID_MESSAGE\\0" + "INVALID_OUTER_RECORD_TYPE\\0" + "INVALID_SCT_LIST\\0" + "INVALID_SSL_SESSION\\0" + "INVALID_TICKET_KEYS_LENGTH\\0" + "LENGTH_MISMATCH\\0" + "MISSING_EXTENSION\\0" + "MISSING_KEY_SHARE\\0" + "MISSING_RSA_CERTIFICATE\\0" + "MISSING_TMP_DH_KEY\\0" + "MISSING_TMP_ECDH_KEY\\0" + "MIXED_SPECIAL_OPERATOR_WITH_GROUPS\\0" + "MTU_TOO_SMALL\\0" + "NEGOTIATED_BOTH_NPN_AND_ALPN\\0" + "NESTED_GROUP\\0" + "NO_CERTIFICATES_RETURNED\\0" + "NO_CERTIFICATE_ASSIGNED\\0" + "NO_CERTIFICATE_SET\\0" + "NO_CIPHERS_AVAILABLE\\0" + "NO_CIPHERS_PASSED\\0" + "NO_CIPHERS_SPECIFIED\\0" + "NO_CIPHER_MATCH\\0" + "NO_COMMON_SIGNATURE_ALGORITHMS\\0" + "NO_COMPRESSION_SPECIFIED\\0" + "NO_GROUPS_SPECIFIED\\0" + "NO_METHOD_SPECIFIED\\0" + "NO_P256_SUPPORT\\0" + "NO_PRIVATE_KEY_ASSIGNED\\0" + "NO_RENEGOTIATION\\0" + "NO_REQUIRED_DIGEST\\0" + "NO_SHARED_CIPHER\\0" + "NO_SHARED_GROUP\\0" + "NO_SUPPORTED_VERSIONS_ENABLED\\0" + "NULL_SSL_CTX\\0" + "NULL_SSL_METHOD_PASSED\\0" + "OLD_SESSION_CIPHER_NOT_RETURNED\\0" + "OLD_SESSION_PRF_HASH_MISMATCH\\0" + "OLD_SESSION_VERSION_NOT_RETURNED\\0" + "PARSE_TLSEXT\\0" + "PATH_TOO_LONG\\0" + "PEER_DID_NOT_RETURN_A_CERTIFICATE\\0" + "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\\0" + "PRE_SHARED_KEY_MUST_BE_LAST\\0" + "PROTOCOL_IS_SHUTDOWN\\0" + "PSK_IDENTITY_BINDER_COUNT_MISMATCH\\0" + "PSK_IDENTITY_NOT_FOUND\\0" + "PSK_NO_CLIENT_CB\\0" + "PSK_NO_SERVER_CB\\0" + "READ_TIMEOUT_EXPIRED\\0" + "RECORD_LENGTH_MISMATCH\\0" + "RECORD_TOO_LARGE\\0" + "RENEGOTIATION_EMS_MISMATCH\\0" + "RENEGOTIATION_ENCODING_ERR\\0" + "RENEGOTIATION_MISMATCH\\0" + "REQUIRED_CIPHER_MISSING\\0" + "RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION\\0" + "RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION\\0" + "SCSV_RECEIVED_WHEN_RENEGOTIATING\\0" + "SERVERHELLO_TLSEXT\\0" + "SERVER_CERT_CHANGED\\0" + "SESSION_ID_CONTEXT_UNINITIALIZED\\0" + "SESSION_MAY_NOT_BE_CREATED\\0" + "SHUTDOWN_WHILE_IN_INIT\\0" + "SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER\\0" + "SRTP_COULD_NOT_ALLOCATE_PROFILES\\0" + "SRTP_UNKNOWN_PROTECTION_PROFILE\\0" + "SSL3_EXT_INVALID_SERVERNAME\\0" + "SSLV3_ALERT_BAD_CERTIFICATE\\0" + "SSLV3_ALERT_BAD_RECORD_MAC\\0" + "SSLV3_ALERT_CERTIFICATE_EXPIRED\\0" + "SSLV3_ALERT_CERTIFICATE_REVOKED\\0" + "SSLV3_ALERT_CERTIFICATE_UNKNOWN\\0" + "SSLV3_ALERT_CLOSE_NOTIFY\\0" + "SSLV3_ALERT_DECOMPRESSION_FAILURE\\0" + "SSLV3_ALERT_HANDSHAKE_FAILURE\\0" + "SSLV3_ALERT_ILLEGAL_PARAMETER\\0" + "SSLV3_ALERT_NO_CERTIFICATE\\0" + "SSLV3_ALERT_UNEXPECTED_MESSAGE\\0" + "SSLV3_ALERT_UNSUPPORTED_CERTIFICATE\\0" + "SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION\\0" + "SSL_HANDSHAKE_FAILURE\\0" + "SSL_SESSION_ID_CONTEXT_TOO_LONG\\0" + "TICKET_ENCRYPTION_FAILED\\0" + "TLSV1_ALERT_ACCESS_DENIED\\0" + "TLSV1_ALERT_DECODE_ERROR\\0" + "TLSV1_ALERT_DECRYPTION_FAILED\\0" + "TLSV1_ALERT_DECRYPT_ERROR\\0" + "TLSV1_ALERT_EXPORT_RESTRICTION\\0" + "TLSV1_ALERT_INAPPROPRIATE_FALLBACK\\0" + "TLSV1_ALERT_INSUFFICIENT_SECURITY\\0" + "TLSV1_ALERT_INTERNAL_ERROR\\0" + "TLSV1_ALERT_NO_RENEGOTIATION\\0" + "TLSV1_ALERT_PROTOCOL_VERSION\\0" + "TLSV1_ALERT_RECORD_OVERFLOW\\0" + "TLSV1_ALERT_UNKNOWN_CA\\0" + "TLSV1_ALERT_USER_CANCELLED\\0" + "TLSV1_BAD_CERTIFICATE_HASH_VALUE\\0" + "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\\0" + "TLSV1_CERTIFICATE_REQUIRED\\0" + "TLSV1_CERTIFICATE_UNOBTAINABLE\\0" + "TLSV1_UNKNOWN_PSK_IDENTITY\\0" + "TLSV1_UNRECOGNIZED_NAME\\0" + "TLSV1_UNSUPPORTED_EXTENSION\\0" + "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\\0" + "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG\\0" + "TOO_MANY_EMPTY_FRAGMENTS\\0" + "TOO_MANY_KEY_UPDATES\\0" + "TOO_MANY_WARNING_ALERTS\\0" + "TOO_MUCH_READ_EARLY_DATA\\0" + "TOO_MUCH_SKIPPED_EARLY_DATA\\0" + "UNABLE_TO_FIND_ECDH_PARAMETERS\\0" + "UNEXPECTED_EXTENSION\\0" + "UNEXPECTED_EXTENSION_ON_EARLY_DATA\\0" + "UNEXPECTED_MESSAGE\\0" + "UNEXPECTED_OPERATOR_IN_GROUP\\0" + "UNEXPECTED_RECORD\\0" + "UNKNOWN_ALERT_TYPE\\0" + "UNKNOWN_CERTIFICATE_TYPE\\0" + "UNKNOWN_CIPHER_RETURNED\\0" + "UNKNOWN_CIPHER_TYPE\\0" + "UNKNOWN_KEY_EXCHANGE_TYPE\\0" + "UNKNOWN_PROTOCOL\\0" + "UNKNOWN_SSL_VERSION\\0" + "UNKNOWN_STATE\\0" + "UNSAFE_LEGACY_RENEGOTIATION_DISABLED\\0" + "UNSUPPORTED_COMPRESSION_ALGORITHM\\0" + "UNSUPPORTED_ELLIPTIC_CURVE\\0" + "UNSUPPORTED_PROTOCOL\\0" + "UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY\\0" + "WRONG_CERTIFICATE_TYPE\\0" + "WRONG_CIPHER_RETURNED\\0" + "WRONG_CURVE\\0" + "WRONG_MESSAGE_TYPE\\0" + "WRONG_SIGNATURE_TYPE\\0" + "WRONG_SSL_VERSION\\0" + "WRONG_VERSION_NUMBER\\0" + "WRONG_VERSION_ON_EARLY_DATA\\0" + "X509_LIB\\0" + "X509_VERIFICATION_SETUP_PROBLEMS\\0" + "AKID_MISMATCH\\0" + "BAD_X509_FILETYPE\\0" + "BASE64_DECODE_ERROR\\0" + "CANT_CHECK_DH_KEY\\0" + "CERT_ALREADY_IN_HASH_TABLE\\0" + "CRL_ALREADY_DELTA\\0" + "CRL_VERIFY_FAILURE\\0" + "IDP_MISMATCH\\0" + "INVALID_DIRECTORY\\0" + "INVALID_FIELD_NAME\\0" + "INVALID_PARAMETER\\0" + "INVALID_PSS_PARAMETERS\\0" + "INVALID_TRUST\\0" + "ISSUER_MISMATCH\\0" + "KEY_TYPE_MISMATCH\\0" + "KEY_VALUES_MISMATCH\\0" + "LOADING_CERT_DIR\\0" + "LOADING_DEFAULTS\\0" + "NAME_TOO_LONG\\0" + "NEWER_CRL_NOT_NEWER\\0" + "NO_CERT_SET_FOR_US_TO_VERIFY\\0" + "NO_CRL_NUMBER\\0" + "PUBLIC_KEY_DECODE_ERROR\\0" + "PUBLIC_KEY_ENCODE_ERROR\\0" + "SHOULD_RETRY\\0" + "UNKNOWN_KEY_TYPE\\0" + "UNKNOWN_PURPOSE_ID\\0" + "UNKNOWN_TRUST_ID\\0" + "WRONG_LOOKUP_TYPE\\0" + "BAD_IP_ADDRESS\\0" + "BAD_OBJECT\\0" + "BN_DEC2BN_ERROR\\0" + "BN_TO_ASN1_INTEGER_ERROR\\0" + "CANNOT_FIND_FREE_FUNCTION\\0" + "DIRNAME_ERROR\\0" + "DISTPOINT_ALREADY_SET\\0" + "DUPLICATE_ZONE_ID\\0" + "ERROR_CONVERTING_ZONE\\0" + "ERROR_CREATING_EXTENSION\\0" + "ERROR_IN_EXTENSION\\0" + "EXPECTED_A_SECTION_NAME\\0" + "EXTENSION_EXISTS\\0" + "EXTENSION_NAME_ERROR\\0" + "EXTENSION_NOT_FOUND\\0" + "EXTENSION_SETTING_NOT_SUPPORTED\\0" + "EXTENSION_VALUE_ERROR\\0" + "ILLEGAL_EMPTY_EXTENSION\\0" + "ILLEGAL_HEX_DIGIT\\0" + "INCORRECT_POLICY_SYNTAX_TAG\\0" + "INVALID_BOOLEAN_STRING\\0" + "INVALID_EXTENSION_STRING\\0" + "INVALID_MULTIPLE_RDNS\\0" + "INVALID_NAME\\0" + "INVALID_NULL_ARGUMENT\\0" + "INVALID_NULL_NAME\\0" + "INVALID_NULL_VALUE\\0" + "INVALID_NUMBERS\\0" + "INVALID_OBJECT_IDENTIFIER\\0" + "INVALID_OPTION\\0" + "INVALID_POLICY_IDENTIFIER\\0" + "INVALID_PROXY_POLICY_SETTING\\0" + "INVALID_PURPOSE\\0" + "INVALID_SECTION\\0" + "INVALID_SYNTAX\\0" + "ISSUER_DECODE_ERROR\\0" + "NEED_ORGANIZATION_AND_NUMBERS\\0" + "NO_CONFIG_DATABASE\\0" + "NO_ISSUER_CERTIFICATE\\0" + "NO_ISSUER_DETAILS\\0" + "NO_POLICY_IDENTIFIER\\0" + "NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED\\0" + "NO_PUBLIC_KEY\\0" + "NO_SUBJECT_DETAILS\\0" + "ODD_NUMBER_OF_DIGITS\\0" + "OPERATION_NOT_DEFINED\\0" + "OTHERNAME_ERROR\\0" + "POLICY_LANGUAGE_ALREADY_DEFINED\\0" + "POLICY_PATH_LENGTH\\0" + "POLICY_PATH_LENGTH_ALREADY_DEFINED\\0" + "POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY\\0" + "SECTION_NOT_FOUND\\0" + "UNABLE_TO_GET_ISSUER_DETAILS\\0" + "UNABLE_TO_GET_ISSUER_KEYID\\0" + "UNKNOWN_BIT_STRING_ARGUMENT\\0" + "UNKNOWN_EXTENSION\\0" + "UNKNOWN_EXTENSION_NAME\\0" + "UNKNOWN_OPTION\\0" + "UNSUPPORTED_OPTION\\0" + "USER_TOO_LONG\\0" + ""; + EOF - sed -i'.back' '/^#define \\([A-Za-z0-9_]*\\) \\1/d' include/openssl/ssl.h - sed -i'.back' 'N;/^#define \\([A-Za-z0-9_]*\\) *\\\\\\n *\\1/d' include/openssl/ssl.h - sed -i'.back' 's/#ifndef md5_block_data_order/#ifndef GRPC_SHADOW_md5_block_data_order/g' crypto/fipsmodule/md5/md5.c - find . -type f \\( -path '*.h' -or -path '*.cc' -or -path '*.c' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include Date: Thu, 17 Jan 2019 13:37:33 -0800 Subject: [PATCH 018/218] generate projects --- gRPC-C++.podspec | 1 + gRPC-Core.podspec | 1 + gRPC.podspec | 1 + src/objective-c/!ProtoCompiler-gRPCPlugin.podspec | 1 + src/objective-c/BoringSSL-GRPC.podspec | 1 + 5 files changed, 5 insertions(+) diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 9935ec40e3f..4c30e568a1b 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -41,6 +41,7 @@ Pod::Spec.new do |s| s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' s.tvos.deployment_target = '10.0' + s.requires_arc = false name = 'grpcpp' diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 8eabd00e6f0..6f687ca3fb5 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -41,6 +41,7 @@ Pod::Spec.new do |s| s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' s.tvos.deployment_target = '10.0' + s.requires_arc = false name = 'grpc' diff --git a/gRPC.podspec b/gRPC.podspec index 940a1ac6217..8577c9d2a33 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -34,6 +34,7 @@ Pod::Spec.new do |s| s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '10.0' name = 'GRPCClient' s.module_name = name diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index 55ca6048bc3..50f2bc4eb29 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -105,6 +105,7 @@ Pod::Spec.new do |s| # For the Protobuf dependency not to complain: s.ios.deployment_target = '7.0' s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '10.0' # Restrict the gRPC runtime version to the one supported by this plugin. s.dependency 'gRPC-ProtoRPC', v diff --git a/src/objective-c/BoringSSL-GRPC.podspec b/src/objective-c/BoringSSL-GRPC.podspec index 3f02268b4fe..6ec3747faef 100644 --- a/src/objective-c/BoringSSL-GRPC.podspec +++ b/src/objective-c/BoringSSL-GRPC.podspec @@ -1,4 +1,5 @@ + # This file has been automatically generated from a template file. # Please make modifications to # `templates/src/objective-c/BoringSSL-GRPC.podspec.template` instead. This From 4351ca35ee059ae3301dd8033d7d262daa416799 Mon Sep 17 00:00:00 2001 From: Jerry Date: Thu, 17 Jan 2019 14:36:15 -0800 Subject: [PATCH 019/218] memory leak test for php --- src/php/bin/run_tests.sh | 10 + .../tests/MemoryLeakTest/MemoryLeakTest.php | 2310 +++++++++++++++++ src/php/tests/unit_tests/CallTest.php | 20 + 3 files changed, 2340 insertions(+) create mode 100644 src/php/tests/MemoryLeakTest/MemoryLeakTest.php diff --git a/src/php/bin/run_tests.sh b/src/php/bin/run_tests.sh index 295bcb2430c..cfe16ee3e85 100755 --- a/src/php/bin/run_tests.sh +++ b/src/php/bin/run_tests.sh @@ -22,9 +22,19 @@ cd src/php/bin source ./determine_extension_dir.sh # in some jenkins macos machine, somehow the PHP build script can't find libgrpc.dylib export DYLD_LIBRARY_PATH=$root/libs/$CONFIG + php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \ --exclude-group persistent_list_bound_tests ../tests/unit_tests php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \ ../tests/unit_tests/PersistentChannelTests +export ZEND_DONT_UNLOAD_MODULES=1 +export USE_ZEND_ALLOC=0 +# Detect whether valgrind is executable +if ! [ -x "$(command -v valgrind)" ]; then + echo 'Error: valgrind is not installed and is not executable' >&2 + exit 1 +fi +valgrind --error-exitcode=10 --leak-check=yes php $extension_dir -d max_execution_time=300 \ + ../tests/MemoryLeakTest/MemoryLeakTest.php diff --git a/src/php/tests/MemoryLeakTest/MemoryLeakTest.php b/src/php/tests/MemoryLeakTest/MemoryLeakTest.php new file mode 100644 index 00000000000..6b5fcb1ec78 --- /dev/null +++ b/src/php/tests/MemoryLeakTest/MemoryLeakTest.php @@ -0,0 +1,2310 @@ + "v1"]; +} + +function assertConnecting($state) +{ + assert(($state == GRPC\CHANNEL_CONNECTING || $state == GRPC\CHANNEL_TRANSIENT_FAILURE) == true); +} + +function waitUntilNotIdle($channel) { + for ($i = 0; $i < 10; $i++) { + $now = Grpc\Timeval::now(); + $deadline = $now->add(new Grpc\Timeval(10000)); + if ($channel->watchConnectivityState(GRPC\CHANNEL_IDLE, + $deadline)) { + return true; + } + } + assert(true == false); +} + +// Set up +$channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + +// Test InsecureCredentials +assert('Grpc\Channel' == get_class($channel)); + +// Test ConnectivityState +$state = $channel->getConnectivityState(); +assert(0 == $state); + +// Test GetConnectivityStateWithInt +$state = $channel->getConnectivityState(123); +assert(0 == $state); + +// Test GetConnectivityStateWithString +$state = $channel->getConnectivityState('hello'); +assert(0 == $state); + +// Test GetConnectivityStateWithBool +$state = $channel->getConnectivityState(true); +assert(0 == $state); + +$channel->close(); + +// Test GetTarget +$channel = new Grpc\Channel('localhost:8888', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); +$target = $channel->getTarget(); +assert(is_string($target) == true); +$channel->close(); + +// Test WatchConnectivityState +$channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); +$now = Grpc\Timeval::now(); +$deadline = $now->add(new Grpc\Timeval(100*1000)); + +$state = $channel->watchConnectivityState(1, $deadline); +assert($state == true); + +unset($now); +unset($deadline); + +$channel->close(); + +// Test InvalidConstructorWithNull +try { + $channel = new Grpc\Channel(); + assert($channel == NULL); +} +catch (\Exception $e) { +} + +// Test InvalidConstructorWith +try { + $channel = new Grpc\Channel('localhost:0', 'invalid'); + assert($channel == NULL); +} +catch (\Exception $e) { +} + +// Test InvalideCredentials +try { + $channel = new Grpc\Channel('localhost:0', ['credentials' => new Grpc\Timeval(100)]); +} +catch (\Exception $e) { +} + +// Test InvalidOptionsArrray +try { + $channel = new Grpc\Channel('localhost:0', ['abc' => []]); +} +catch (\Exception $e) { +} + +// Test InvalidGetConnectivityStateWithArray +$channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); +try { + $channel->getConnectivityState([]); +} +catch (\Exception $e) { +} + +// Test InvalidWatchConnectivityState +try { + $channel->watchConnectivityState([]); +} +catch (\Exception $e) { +} + +// Test InvalidWatchConnectivityState2 +try { + $channel->watchConnectivityState(1, 'hi'); +} +catch (\Exception $e) { +} + +$channel->close(); + +// Test PersistentChannelSameHost +$channel1 = new Grpc\Channel('localhost:1', []); +$channel2 = new Grpc\Channel('localhost:1', []); +$state = $channel1->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +$state = $channel1->getConnectivityState(true); +waitUntilNotIdle($channel1); + +$state = $channel1->getConnectivityState(); +assertConnecting($state); +$state = $channel2->getConnectivityState(); +assertConnecting($state); + +$channel1->close(); +$channel2->close(); + +// Test PersistentChannelDifferentHost +$channel1 = new Grpc\Channel('localhost:1', ["grpc_target_persist_bound" => 3,]); +$channel2 = new Grpc\Channel('localhost:2', []); +$state = $channel1->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +$state = $channel1->getConnectivityState(true); +waitUntilNotIdle($channel1); + +$state = $channel1->getConnectivityState(); +assertConnecting($state); +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +$channel1->close(); +$channel2->close(); + +// Test PersistentChannelSameArgs +$channel1 = new Grpc\Channel('localhost:1', [ + "grpc_target_persist_bound" => 3, + "abc" => "def", + ]); +$channel2 = new Grpc\Channel('localhost:1', ["abc" => "def"]); +$state = $channel1->getConnectivityState(true); +waitUntilNotIdle($channel1); + +$state = $channel1->getConnectivityState(); +assertConnecting($state); +$state = $channel2->getConnectivityState(); +assertConnecting($state); + +$channel1->close(); +$channel2->close(); + +// Test PersistentChannelDifferentArgs +$channel1 = new Grpc\Channel('localhost:1', []); +$channel2 = new Grpc\Channel('localhost:1', ["abc" => "def"]); +$state = $channel1->getConnectivityState(true); +waitUntilNotIdle($channel1); + +$state = $channel1->getConnectivityState(); +assertConnecting($state); +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +$channel1->close(); +$channel2->close(); + +// Test PersistentChannelSameChannelCredentials +$creds1 = Grpc\ChannelCredentials::createSsl(); +$creds2 = Grpc\ChannelCredentials::createSsl(); + +$channel1 = new Grpc\Channel('localhost:1', + ["credentials" => $creds1, + "grpc_target_persist_bound" => 3, + ]); +$channel2 = new Grpc\Channel('localhost:1', + ["credentials" => $creds2]); + +$state = $channel1->getConnectivityState(true); +print "state: ".$state."......................"; +waitUntilNotIdle($channel1); + +$state = $channel1->getConnectivityState(); +assertConnecting($state); +$state = $channel2->getConnectivityState(); +assertConnecting($state); + +$channel1->close(); +$channel2->close(); + +// Test PersistentChannelDifferentChannelCredentials +$creds1 = Grpc\ChannelCredentials::createSsl(); +$creds2 = Grpc\ChannelCredentials::createSsl( + file_get_contents(dirname(__FILE__).'/../data/ca.pem')); + +$channel1 = new Grpc\Channel('localhost:1', + ["credentials" => $creds1, + "grpc_target_persist_bound" => 3, + ]); +$channel2 = new Grpc\Channel('localhost:1', + ["credentials" => $creds2]); + +$state = $channel1->getConnectivityState(true); +waitUntilNotIdle($channel1); + +$state = $channel1->getConnectivityState(); +assertConnecting($state); +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +$channel1->close(); +$channel2->close(); + + +// Test PersistentChannelSameChannelCredentialsRootCerts +$creds1 = Grpc\ChannelCredentials::createSsl( + file_get_contents(dirname(__FILE__).'/../data/ca.pem')); +$creds2 = Grpc\ChannelCredentials::createSsl( + file_get_contents(dirname(__FILE__).'/../data/ca.pem')); + +$channel1 = new Grpc\Channel('localhost:1', + ["credentials" => $creds1, + "grpc_target_persist_bound" => 3, + ]); +$channel2 = new Grpc\Channel('localhost:1', + ["credentials" => $creds2]); + +$state = $channel1->getConnectivityState(true); +waitUntilNotIdle($channel1); + +$state = $channel1->getConnectivityState(); +assertConnecting($state); +$state = $channel2->getConnectivityState(); +assertConnecting($state); + +$channel1->close(); +$channel2->close(); + +// Test PersistentChannelDifferentSecureChannelCredentials +$creds1 = Grpc\ChannelCredentials::createSsl(); +$creds2 = Grpc\ChannelCredentials::createInsecure(); + +$channel1 = new Grpc\Channel('localhost:1', + ["credentials" => $creds1, + "grpc_target_persist_bound" => 3, + ]); +$channel2 = new Grpc\Channel('localhost:1', + ["credentials" => $creds2]); + +$state = $channel1->getConnectivityState(true); +waitUntilNotIdle($channel1); + +$state = $channel1->getConnectivityState(); +assertConnecting($state); +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +$channel1->close(); +$channel2->close(); + +// Test PersistentChannelSharedChannelClose1 +$channel1 = new Grpc\Channel('localhost:1', [ + "grpc_target_persist_bound" => 3, +]); +$channel2 = new Grpc\Channel('localhost:1', []); + +$channel1->close(); + +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); +$channel2->close(); + +// Test PersistentChannelSharedChannelClose2 +$channel1 = new Grpc\Channel('localhost:1', [ + "grpc_target_persist_bound" => 3, +]); +$channel2 = new Grpc\Channel('localhost:1', []); + +$channel1->close(); + +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +try{ + $state = $channel1->getConnectivityState(); +} +catch(\Exception $e){ +} + +$channel2->close(); + +//Test PersistentChannelCreateAfterClose +$channel1 = new Grpc\Channel('localhost:1', [ + "grpc_target_persist_bound" => 3, +]); + +$channel1->close(); + +$channel2 = new Grpc\Channel('localhost:1', []); +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +$channel2->close(); + +//Test PersistentChannelSharedMoreThanTwo +$channel1 = new Grpc\Channel('localhost:1', [ + "grpc_target_persist_bound" => 3, +]); +$channel2 = new Grpc\Channel('localhost:1', []); +$channel3 = new Grpc\Channel('localhost:1', []); + +$state = $channel1->getConnectivityState(true); +waitUntilNotIdle($channel1); + +$state = $channel1->getConnectivityState(); +assertConnecting($state); +$state = $channel2->getConnectivityState(); +assertConnecting($state); +$state = $channel3->getConnectivityState(); +assertConnecting($state); + +$channel1->close(); + +//Test PersistentChannelWithCallCredentials +$creds = Grpc\ChannelCredentials::createSsl(); +$callCreds = Grpc\CallCredentials::createFromPlugin( + 'callbackFunc'); +$credsWithCallCreds = Grpc\ChannelCredentials::createComposite( + $creds, $callCreds); + +$channel1 = new Grpc\Channel('localhost:1', + ["credentials" => + $credsWithCallCreds, + "grpc_target_persist_bound" => 3, + ]); +$channel2 = new Grpc\Channel('localhost:1', + ["credentials" => + $credsWithCallCreds]); + +$state = $channel1->getConnectivityState(true); +waitUntilNotIdle($channel1); + +$state = $channel1->getConnectivityState(); +assertConnecting($state); +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +$channel1->close(); +$channel2->close(); + +// Test PersistentChannelWithDifferentCallCredentials +$callCreds1 = Grpc\CallCredentials::createFromPlugin('callbackFunc'); +$callCreds2 = Grpc\CallCredentials::createFromPlugin('callbackFunc2'); + +$creds1 = Grpc\ChannelCredentials::createSsl(); +$creds2 = Grpc\ChannelCredentials::createComposite( + $creds1, $callCreds1); +$creds3 = Grpc\ChannelCredentials::createComposite( + $creds1, $callCreds2); + +$channel1 = new Grpc\Channel('localhost:1', + ["credentials" => $creds1, + "grpc_target_persist_bound" => 3, + ]); +$channel2 = new Grpc\Channel('localhost:1', + ["credentials" => $creds2]); +$channel3 = new Grpc\Channel('localhost:1', + ["credentials" => $creds3]); + +$state = $channel1->getConnectivityState(true); +waitUntilNotIdle($channel1); + +$state = $channel1->getConnectivityState(); +assertConnecting($state); +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); +$state = $channel3->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +$channel1->close(); +$channel2->close(); +$channel3->close(); + +// Test PersistentChannelForceNew +$channel1 = new Grpc\Channel('localhost:1', [ + "grpc_target_persist_bound" => 2, +]); +$channel2 = new Grpc\Channel('localhost:1', + ["force_new" => true]); + +$state = $channel1->getConnectivityState(true); +waitUntilNotIdle($channel1); + +$state = $channel1->getConnectivityState(); +assertConnecting($state); +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +$channel1->close(); +$channel2->close(); + +// Test PersistentChannelForceNewOldChannelIdle1 +$channel1 = new Grpc\Channel('localhost:1', [ + "grpc_target_persist_bound" => 2, +]); +$channel2 = new Grpc\Channel('localhost:1', + ["force_new" => true]); +$channel3 = new Grpc\Channel('localhost:1', []); + +$state = $channel2->getConnectivityState(true); +waitUntilNotIdle($channel2); +$state = $channel1->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); +$state = $channel2->getConnectivityState(); +assertConnecting($state); +$state = $channel3->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +$channel1->close(); +$channel2->close(); + +// Test PersistentChannelForceNewOldChannelIdle2 +$channel1 = new Grpc\Channel('localhost:1', [ + "grpc_target_persist_bound" => 2, +]); +$channel2 = new Grpc\Channel('localhost:1', []); + +$state = $channel1->getConnectivityState(true); +waitUntilNotIdle($channel2); +$state = $channel1->getConnectivityState(); +assertConnecting($state); +$state = $channel2->getConnectivityState(); +assertConnecting($state); + +$channel1->close(); +$channel2->close(); + +// Test PersistentChannelForceNewOldChannelClose1 +$channel1 = new Grpc\Channel('localhost:1', [ + "grpc_target_persist_bound" => 2, +]); +$channel2 = new Grpc\Channel('localhost:1', + ["force_new" => true]); +$channel3 = new Grpc\Channel('localhost:1', []); + +$channel1->close(); + +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); +$state = $channel3->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +$channel2->close(); +$channel3->close(); + +// Test PersistentChannelForceNewOldChannelClose2 +$channel1 = new Grpc\Channel('localhost:1', [ + "grpc_target_persist_bound" => 2, +]); +$channel2 = new Grpc\Channel('localhost:1', + ["force_new" => true]); +// channel3 shares with channel1 +$channel3 = new Grpc\Channel('localhost:1', []); + +$channel1->close(); + +$state = $channel2->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +// channel3 is still usable +$state = $channel3->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +// channel 1 is closed +try{ + $channel1->getConnectivityState(); +} +catch(\Exception $e){ +} + +$channel2->close(); +$channel3->close(); + +// Test PersistentChannelForceNewNewChannelClose +$channel1 = new Grpc\Channel('localhost:1', [ + "grpc_target_persist_bound" => 2, +]); +$channel2 = new Grpc\Channel('localhost:1', + ["force_new" => true]); +$channel3 = new Grpc\Channel('localhost:1', []); + +$channel2->close(); + +$state = $channel1->getConnectivityState(); +assert(GRPC\CHANNEL_IDLE == $state); + +// can still connect on channel1 +$state = $channel1->getConnectivityState(true); +waitUntilNotIdle($channel1); + +$state = $channel1->getConnectivityState(); +assertConnecting($state); + +$channel1->close(); + +//============== Call Test ==================== +$server = new Grpc\Server([]); +$port = $server->addHttp2Port('0.0.0.0:53000'); +$channel = new Grpc\Channel('localhost:'.$port, []); +$call = new Grpc\Call($channel, + '/foo', + Grpc\Timeval::infFuture()); + +// Test AddEmptyMetadata +$batch = [ + Grpc\OP_SEND_INITIAL_METADATA => [], +]; +$result = $call->startBatch($batch); +assert($result->send_metadata == true); + +// Test testAddSingleMetadata +$batch = [ + Grpc\OP_SEND_INITIAL_METADATA => ['key' => ['value']], +]; +$call = new Grpc\Call($channel, + '/foo', + Grpc\Timeval::infFuture()); +$result = $call->startBatch($batch); +assert($result->send_metadata == true); + +// Test AddMultiValue +$batch = [ + Grpc\OP_SEND_INITIAL_METADATA => ['key' => ['value1', 'value2']], +]; +$call = new Grpc\Call($channel, + '/foo', + Grpc\Timeval::infFuture()); +$result = $call->startBatch($batch); +assert($result->send_metadata == true); + +// Test AddSingleAndMultiValueMetadata +$batch = [ + Grpc\OP_SEND_INITIAL_METADATA => ['key1' => ['value1'], + 'key2' => ['value2', + 'value3', ], ], +]; +$call = new Grpc\Call($channel, + '/foo', + Grpc\Timeval::infFuture()); +$result = $call->startBatch($batch); +assert($result->send_metadata == true); + +// Test AddMultiAndMultiValueMetadata +$batch = [ + Grpc\OP_SEND_INITIAL_METADATA => ['key1' => ['value1'], + 'key2' => ['value2', + 'value3', ], ], +]; +$call = new Grpc\Call($channel, + '/foo', + Grpc\Timeval::infFuture()); +$result = $call->startBatch($batch); +assert($result->send_metadata == true); + +// Test GetPeer +assert(is_string($call->getPeer()) == true); + +// Test Cancel +assert($call->cancel == NULL); + +// Test InvalidStartBatchKey +$batch = [ + 'invalid' => ['key1' => 'value1'], +]; +try{ + $result = $call->startBatch($batch); +} +catch(\Exception $e){ +} + +// Test InvalideMetadataStrKey +$batch = [ + Grpc\OP_SEND_INITIAL_METADATA => ['Key' => ['value1', 'value2']], +]; +$call = new Grpc\Call($channel, + '/foo', + Grpc\Timeval::infFuture()); +try{ + $result = $call->startBatch($batch); +} +catch(\Exception $e){ +} + +// Test InvalidMetadataIntKey +$batch = [ + Grpc\OP_SEND_INITIAL_METADATA => [1 => ['value1', 'value2']], +]; +$call = new Grpc\Call($channel, + '/foo', + Grpc\Timeval::infFuture()); +try{ + $result = $call->startBatch($batch); +} +catch(\Exception $e){ +} + +// Test InvalidMetadataInnerValue +$batch = [ + Grpc\OP_SEND_INITIAL_METADATA => ['key1' => 'value1'], +]; +$call = new Grpc\Call($channel, + '/foo', + Grpc\Timeval::infFuture()); +try{ + $result = $call->startBatch($batch); +} +catch(\Exception $e){ +} + +// Test InvalidConstuctor +try { + $call = new Grpc\Call(); +} catch (\Exception $e) {} + +// Test InvalidConstuctor2 +try { + $call = new Grpc\Call('hi', 'hi', 'hi'); +} catch (\Exception $e) {} + +// Test InvalidSetCredentials +try{ + $call->setCredentials('hi'); +} +catch(\Exception $e){ +} + +// Test InvalidSetCredentials2 +try { + $call->setCredentials([]); +} catch (\Exception $e) {} + + +//============== CallCredentials Test 2 ==================== +// Set Up +$credentials = Grpc\ChannelCredentials::createSsl( + file_get_contents(dirname(__FILE__).'/../data/ca.pem')); +$server_credentials = Grpc\ServerCredentials::createSsl( + null, + file_get_contents(dirname(__FILE__).'/../data/server1.key'), + file_get_contents(dirname(__FILE__).'/../data/server1.pem')); +$server = new Grpc\Server(); +$port = $server->addSecureHttp2Port('0.0.0.0:0', + $server_credentials); +$server->start(); +$host_override = 'foo.test.google.fr'; +$channel = new Grpc\Channel( + 'localhost:'.$port, + [ + 'grpc.ssl_target_name_override' => $host_override, + 'grpc.default_authority' => $host_override, + 'credentials' => $credentials, + ] +); +function callCredscallbackFunc($context) +{ + is_string($context->service_url); + is_string($context->method_name); + return ['k1' => ['v1'], 'k2' => ['v2']]; +} + +// Test CreateFromPlugin +$deadline = Grpc\Timeval::infFuture(); +$status_text = 'xyz'; +$call = new Grpc\Call($channel, + '/abc/dummy_method', + $deadline, + $host_override); + $call_credentials = Grpc\CallCredentials::createFromPlugin( + 'callCredscallbackFunc'); +$call->setCredentials($call_credentials); + $event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, +]); +assert($event->send_metadata == true); +assert($event->send_close == true); + +$event = $server->requestCall(); +assert(is_array($event->metadata) == true); + +$metadata = $event->metadata; +assert(array_key_exists('k1', $metadata) == true); +assert(array_key_exists('k2', $metadata) == true); +assert($metadata['k1'] == ['v1']); +assert($metadata['k2'] == ['v2']); +assert('/abc/dummy_method' == $event->method); + +$server_call = $event->call; +$event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => $status_text, + ], + Grpc\OP_RECV_CLOSE_ON_SERVER => true, +]); +assert($event->send_metadata == true); +assert($event->send_status == true); +assert($event->cancelled == false); + +$event = $call->startBatch([ + Grpc\OP_RECV_INITIAL_METADATA => true, + Grpc\OP_RECV_STATUS_ON_CLIENT => true, +]); +assert([] == $event->metadata); + +$status = $event->status; +assert([] == $status->metadata); +assert(Grpc\STATUS_OK == $status->code); +assert($status_text == $status->details); + +unset($call); +unset($server_call); + +function invalidKeyCallbackFunc($context) +{ + is_string($context->service_url); + is_string($context->method_name); + return ['K1' => ['v1']]; +} + +// Test CallbackWithInvalidKey +$deadline = Grpc\Timeval::infFuture(); +$status_text = 'xyz'; +$call = new Grpc\Call($channel, + '/abc/dummy_method', + $deadline, + $host_override); + $call_credentials = Grpc\CallCredentials::createFromPlugin( + 'invalidKeyCallbackFunc'); +$call->setCredentials($call_credentials); +$event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + Grpc\OP_RECV_STATUS_ON_CLIENT => true, +]); +assert($event->send_metadata == true); +assert($event->send_close == true); +assert(($event->status->code == Grpc\STATUS_UNAVAILABLE) == true); + +function invalidReturnCallbackFunc($context) +{ + is_string($context->service_url); + is_string($context->method_name); + return 'a string'; +} + +// Test CallbackWithInvalidReturnValue +$deadline = Grpc\Timeval::infFuture(); +$status_text = 'xyz'; +$call = new Grpc\Call($channel, + '/abc/dummy_method', + $deadline, + $host_override); + $call_credentials = Grpc\CallCredentials::createFromPlugin( + 'invalidReturnCallbackFunc'); +$call->setCredentials($call_credentials); + $event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + Grpc\OP_RECV_STATUS_ON_CLIENT => true, +]); + +assert($event->send_metadata == true); +assert($event->send_close == true); +assert(($event->status->code == Grpc\STATUS_UNAVAILABLE) == true); + +unset($channel); +unset($server); + +//============== CallCredentials Test ==================== +//Set Up +$credentials = Grpc\ChannelCredentials::createSsl( + file_get_contents(dirname(__FILE__).'/../data/ca.pem')); +$call_credentials = Grpc\CallCredentials::createFromPlugin('callbackFunc'); +$credentials = Grpc\ChannelCredentials::createComposite( + $credentials, + $call_credentials +); +$server_credentials = Grpc\ServerCredentials::createSsl( + null, + file_get_contents(dirname(__FILE__).'/../data/server1.key'), + file_get_contents(dirname(__FILE__).'/../data/server1.pem')); +$server = new Grpc\Server(); +$port = $server->addSecureHttp2Port('0.0.0.0:0', + $server_credentials); +$server->start(); +$host_override = 'foo.test.google.fr'; +$channel = new Grpc\Channel( + 'localhost:'.$port, + [ + 'grpc.ssl_target_name_override' => $host_override, + 'grpc.default_authority' => $host_override, + 'credentials' => $credentials, + ] +); + +// Test CreateComposite +$call_credentials2 = Grpc\CallCredentials::createFromPlugin('callbackFunc'); +$call_credentials3 = Grpc\CallCredentials::createComposite( + $call_credentials, + $call_credentials2 +); +assert('Grpc\CallCredentials' == get_class($call_credentials3)); + +// Test CreateFromPluginInvalidParam +try{ + $call_credentials = Grpc\CallCredentials::createFromPlugin( + 'callbackFunc' + ); +} +catch(\Exception $e){} + +// Test CreateCompositeInvalidParam +try{ + $call_credentials3 = Grpc\CallCredentials::createComposite( + $call_credentials, + $credentials + ); +} +catch(\Exception $e){} + +unset($channel); +unset($server); + + +//============== EndToEnd Test ==================== +// Set Up +$server = new Grpc\Server([]); +$port = $server->addHttp2Port('0.0.0.0:0'); +$channel = new Grpc\Channel('localhost:'.$port, []); +$server->start(); + +// Test SimpleRequestBody +$deadline = Grpc\Timeval::infFuture(); +$status_text = 'xyz'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline); +$event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, +]); +assert($event->send_metadata == true); +assert($event->send_close == true); + +$event = $server->requestCall(); +assert('dummy_method' == $event->method); + +$server_call = $event->call; +$event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => $status_text, + ], + Grpc\OP_RECV_CLOSE_ON_SERVER => true, +]); +assert($event->send_metadata == true); +assert($event->send_status == true); +assert($event->cancelled == false) +; + $event = $call->startBatch([ + Grpc\OP_RECV_INITIAL_METADATA => true, + Grpc\OP_RECV_STATUS_ON_CLIENT => true, +]); +$status = $event->status; +assert([] == $status->metadata); +assert(Grpc\STATUS_OK == $status->code); +assert($status_text == $status->details); + +unset($call); +unset($server_call); + +// Test MessageWriteFlags +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'message_write_flags_test'; +$status_text = 'xyz'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline); +$event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_MESSAGE => ['message' => $req_text, + 'flags' => Grpc\WRITE_NO_COMPRESS, ], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, +]); +assert($event->send_metadata == true); +assert($event->send_close == true); + +$event = $server->requestCall(); +assert('dummy_method' == $event->method); + +$server_call = $event->call; +$event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => $status_text, + ], +]); +$event = $call->startBatch([ + Grpc\OP_RECV_INITIAL_METADATA => true, + Grpc\OP_RECV_STATUS_ON_CLIENT => true, +]); +$status = $event->status; + +assert([] == $status->metadata); +assert(Grpc\STATUS_OK == $status->code); +assert($status_text == $status->details); + +unset($call); +unset($server_call); + +// Test ClientServerFullRequestResponse +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'client_server_full_request_response'; +$reply_text = 'reply:client_server_full_request_response'; +$status_text = 'status:client_server_full_response_text'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline); + $event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + Grpc\OP_SEND_MESSAGE => ['message' => $req_text], +]); +assert($event->send_metadata == true); +assert($event->send_close == true); +assert($event->send_message == true); + +$event = $server->requestCall(); +assert('dummy_method' == $event->method); +$server_call = $event->call; + +$event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => $status_text, + ], + Grpc\OP_RECV_MESSAGE => true, + Grpc\OP_RECV_CLOSE_ON_SERVER => true, +]); +assert($event->send_metadata == true); +assert($event->send_status == true); +assert($event->send_message == true); +assert($event->cancelled == false); +assert($req_text == $event->message); + +$event = $call->startBatch([ + Grpc\OP_RECV_INITIAL_METADATA => true, + Grpc\OP_RECV_MESSAGE => true, + Grpc\OP_RECV_STATUS_ON_CLIENT => true, +]); +assert([] == $event->metadata); +assert($reply_text == $event->message); +$status = $event->status; +assert([] == $status->metadata); +assert(Grpc\STATUS_OK == $status->code); +assert($status_text == $status->details); + +unset($call); +unset($server_call); + +// Test InvalidClientMessageArray +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'client_server_full_request_response'; +$reply_text = 'reply:client_server_full_request_response'; +$status_text = 'status:client_server_full_response_text'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline); +try { + $event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + Grpc\OP_SEND_MESSAGE => 'invalid', + ]); +} catch (\Exception $e) {} + +// Test InvalidClientMessageString +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'client_server_full_request_response'; +$reply_text = 'reply:client_server_full_request_response'; +$status_text = 'status:client_server_full_response_text'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline); +try{ + $event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + Grpc\OP_SEND_MESSAGE => ['message' => 0], + ]); +} catch (\Exception $e) {} + +// Test InvalidClientMessageFlags +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'client_server_full_request_response'; +$reply_text = 'reply:client_server_full_request_response'; +$status_text = 'status:client_server_full_response_text'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline); +try{ + $event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + Grpc\OP_SEND_MESSAGE => ['message' => 'abc', + 'flags' => 'invalid', + ], + ]); +} catch (\Exception $e) {} + +// Test InvalidServerStatusMetadata +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'client_server_full_request_response'; +$reply_text = 'reply:client_server_full_request_response'; +$status_text = 'status:client_server_full_response_text'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline); +$event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + Grpc\OP_SEND_MESSAGE => ['message' => $req_text], +]); +assert($event->send_metadata == true); +assert($event->send_close == true); +assert($event->send_message == true); + +$event = $server->requestCall(); +assert('dummy_method' == $event->method); +$server_call = $event->call; +try { + $event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => 'invalid', + 'code' => Grpc\STATUS_OK, + 'details' => $status_text, + ], + Grpc\OP_RECV_MESSAGE => true, + Grpc\OP_RECV_CLOSE_ON_SERVER => true, + ]); +} catch (\Exception $e) {} + +// Test InvalidServerStatusCode +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'client_server_full_request_response'; +$reply_text = 'reply:client_server_full_request_response'; +$status_text = 'status:client_server_full_response_text'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline); +$event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + Grpc\OP_SEND_MESSAGE => ['message' => $req_text], +]); +assert($event->send_metadata == true); +assert($event->send_close == true); +assert($event->send_message == true); + +$event = $server->requestCall(); +assert('dummy_method' == $event->method); +$server_call = $event->call; +try { + $event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => 'invalid', + 'details' => $status_text, + ], + Grpc\OP_RECV_MESSAGE => true, + Grpc\OP_RECV_CLOSE_ON_SERVER => true, + ]); +} catch (\Exception $e) {} + +// Test MissingServerStatusCode +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'client_server_full_request_response'; +$reply_text = 'reply:client_server_full_request_response'; +$status_text = 'status:client_server_full_response_text'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline); +$event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + Grpc\OP_SEND_MESSAGE => ['message' => $req_text], +]); +$event = $server->requestCall(); +$server_call = $event->call; +try { + $event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'details' => $status_text, + ], + Grpc\OP_RECV_MESSAGE => true, + Grpc\OP_RECV_CLOSE_ON_SERVER => true, + ]); +} catch (\Exception $e) {} + +// Test InvalidServerStatusDetails +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'client_server_full_request_response'; +$reply_text = 'reply:client_server_full_request_response'; +$status_text = 'status:client_server_full_response_text'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline); +$event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + Grpc\OP_SEND_MESSAGE => ['message' => $req_text], +]); +$event = $server->requestCall(); +$server_call = $event->call; +try { + $event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => 0, + ], + Grpc\OP_RECV_MESSAGE => true, + Grpc\OP_RECV_CLOSE_ON_SERVER => true, + ]); +} catch (\Exception $e) {} + +// Test MissingServerStatusDetails +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'client_server_full_request_response'; +$reply_text = 'reply:client_server_full_request_response'; +$status_text = 'status:client_server_full_response_text'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline); +$event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + Grpc\OP_SEND_MESSAGE => ['message' => $req_text], +]); +$event = $server->requestCall(); +$server_call = $event->call; +try { + $event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + ], + Grpc\OP_RECV_MESSAGE => true, + Grpc\OP_RECV_CLOSE_ON_SERVER => true, + ]); +} catch (\Exception $e) {} + +// Test InvalidStartBatchKey +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'client_server_full_request_response'; +$reply_text = 'reply:client_server_full_request_response'; +$status_text = 'status:client_server_full_response_text'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline); +try { + $event = $call->startBatch([ + 9999999 => [], + ]); +} catch (\Exception $e) {} + +// Test InvalidStartBatch +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'client_server_full_request_response'; +$reply_text = 'reply:client_server_full_request_response'; +$status_text = 'status:client_server_full_response_text'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline); +try { + $event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + Grpc\OP_SEND_MESSAGE => ['message' => $req_text], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => 'abc', + ], + ]); +} catch (\Exception $e) {} + +// Test GetTarget +assert(is_string($channel->getTarget()) == true); + +// Test GetConnectivityState +assert(($channel->getConnectivityState() == + Grpc\CHANNEL_IDLE) == true); + +// Test WatchConnectivityStateFailed +$idle_state = $channel->getConnectivityState(); +assert(($idle_state == Grpc\CHANNEL_IDLE) == true); + +$now = Grpc\Timeval::now(); +$delta = new Grpc\Timeval(50000); // should timeout +$deadline = $now->add($delta); +assert($channel->watchConnectivityState( + $idle_state, $deadline) == false); + +// Test WatchConnectivityStateSuccess() +$idle_state = $channel->getConnectivityState(true); +assert(($idle_state == Grpc\CHANNEL_IDLE) == true); + +$now = Grpc\Timeval::now(); +$delta = new Grpc\Timeval(3000000); // should finish well before +$deadline = $now->add($delta); +$new_state = $channel->getConnectivityState(); +assert($new_state != $idle_state); + +// Test WatchConnectivityStateDoNothing +$idle_state = $channel->getConnectivityState(); +$now = Grpc\Timeval::now(); +$delta = new Grpc\Timeval(50000); +$deadline = $now->add($delta); +assert(!$channel->watchConnectivityState( + $idle_state, $deadline)); + +$new_state = $channel->getConnectivityState(); +assert($new_state == Grpc\CHANNEL_IDLE); + +// Test GetConnectivityStateInvalidParam +try { + $channel->getConnectivityState(new Grpc\Timeval()); +} catch (\Exception $e) {} +// Test WatchConnectivityStateInvalidParam +try { + $channel->watchConnectivityState(0, 1000); +} catch (\Exception $e) {} +// Test ChannelConstructorInvalidParam +try { + $channel = new Grpc\Channel('localhost:'.$port, null); +} catch (\Exception $e) {} +// testClose() +$channel->close(); + + +//============== SecureEndToEnd Test ==================== +// Set Up + +$credentials = Grpc\ChannelCredentials::createSsl( + file_get_contents(dirname(__FILE__).'/../data/ca.pem')); +$server_credentials = Grpc\ServerCredentials::createSsl( + null, + file_get_contents(dirname(__FILE__).'/../data/server1.key'), + file_get_contents(dirname(__FILE__).'/../data/server1.pem')); +$server = new Grpc\Server(); +$port = $server->addSecureHttp2Port('0.0.0.0:0', + $server_credentials); +$server->start(); +$host_override = 'foo.test.google.fr'; +$channel = new Grpc\Channel( + 'localhost:'.$port, + [ + 'grpc.ssl_target_name_override' => $host_override, + 'grpc.default_authority' => $host_override, + 'credentials' => $credentials, + ] +); + +// Test SimpleRequestBody +$deadline = Grpc\Timeval::infFuture(); +$status_text = 'xyz'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline, + $host_override); + $event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, +]); +assert($event->send_metadata == true); +assert($event->send_close == true); + +$event = $server->requestCall(); +assert('dummy_method' == $event->method); + +$server_call = $event->call; +$event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => $status_text, + ], + Grpc\OP_RECV_CLOSE_ON_SERVER => true, +]); +assert($event->send_metadata == true); +assert($event->send_status == true); +assert($event->cancelled == false); + +$event = $call->startBatch([ + Grpc\OP_RECV_INITIAL_METADATA => true, + Grpc\OP_RECV_STATUS_ON_CLIENT => true, +]); +assert([] == $event->metadata); +$status = $event->status; +assert([] == $status->metadata); +assert(Grpc\STATUS_OK == $status->code); +assert($status_text == $status->details); + +unset($call); +unset($server_call); + +// Test MessageWriteFlags +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'message_write_flags_test'; +$status_text = 'xyz'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline, + $host_override); + $event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_MESSAGE => ['message' => $req_text, + 'flags' => Grpc\WRITE_NO_COMPRESS, ], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, +]); +assert($event->send_metadata == true); +assert($event->send_close == true); + +$event = $server->requestCall(); +assert('dummy_method' == $event->method); + +$server_call = $event->call; +$event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => $status_text, + ], +]); +$event = $call->startBatch([ + Grpc\OP_RECV_INITIAL_METADATA => true, + Grpc\OP_RECV_STATUS_ON_CLIENT => true, +]); +assert([] == $event->metadata); +$status = $event->status; +assert([] == $status->metadata); +assert(Grpc\STATUS_OK == $status->code); +assert($status_text == $status->details);unset($call); + +unset($call); +unset($server_call); + +// Test ClientServerFullRequestResponse +$deadline = Grpc\Timeval::infFuture(); +$req_text = 'client_server_full_request_response'; +$reply_text = 'reply:client_server_full_request_response'; +$status_text = 'status:client_server_full_response_text'; +$call = new Grpc\Call($channel, + 'dummy_method', + $deadline, + $host_override); +$event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + Grpc\OP_SEND_MESSAGE => ['message' => $req_text], +]); +assert($event->send_metadata == true); +assert($event->send_close == true); +assert($event->send_message == true); + +$event = $server->requestCall(); +assert('dummy_method' == $event->method); + +$server_call = $event->call; +$event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => $status_text, + ], + Grpc\OP_RECV_MESSAGE => true, + Grpc\OP_RECV_CLOSE_ON_SERVER => true, +]); +assert($event->send_metadata); +assert($event->send_status); +assert($event->send_message); +assert(!$event->cancelled); +assert($req_text == $event->message); + +$event = $call->startBatch([ + Grpc\OP_RECV_INITIAL_METADATA => true, + Grpc\OP_RECV_MESSAGE => true, + Grpc\OP_RECV_STATUS_ON_CLIENT => true, +]); +assert([] == $event->metadata); +assert($reply_text == $event->message); +$status = $event->status; +assert([] == $status->metadata); +assert(Grpc\STATUS_OK == $status->code); +assert($status_text == $status->details); + +unset($call); +unset($server_call); + +$channel->close(); + + +//============== Timeval Test ==================== +// Test ConstructorWithInt +$time = new Grpc\Timeval(1234); +assert($time != NULL); +assert('Grpc\Timeval' == get_class($time)); + +// Test ConstructorWithNegative +$time = new Grpc\Timeval(-123); +assert($time != NULL); +assert('Grpc\Timeval' == get_class($time)); + +// Test ConstructorWithZero +$time = new Grpc\Timeval(0); +assert($time != NULL); +assert('Grpc\Timeval' == get_class($time)); + +// Test ConstructorWithOct +$time = new Grpc\Timeval(0123); +assert($time != NULL); +assert('Grpc\Timeval' == get_class($time)); + +// Test ConstructorWithHex +$time = new Grpc\Timeval(0x1A); +assert($time != NULL); +assert('Grpc\Timeval' == get_class($time)); + +// Test ConstructorWithFloat +$time = new Grpc\Timeval(123.456); +assert($time != NULL); +assert('Grpc\Timeval' == get_class($time)); + +// Test CompareSame +$zero = Grpc\Timeval::zero(); +assert(0 == Grpc\Timeval::compare($zero, $zero)); + +// Test PastIsLessThanZero +$zero = Grpc\Timeval::zero(); +$past = Grpc\Timeval::infPast(); +assert(0 > Grpc\Timeval::compare($past, $zero)); +assert(0 < Grpc\Timeval::compare($zero, $past)); + +// Test FutureIsGreaterThanZero +$zero = Grpc\Timeval::zero(); +$future = Grpc\Timeval::infFuture(); +assert(0 > Grpc\Timeval::compare($zero, $future)); +assert(0 < Grpc\Timeval::compare($future, $zero)); + +// Test NowIsBetweenZeroAndFuture +$zero = Grpc\Timeval::zero(); +$future = Grpc\Timeval::infFuture(); +$now = Grpc\Timeval::now(); +assert(0 > Grpc\Timeval::compare($zero, $now)); +assert(0 > Grpc\Timeval::compare($now, $future)); + +// Test NowAndAdd +$now = Grpc\Timeval::now(); +assert($now != NULL); +$delta = new Grpc\Timeval(1000); +$deadline = $now->add($delta); +assert(0 < Grpc\Timeval::compare($deadline, $now)); + +// Test NowAndSubtract +$now = Grpc\Timeval::now(); +$delta = new Grpc\Timeval(1000); +$deadline = $now->subtract($delta); +assert(0 > Grpc\Timeval::compare($deadline, $now)); + +// Test AddAndSubtract +$now = Grpc\Timeval::now(); +$delta = new Grpc\Timeval(1000); +$deadline = $now->add($delta); +$back_to_now = $deadline->subtract($delta); +assert(0 == Grpc\Timeval::compare($back_to_now, $now)); + +// Test Similar +$a = Grpc\Timeval::now(); +$delta = new Grpc\Timeval(1000); +$b = $a->add($delta); +$thresh = new Grpc\Timeval(1100); +assert(Grpc\Timeval::similar($a, $b, $thresh)); +$thresh = new Grpc\Timeval(900); +assert(!Grpc\Timeval::similar($a, $b, $thresh)); + +// Test SleepUntil +$curr_microtime = microtime(true); +$now = Grpc\Timeval::now(); +$delta = new Grpc\Timeval(1000); +$deadline = $now->add($delta); +$deadline->sleepUntil(); +$done_microtime = microtime(true); +assert(($done_microtime - $curr_microtime) > 0.0009); + +// Test ConstructorInvalidParam +try { + $delta = new Grpc\Timeval('abc'); +} catch (\Exception $e) {} +// Test AddInvalidParam +$a = Grpc\Timeval::now(); +try { + $a->add(1000); +} catch (\Exception $e) {} +// Test SubtractInvalidParam +$a = Grpc\Timeval::now(); +try { + $a->subtract(1000); +} catch (\Exception $e) {} +// Test CompareInvalidParam +try { + $a = Grpc\Timeval::compare(1000, 1100); +} catch (\Exception $e) {} +// Test SimilarInvalidParam +try { + $a = Grpc\Timeval::similar(1000, 1100, 1200); +} catch (\Exception $e) {} + unset($time); + + //============== Server Test ==================== + //Set Up + $server = NULL; + + // Test ConstructorWithNull +$server = new Grpc\Server(); +assert($server != NULL); + +// Test ConstructorWithNullArray +$server = new Grpc\Server([]); +assert($server != NULL); + +// Test ConstructorWithArray +$server = new Grpc\Server(['ip' => '127.0.0.1', + 'port' => '8080', ]); +assert($server != NULL); + +// Test RequestCall +$server = new Grpc\Server(); +$port = $server->addHttp2Port('0.0.0.0:0'); +$server->start(); +$channel = new Grpc\Channel('localhost:'.$port, + [ + 'force_new' => true, + 'credentials' => Grpc\ChannelCredentials::createInsecure() + ]); + +$deadline = Grpc\Timeval::infFuture(); +$call = new Grpc\Call($channel, 'dummy_method', $deadline); + +$event = $call->startBatch([Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + ]); + +$c = $server->requestCall(); +assert('dummy_method' == $c->method); +assert(is_string($c->host)); + +unset($call); +unset($channel); + +// Test InvalidConstructorWithNumKeyOfArray +try{ + $server = new Grpc\Server([10 => '127.0.0.1', + 20 => '8080', ]); +} +catch(\Exception $e){} + +// Test Invalid ArgumentException +try{ + $server = new Grpc\Server(['127.0.0.1', '8080']); +} +catch(\Exception $e){} + +// Test InvalidAddHttp2Port +$server = new Grpc\Server([]); +try{ + $port = $server->addHttp2Port(['0.0.0.0:0']); +} +catch(\Exception $e){} + +// Test InvalidAddSecureHttp2Port +$server = new Grpc\Server([]); +try{ + $port = $server->addSecureHttp2Port(['0.0.0.0:0']); +} +catch(\Exception $e){} + +// Test InvalidAddSecureHttp2Port2 +$server = new Grpc\Server(); +try{ + $port = $server->addSecureHttp2Port('0.0.0.0:0'); +} +catch(\Exception $e){} + +// Test InvalidAddSecureHttp2Port3 +$server = new Grpc\Server(); +try{ + $port = $server->addSecureHttp2Port('0.0.0.0:0', 'invalid'); +} +catch(\Exception $e){} +unset($server); + + +//============== ChannelCredential Test ==================== +// Test CreateSslWith3Null +$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null, + null); +assert($channel_credentials != NULL); + +// Test CreateSslWith3NullString +$channel_credentials = Grpc\ChannelCredentials::createSsl('', '', ''); +assert($channel_credentials != NULL); + +// Test CreateInsecure +$channel_credentials = Grpc\ChannelCredentials::createInsecure(); +assert($channel_credentials == NULL); + +// Test InvalidCreateSsl() +try { + $channel_credentials = Grpc\ChannelCredentials::createSsl([]); +} +catch (\Exception $e) { +} +try { + $channel_credentials = Grpc\ChannelCredentials::createComposite( + 'something', 'something'); +} +catch (\Exception $e) { +} + +//============== Interceptor Test ==================== +require_once(dirname(__FILE__).'/../../lib/Grpc/BaseStub.php'); +require_once(dirname(__FILE__).'/../../lib/Grpc/AbstractCall.php'); +require_once(dirname(__FILE__).'/../../lib/Grpc/UnaryCall.php'); +require_once(dirname(__FILE__).'/../../lib/Grpc/ClientStreamingCall.php'); +require_once(dirname(__FILE__).'/../../lib/Grpc/Interceptor.php'); +require_once(dirname(__FILE__).'/../../lib/Grpc/CallInvoker.php'); +require_once(dirname(__FILE__).'/../../lib/Grpc/DefaultCallInvoker.php'); +require_once(dirname(__FILE__).'/../../lib/Grpc/Internal/InterceptorChannel.php'); + +class SimpleRequest +{ + private $data; + public function __construct($data) + { + $this->data = $data; + } + public function setData($data) + { + $this->data = $data; + } + public function serializeToString() + { + return $this->data; + } +} + +class InterceptorClient extends Grpc\BaseStub +{ + + /** + * @param string $hostname hostname + * @param array $opts channel options + * @param Channel|InterceptorChannel $channel (optional) re-use channel object + */ + public function __construct($hostname, $opts, $channel = null) + { + parent::__construct($hostname, $opts, $channel); + } + + /** + * A simple RPC. + * @param SimpleRequest $argument input argument + * @param array $metadata metadata + * @param array $options call options + */ + public function UnaryCall( + SimpleRequest $argument, + $metadata = [], + $options = [] + ) { + return $this->_simpleRequest( + '/dummy_method', + $argument, + [], + $metadata, + $options + ); + } + + /** + * A client-to-server streaming RPC. + * @param array $metadata metadata + * @param array $options call options + */ + public function StreamCall( + $metadata = [], + $options = [] + ) { + return $this->_clientStreamRequest('/dummy_method', [], $metadata, $options); + } +} + +class ChangeMetadataInterceptor extends Grpc\Interceptor +{ + public function interceptUnaryUnary($method, + $argument, + $deserialize, + array $metadata = [], + array $options = [], + $continuation) + { + $metadata["foo"] = array('interceptor_from_unary_request'); + return $continuation($method, $argument, $deserialize, $metadata, $options); + } + public function interceptStreamUnary($method, $deserialize, array $metadata = [], array $options = [], $continuation) + { + $metadata["foo"] = array('interceptor_from_stream_request'); + return $continuation($method, $deserialize, $metadata, $options); + } +} + +class ChangeMetadataInterceptor2 extends Grpc\Interceptor +{ + public function interceptUnaryUnary($method, + $argument, + $deserialize, + array $metadata = [], + array $options = [], + $continuation) + { + if (array_key_exists('foo', $metadata)) { + $metadata['bar'] = array('ChangeMetadataInterceptor should be executed first'); + } else { + $metadata["bar"] = array('interceptor_from_unary_request'); + } + return $continuation($method, $argument, $deserialize, $metadata, $options); + } + public function interceptStreamUnary($method, + $deserialize, + array $metadata = [], + array $options = [], + $continuation) + { + if (array_key_exists('foo', $metadata)) { + $metadata['bar'] = array('ChangeMetadataInterceptor should be executed first'); + } else { + $metadata["bar"] = array('interceptor_from_stream_request'); + } + return $continuation($method, $deserialize, $metadata, $options); + } +} + +class ChangeRequestCall +{ + private $call; + + public function __construct($call) + { + $this->call = $call; + } + public function getCall() + { + return $this->call; + } + + public function write($request) + { + $request->setData('intercepted_stream_request'); + $this->getCall()->write($request); + } + + public function wait() + { + return $this->getCall()->wait(); + } +} + +class ChangeRequestInterceptor extends Grpc\Interceptor +{ + public function interceptUnaryUnary($method, + $argument, + $deserialize, + array $metadata = [], + array $options = [], + $continuation) + { + $argument->setData('intercepted_unary_request'); + return $continuation($method, $argument, $deserialize, $metadata, $options); + } + public function interceptStreamUnary($method, $deserialize, array $metadata = [], array $options = [], $continuation) + { + return new ChangeRequestCall( + $continuation($method, $deserialize, $metadata, $options) + ); + } +} + +class StopCallInterceptor extends Grpc\Interceptor +{ + public function interceptUnaryUnary($method, + $argument, + array $metadata = [], + array $options = [], + $continuation) + { + $metadata["foo"] = array('interceptor_from_request_response'); + } + public function interceptStreamUnary($method, + array $metadata = [], + array $options = [], + $continuation) + { + $metadata["foo"] = array('interceptor_from_request_response'); + } +} + +// Set Up +$server = new Grpc\Server([]); +$port = $server->addHttp2Port('0.0.0.0:0'); +$channel = new Grpc\Channel('localhost:'.$port, [ + 'force_new' => true, + 'credentials' => Grpc\ChannelCredentials::createInsecure()]); +$server->start(); + +// Test ClientChangeMetadataOneInterceptor +$req_text = 'client_request'; +$channel_matadata_interceptor = new ChangeMetadataInterceptor(); +$intercept_channel = Grpc\Interceptor::intercept($channel, $channel_matadata_interceptor); +$client = new InterceptorClient('localhost:'.$port, [ + 'force_new' => true, + 'credentials' => Grpc\ChannelCredentials::createInsecure(), +], $intercept_channel); +$req = new SimpleRequest($req_text); +$unary_call = $client->UnaryCall($req); +$event = $server->requestCall(); +assert('/dummy_method' == $event->method); +assert(['interceptor_from_unary_request'] == $event->metadata['foo']); + +$stream_call = $client->StreamCall(); +$stream_call->write($req); +$event = $server->requestCall(); +assert('/dummy_method' == $event->method); +assert(['interceptor_from_stream_request'] == $event->metadata['foo']); + +unset($unary_call); +unset($stream_call); +unset($server_call); + +// Test ClientChangeMetadataTwoInterceptor +$req_text = 'client_request'; +$channel_matadata_interceptor = new ChangeMetadataInterceptor(); +$channel_matadata_intercepto2 = new ChangeMetadataInterceptor2(); +// test intercept separately. +$intercept_channel1 = Grpc\Interceptor::intercept($channel, $channel_matadata_interceptor); +$intercept_channel2 = Grpc\Interceptor::intercept($intercept_channel1, $channel_matadata_intercepto2); +$client = new InterceptorClient('localhost:'.$port, [ + 'force_new' => true, + 'credentials' => Grpc\ChannelCredentials::createInsecure(), +], $intercept_channel2); + +$req = new SimpleRequest($req_text); +$unary_call = $client->UnaryCall($req); +$event = $server->requestCall(); +assert('/dummy_method' == $event->method); +assert(['interceptor_from_unary_request'] == $event->metadata['foo']); +assert(['interceptor_from_unary_request'] == $event->metadata['bar']); + +$stream_call = $client->StreamCall(); +$stream_call->write($req); +$event = $server->requestCall(); +assert('/dummy_method' == $event->method); +assert(['interceptor_from_stream_request'] == $event->metadata['foo']); +assert(['interceptor_from_stream_request'] == $event->metadata['bar']); + +unset($unary_call); +unset($stream_call); +unset($server_call); + +// test intercept by array. +$intercept_channel3 = Grpc\Interceptor::intercept($channel, + [$channel_matadata_intercepto2, $channel_matadata_interceptor]); +$client = new InterceptorClient('localhost:'.$port, [ + 'force_new' => true, + 'credentials' => Grpc\ChannelCredentials::createInsecure(), +], $intercept_channel3); + +$req = new SimpleRequest($req_text); +$unary_call = $client->UnaryCall($req); +$event = $server->requestCall(); +assert('/dummy_method' == $event->method); +assert(['interceptor_from_unary_request'] == $event->metadata['foo']); +assert(['interceptor_from_unary_request'] == $event->metadata['bar']); + +$stream_call = $client->StreamCall(); +$stream_call->write($req); +$event = $server->requestCall(); +assert('/dummy_method' == $event->method); +assert(['interceptor_from_stream_request'] == $event->metadata['foo']); +assert(['interceptor_from_stream_request'] == $event->metadata['bar']); + +unset($unary_call); +unset($stream_call); +unset($server_call); + + +// Test ClientChangeRequestInterceptor +$req_text = 'client_request'; +$change_request_interceptor = new ChangeRequestInterceptor(); +$intercept_channel = Grpc\Interceptor::intercept($channel, + $change_request_interceptor); +$client = new InterceptorClient('localhost:'.$port, [ + 'force_new' => true, + 'credentials' => Grpc\ChannelCredentials::createInsecure(), +], $intercept_channel); + +$req = new SimpleRequest($req_text); +$unary_call = $client->UnaryCall($req); + +$event = $server->requestCall(); +assert('/dummy_method' == $event->method); +$server_call = $event->call; +$event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => '', + ], + Grpc\OP_RECV_MESSAGE => true, + Grpc\OP_RECV_CLOSE_ON_SERVER => true, +]); +assert('intercepted_unary_request' == $event->message); + +$stream_call = $client->StreamCall(); +$stream_call->write($req); +$event = $server->requestCall(); +assert('/dummy_method' == $event->method); +$server_call = $event->call; +$event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => '', + ], + Grpc\OP_RECV_MESSAGE => true, + Grpc\OP_RECV_CLOSE_ON_SERVER => true, +]); +assert('intercepted_stream_request' == $event->message); + +unset($unary_call); +unset($stream_call); +unset($server_call); + +// Test ClientChangeStopCallInterceptor +$req_text = 'client_request'; +$channel_request_interceptor = new StopCallInterceptor(); +$intercept_channel = Grpc\Interceptor::intercept($channel, + $channel_request_interceptor); +$client = new InterceptorClient('localhost:'.$port, [ + 'force_new' => true, + 'credentials' => Grpc\ChannelCredentials::createInsecure(), +], $intercept_channel); + +$req = new SimpleRequest($req_text); +$unary_call = $client->UnaryCall($req); +assert($unary_call == NULL); + + +$stream_call = $client->StreamCall(); +assert($stream_call == NULL); + +unset($unary_call); +unset($stream_call); +unset($server_call); + +// Test GetInterceptorChannelConnectivityState +$channel = new Grpc\Channel( + 'localhost:0', + [ + 'force_new' => true, + 'credentials' => Grpc\ChannelCredentials::createInsecure() + ] +); +$interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor()); +$state = $interceptor_channel->getConnectivityState(); +assert(0 == $state); +$channel->close(); + +// Test InterceptorChannelWatchConnectivityState +$channel = new Grpc\Channel( + 'localhost:0', + [ + 'force_new' => true, + 'credentials' => Grpc\ChannelCredentials::createInsecure() + ] +); +$interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor()); +$now = Grpc\Timeval::now(); +$deadline = $now->add(new Grpc\Timeval(100*1000)); +$state = $interceptor_channel->watchConnectivityState(1, $deadline); +assert($state); +unset($time); +unset($deadline); +$channel->close(); + +// Test InterceptorChannelClose +$channel = new Grpc\Channel( + 'localhost:0', + [ + 'force_new' => true, + 'credentials' => Grpc\ChannelCredentials::createInsecure() + ] +); +$interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor()); +assert($interceptor_channel != NULL); +$channel->close(); + +// Test InterceptorChannelGetTarget +$channel = new Grpc\Channel( + 'localhost:8888', + [ + 'force_new' => true, + 'credentials' => Grpc\ChannelCredentials::createInsecure() + ] +); +$interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor()); +$target = $interceptor_channel->getTarget(); +assert(is_string($target)); + +$channel->close(); +unset($server); + + +//============== CallInvoker Test ==================== +class CallInvokerSimpleRequest +{ + private $data; + public function __construct($data) + { + $this->data = $data; + } + public function setData($data) + { + $this->data = $data; + } + public function serializeToString() + { + return $this->data; + } +} + +class CallInvokerClient extends Grpc\BaseStub +{ + + /** + * @param string $hostname hostname + * @param array $opts channel options + * @param Channel|InterceptorChannel $channel (optional) re-use channel object + */ + public function __construct($hostname, $opts, $channel = null) + { + parent::__construct($hostname, $opts, $channel); + } + + /** + * A simple RPC. + * @param SimpleRequest $argument input argument + * @param array $metadata metadata + * @param array $options call options + */ + public function UnaryCall( + CallInvokerSimpleRequest $argument, + $metadata = [], + $options = [] + ) { + return $this->_simpleRequest( + '/dummy_method', + $argument, + [], + $metadata, + $options + ); + } +} + +class CallInvokerUpdateChannel implements \Grpc\CallInvoker +{ + private $channel; + + public function getChannel() { + return $this->channel; + } + + public function createChannelFactory($hostname, $opts) { + $this->channel = new \Grpc\Channel('localhost:50050', $opts); + return $this->channel; + } + + public function UnaryCall($channel, $method, $deserialize, $options) { + return new UnaryCall($channel, $method, $deserialize, $options); + } + + public function ClientStreamingCall($channel, $method, $deserialize, $options) { + return new ClientStreamingCall($channel, $method, $deserialize, $options); + } + + public function ServerStreamingCall($channel, $method, $deserialize, $options) { + return new ServerStreamingCall($channel, $method, $deserialize, $options); + } + + public function BidiStreamingCall($channel, $method, $deserialize, $options) { + return new BidiStreamingCall($channel, $method, $deserialize, $options); + } +} + +class CallInvokerChangeRequest implements \Grpc\CallInvoker +{ + private $channel; + + public function getChannel() { + return $this->channel; + } + public function createChannelFactory($hostname, $opts) { + $this->channel = new \Grpc\Channel($hostname, $opts); + return $this->channel; + } + + public function UnaryCall($channel, $method, $deserialize, $options) { + return new CallInvokerChangeRequestCall($channel, $method, $deserialize, $options); + } + + public function ClientStreamingCall($channel, $method, $deserialize, $options) { + return new ClientStreamingCall($channel, $method, $deserialize, $options); + } + + public function ServerStreamingCall($channel, $method, $deserialize, $options) { + return new ServerStreamingCall($channel, $method, $deserialize, $options); + } + + public function BidiStreamingCall($channel, $method, $deserialize, $options) { + return new BidiStreamingCall($channel, $method, $deserialize, $options); + } +} + +class CallInvokerChangeRequestCall +{ + private $call; + + public function __construct($channel, $method, $deserialize, $options) + { + $this->call = new \Grpc\UnaryCall($channel, $method, $deserialize, $options); + } + + public function start($argument, $metadata, $options) { + $argument->setData('intercepted_unary_request'); + $this->call->start($argument, $metadata, $options); + } + + public function wait() + { + return $this->call->wait(); + } +} + +// Set Up +$server = new Grpc\Server([]); +$port = $server->addHttp2Port('0.0.0.0:0'); +$server->start(); + +// Test CreateDefaultCallInvoker +$call_invoker = new \Grpc\DefaultCallInvoker(); + +// Test CreateCallInvoker +$call_invoker = new CallInvokerUpdateChannel(); + +// Test CallInvokerAccessChannel +$call_invoker = new CallInvokerUpdateChannel(); +$stub = new \Grpc\BaseStub('localhost:50051', + ['credentials' => \Grpc\ChannelCredentials::createInsecure(), + 'grpc_call_invoker' => $call_invoker]); +assert($call_invoker->getChannel()->getTarget() == 'localhost:50050'); +$call_invoker->getChannel()->close(); + +// Test ClientChangeRequestCallInvoker +$req_text = 'client_request'; +$call_invoker = new CallInvokerChangeRequest(); +$client = new CallInvokerClient('localhost:'.$port, [ + 'force_new' => true, + 'credentials' => Grpc\ChannelCredentials::createInsecure(), + 'grpc_call_invoker' => $call_invoker, +]); + +$req = new CallInvokerSimpleRequest($req_text); +$unary_call = $client->UnaryCall($req); + +$event = $server->requestCall(); +assert('/dummy_method' == $event->method); +$server_call = $event->call; +$event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => '', + ], + Grpc\OP_RECV_MESSAGE => true, + Grpc\OP_RECV_CLOSE_ON_SERVER => true, +]); +assert('intercepted_unary_request' == $event->message); +$call_invoker->getChannel()->close(); +unset($unary_call); +unset($server_call); + +unset($server); + +<<<<<<< HEAD +<<<<<<< HEAD +echo "Went Through All Unit Tests..............\r\n"; +======= +echo "Went Through All Unit Tests.............."; +>>>>>>> add MemoryLeakTest +======= +echo "Went Through All Unit Tests..............\r\n"; +>>>>>>> complete memory leak test + + diff --git a/src/php/tests/unit_tests/CallTest.php b/src/php/tests/unit_tests/CallTest.php index be1d77fe7ad..20c35299cb0 100644 --- a/src/php/tests/unit_tests/CallTest.php +++ b/src/php/tests/unit_tests/CallTest.php @@ -86,6 +86,26 @@ class CallTest extends PHPUnit_Framework_TestCase $this->assertTrue($result->send_metadata); } + public function testAddMultiAndMultiValueMetadata() + { + $batch = [ + Grpc\OP_SEND_INITIAL_METADATA => ['key1' => ['value1', 'value2'], + 'key2' => ['value3', 'value4'],], + ]; + $result = $this->call->startBatch($batch); + $this->assertTrue($result->send_metadata); + } + + public function testAddMultiAndMultiValueMetadata() + { + $batch = [ + Grpc\OP_SEND_INITIAL_METADATA => ['key1' => ['value1', 'value2'], + 'key2' => ['value3', 'value4'],], + ]; + $result = $this->call->startBatch($batch); + $this->assertTrue($result->send_metadata); + } + public function testGetPeer() { $this->assertTrue(is_string($this->call->getPeer())); From 22fb5ce2fbd4d69d9952d82954139e29f1fad7bd Mon Sep 17 00:00:00 2001 From: Maxim Bunkov Date: Fri, 18 Jan 2019 05:24:00 +0500 Subject: [PATCH 020/218] Change back to script --- .../BoringSSL-GRPC.podspec.template | 2975 +---------------- 1 file changed, 2 insertions(+), 2973 deletions(-) diff --git a/templates/src/objective-c/BoringSSL-GRPC.podspec.template b/templates/src/objective-c/BoringSSL-GRPC.podspec.template index 8b2a23ae0c5..6804f75f1b0 100644 --- a/templates/src/objective-c/BoringSSL-GRPC.podspec.template +++ b/templates/src/objective-c/BoringSSL-GRPC.podspec.template @@ -1560,2976 +1560,5 @@ # symbols are src/objective-c/grpc_shadow_boringssl_symbol_list. # This is the last part of this file. s.prefix_header_contents = - '#define BIO_f_ssl GRPC_SHADOW_BIO_f_ssl', - '#define BIO_set_ssl GRPC_SHADOW_BIO_set_ssl', - '#define SSL_CTX_add_client_custom_ext GRPC_SHADOW_SSL_CTX_add_client_custom_ext', - '#define SSL_CTX_add_server_custom_ext GRPC_SHADOW_SSL_CTX_add_server_custom_ext', - '#define DTLSv1_get_timeout GRPC_SHADOW_DTLSv1_get_timeout', - '#define DTLSv1_handle_timeout GRPC_SHADOW_DTLSv1_handle_timeout', - '#define DTLSv1_set_initial_timeout_duration GRPC_SHADOW_DTLSv1_set_initial_timeout_duration', - '#define SSL_CTX_set_srtp_profiles GRPC_SHADOW_SSL_CTX_set_srtp_profiles', - '#define SSL_CTX_set_tlsext_use_srtp GRPC_SHADOW_SSL_CTX_set_tlsext_use_srtp', - '#define SSL_get_selected_srtp_profile GRPC_SHADOW_SSL_get_selected_srtp_profile', - '#define SSL_get_srtp_profiles GRPC_SHADOW_SSL_get_srtp_profiles', - '#define SSL_set_srtp_profiles GRPC_SHADOW_SSL_set_srtp_profiles', - '#define SSL_set_tlsext_use_srtp GRPC_SHADOW_SSL_set_tlsext_use_srtp', - '#define DTLS_client_method GRPC_SHADOW_DTLS_client_method', - '#define DTLS_method GRPC_SHADOW_DTLS_method', - '#define DTLS_server_method GRPC_SHADOW_DTLS_server_method', - '#define DTLS_with_buffers_method GRPC_SHADOW_DTLS_with_buffers_method', - '#define DTLSv1_2_client_method GRPC_SHADOW_DTLSv1_2_client_method', - '#define DTLSv1_2_method GRPC_SHADOW_DTLSv1_2_method', - '#define DTLSv1_2_server_method GRPC_SHADOW_DTLSv1_2_server_method', - '#define DTLSv1_client_method GRPC_SHADOW_DTLSv1_client_method', - '#define DTLSv1_method GRPC_SHADOW_DTLSv1_method', - '#define DTLSv1_server_method GRPC_SHADOW_DTLSv1_server_method', - '#define SSL_SESSION_from_bytes GRPC_SHADOW_SSL_SESSION_from_bytes', - '#define SSL_SESSION_to_bytes GRPC_SHADOW_SSL_SESSION_to_bytes', - '#define SSL_SESSION_to_bytes_for_ticket GRPC_SHADOW_SSL_SESSION_to_bytes_for_ticket', - '#define i2d_SSL_SESSION GRPC_SHADOW_i2d_SSL_SESSION', - '#define SSL_CTX_set0_client_CAs GRPC_SHADOW_SSL_CTX_set0_client_CAs', - '#define SSL_CTX_set_cert_cb GRPC_SHADOW_SSL_CTX_set_cert_cb', - '#define SSL_CTX_set_chain_and_key GRPC_SHADOW_SSL_CTX_set_chain_and_key', - '#define SSL_CTX_set_ocsp_response GRPC_SHADOW_SSL_CTX_set_ocsp_response', - '#define SSL_CTX_set_signed_cert_timestamp_list GRPC_SHADOW_SSL_CTX_set_signed_cert_timestamp_list', - '#define SSL_CTX_use_certificate_ASN1 GRPC_SHADOW_SSL_CTX_use_certificate_ASN1', - '#define SSL_get0_peer_certificates GRPC_SHADOW_SSL_get0_peer_certificates', - '#define SSL_get0_server_requested_CAs GRPC_SHADOW_SSL_get0_server_requested_CAs', - '#define SSL_set0_client_CAs GRPC_SHADOW_SSL_set0_client_CAs', - '#define SSL_set_cert_cb GRPC_SHADOW_SSL_set_cert_cb', - '#define SSL_set_chain_and_key GRPC_SHADOW_SSL_set_chain_and_key', - '#define SSL_set_ocsp_response GRPC_SHADOW_SSL_set_ocsp_response', - '#define SSL_set_signed_cert_timestamp_list GRPC_SHADOW_SSL_set_signed_cert_timestamp_list', - '#define SSL_use_certificate_ASN1 GRPC_SHADOW_SSL_use_certificate_ASN1', - '#define SSL_CIPHER_description GRPC_SHADOW_SSL_CIPHER_description', - '#define SSL_CIPHER_get_auth_nid GRPC_SHADOW_SSL_CIPHER_get_auth_nid', - '#define SSL_CIPHER_get_bits GRPC_SHADOW_SSL_CIPHER_get_bits', - '#define SSL_CIPHER_get_cipher_nid GRPC_SHADOW_SSL_CIPHER_get_cipher_nid', - '#define SSL_CIPHER_get_digest_nid GRPC_SHADOW_SSL_CIPHER_get_digest_nid', - '#define SSL_CIPHER_get_id GRPC_SHADOW_SSL_CIPHER_get_id', - '#define SSL_CIPHER_get_kx_name GRPC_SHADOW_SSL_CIPHER_get_kx_name', - '#define SSL_CIPHER_get_kx_nid GRPC_SHADOW_SSL_CIPHER_get_kx_nid', - '#define SSL_CIPHER_get_max_version GRPC_SHADOW_SSL_CIPHER_get_max_version', - '#define SSL_CIPHER_get_min_version GRPC_SHADOW_SSL_CIPHER_get_min_version', - '#define SSL_CIPHER_get_name GRPC_SHADOW_SSL_CIPHER_get_name', - '#define SSL_CIPHER_get_prf_nid GRPC_SHADOW_SSL_CIPHER_get_prf_nid', - '#define SSL_CIPHER_get_rfc_name GRPC_SHADOW_SSL_CIPHER_get_rfc_name', - '#define SSL_CIPHER_get_version GRPC_SHADOW_SSL_CIPHER_get_version', - '#define SSL_CIPHER_is_aead GRPC_SHADOW_SSL_CIPHER_is_aead', - '#define SSL_CIPHER_is_block_cipher GRPC_SHADOW_SSL_CIPHER_is_block_cipher', - '#define SSL_CIPHER_standard_name GRPC_SHADOW_SSL_CIPHER_standard_name', - '#define SSL_COMP_add_compression_method GRPC_SHADOW_SSL_COMP_add_compression_method', - '#define SSL_COMP_free_compression_methods GRPC_SHADOW_SSL_COMP_free_compression_methods', - '#define SSL_COMP_get0_name GRPC_SHADOW_SSL_COMP_get0_name', - '#define SSL_COMP_get_compression_methods GRPC_SHADOW_SSL_COMP_get_compression_methods', - '#define SSL_COMP_get_id GRPC_SHADOW_SSL_COMP_get_id', - '#define SSL_COMP_get_name GRPC_SHADOW_SSL_COMP_get_name', - '#define SSL_get_cipher_by_value GRPC_SHADOW_SSL_get_cipher_by_value', - '#define SSL_CTX_get_default_passwd_cb GRPC_SHADOW_SSL_CTX_get_default_passwd_cb', - '#define SSL_CTX_get_default_passwd_cb_userdata GRPC_SHADOW_SSL_CTX_get_default_passwd_cb_userdata', - '#define SSL_CTX_set_default_passwd_cb GRPC_SHADOW_SSL_CTX_set_default_passwd_cb', - '#define SSL_CTX_set_default_passwd_cb_userdata GRPC_SHADOW_SSL_CTX_set_default_passwd_cb_userdata', - '#define SSL_CTX_use_PrivateKey_file GRPC_SHADOW_SSL_CTX_use_PrivateKey_file', - '#define SSL_CTX_use_RSAPrivateKey_file GRPC_SHADOW_SSL_CTX_use_RSAPrivateKey_file', - '#define SSL_CTX_use_certificate_chain_file GRPC_SHADOW_SSL_CTX_use_certificate_chain_file', - '#define SSL_CTX_use_certificate_file GRPC_SHADOW_SSL_CTX_use_certificate_file', - '#define SSL_add_file_cert_subjects_to_stack GRPC_SHADOW_SSL_add_file_cert_subjects_to_stack', - '#define SSL_load_client_CA_file GRPC_SHADOW_SSL_load_client_CA_file', - '#define SSL_use_PrivateKey_file GRPC_SHADOW_SSL_use_PrivateKey_file', - '#define SSL_use_RSAPrivateKey_file GRPC_SHADOW_SSL_use_RSAPrivateKey_file', - '#define SSL_use_certificate_file GRPC_SHADOW_SSL_use_certificate_file', - '#define SSL_get_curve_name GRPC_SHADOW_SSL_get_curve_name', - '#define ERR_load_SSL_strings GRPC_SHADOW_ERR_load_SSL_strings', - '#define OPENSSL_init_ssl GRPC_SHADOW_OPENSSL_init_ssl', - '#define SSL_CTX_check_private_key GRPC_SHADOW_SSL_CTX_check_private_key', - '#define SSL_CTX_cipher_in_group GRPC_SHADOW_SSL_CTX_cipher_in_group', - '#define SSL_CTX_clear_mode GRPC_SHADOW_SSL_CTX_clear_mode', - '#define SSL_CTX_clear_options GRPC_SHADOW_SSL_CTX_clear_options', - '#define SSL_CTX_enable_ocsp_stapling GRPC_SHADOW_SSL_CTX_enable_ocsp_stapling', - '#define SSL_CTX_enable_signed_cert_timestamps GRPC_SHADOW_SSL_CTX_enable_signed_cert_timestamps', - '#define SSL_CTX_enable_tls_channel_id GRPC_SHADOW_SSL_CTX_enable_tls_channel_id', - '#define SSL_CTX_free GRPC_SHADOW_SSL_CTX_free', - '#define SSL_CTX_get0_privatekey GRPC_SHADOW_SSL_CTX_get0_privatekey', - '#define SSL_CTX_get_ciphers GRPC_SHADOW_SSL_CTX_get_ciphers', - '#define SSL_CTX_get_ex_data GRPC_SHADOW_SSL_CTX_get_ex_data', - '#define SSL_CTX_get_ex_new_index GRPC_SHADOW_SSL_CTX_get_ex_new_index', - '#define SSL_CTX_get_keylog_callback GRPC_SHADOW_SSL_CTX_get_keylog_callback', - '#define SSL_CTX_get_max_cert_list GRPC_SHADOW_SSL_CTX_get_max_cert_list', - '#define SSL_CTX_get_mode GRPC_SHADOW_SSL_CTX_get_mode', - '#define SSL_CTX_get_options GRPC_SHADOW_SSL_CTX_get_options', - '#define SSL_CTX_get_quiet_shutdown GRPC_SHADOW_SSL_CTX_get_quiet_shutdown', - '#define SSL_CTX_get_read_ahead GRPC_SHADOW_SSL_CTX_get_read_ahead', - '#define SSL_CTX_get_session_cache_mode GRPC_SHADOW_SSL_CTX_get_session_cache_mode', - '#define SSL_CTX_get_tlsext_ticket_keys GRPC_SHADOW_SSL_CTX_get_tlsext_ticket_keys', - '#define SSL_CTX_need_tmp_RSA GRPC_SHADOW_SSL_CTX_need_tmp_RSA', - '#define SSL_CTX_new GRPC_SHADOW_SSL_CTX_new', - '#define SSL_CTX_sess_accept GRPC_SHADOW_SSL_CTX_sess_accept', - '#define SSL_CTX_sess_accept_good GRPC_SHADOW_SSL_CTX_sess_accept_good', - '#define SSL_CTX_sess_accept_renegotiate GRPC_SHADOW_SSL_CTX_sess_accept_renegotiate', - '#define SSL_CTX_sess_cache_full GRPC_SHADOW_SSL_CTX_sess_cache_full', - '#define SSL_CTX_sess_cb_hits GRPC_SHADOW_SSL_CTX_sess_cb_hits', - '#define SSL_CTX_sess_connect GRPC_SHADOW_SSL_CTX_sess_connect', - '#define SSL_CTX_sess_connect_good GRPC_SHADOW_SSL_CTX_sess_connect_good', - '#define SSL_CTX_sess_connect_renegotiate GRPC_SHADOW_SSL_CTX_sess_connect_renegotiate', - '#define SSL_CTX_sess_get_cache_size GRPC_SHADOW_SSL_CTX_sess_get_cache_size', - '#define SSL_CTX_sess_hits GRPC_SHADOW_SSL_CTX_sess_hits', - '#define SSL_CTX_sess_misses GRPC_SHADOW_SSL_CTX_sess_misses', - '#define SSL_CTX_sess_number GRPC_SHADOW_SSL_CTX_sess_number', - '#define SSL_CTX_sess_set_cache_size GRPC_SHADOW_SSL_CTX_sess_set_cache_size', - '#define SSL_CTX_sess_timeouts GRPC_SHADOW_SSL_CTX_sess_timeouts', - '#define SSL_CTX_set0_buffer_pool GRPC_SHADOW_SSL_CTX_set0_buffer_pool', - '#define SSL_CTX_set1_curves GRPC_SHADOW_SSL_CTX_set1_curves', - '#define SSL_CTX_set1_curves_list GRPC_SHADOW_SSL_CTX_set1_curves_list', - '#define SSL_CTX_set1_tls_channel_id GRPC_SHADOW_SSL_CTX_set1_tls_channel_id', - '#define SSL_CTX_set_allow_unknown_alpn_protos GRPC_SHADOW_SSL_CTX_set_allow_unknown_alpn_protos', - '#define SSL_CTX_set_alpn_protos GRPC_SHADOW_SSL_CTX_set_alpn_protos', - '#define SSL_CTX_set_alpn_select_cb GRPC_SHADOW_SSL_CTX_set_alpn_select_cb', - '#define SSL_CTX_set_cipher_list GRPC_SHADOW_SSL_CTX_set_cipher_list', - '#define SSL_CTX_set_current_time_cb GRPC_SHADOW_SSL_CTX_set_current_time_cb', - '#define SSL_CTX_set_custom_verify GRPC_SHADOW_SSL_CTX_set_custom_verify', - '#define SSL_CTX_set_dos_protection_cb GRPC_SHADOW_SSL_CTX_set_dos_protection_cb', - '#define SSL_CTX_set_early_data_enabled GRPC_SHADOW_SSL_CTX_set_early_data_enabled', - '#define SSL_CTX_set_ex_data GRPC_SHADOW_SSL_CTX_set_ex_data', - '#define SSL_CTX_set_false_start_allowed_without_alpn GRPC_SHADOW_SSL_CTX_set_false_start_allowed_without_alpn', - '#define SSL_CTX_set_grease_enabled GRPC_SHADOW_SSL_CTX_set_grease_enabled', - '#define SSL_CTX_set_keylog_callback GRPC_SHADOW_SSL_CTX_set_keylog_callback', - '#define SSL_CTX_set_max_cert_list GRPC_SHADOW_SSL_CTX_set_max_cert_list', - '#define SSL_CTX_set_max_send_fragment GRPC_SHADOW_SSL_CTX_set_max_send_fragment', - '#define SSL_CTX_set_mode GRPC_SHADOW_SSL_CTX_set_mode', - '#define SSL_CTX_set_msg_callback GRPC_SHADOW_SSL_CTX_set_msg_callback', - '#define SSL_CTX_set_msg_callback_arg GRPC_SHADOW_SSL_CTX_set_msg_callback_arg', - '#define SSL_CTX_set_next_proto_select_cb GRPC_SHADOW_SSL_CTX_set_next_proto_select_cb', - '#define SSL_CTX_set_next_protos_advertised_cb GRPC_SHADOW_SSL_CTX_set_next_protos_advertised_cb', - '#define SSL_CTX_set_options GRPC_SHADOW_SSL_CTX_set_options', - '#define SSL_CTX_set_psk_client_callback GRPC_SHADOW_SSL_CTX_set_psk_client_callback', - '#define SSL_CTX_set_psk_server_callback GRPC_SHADOW_SSL_CTX_set_psk_server_callback', - '#define SSL_CTX_set_quiet_shutdown GRPC_SHADOW_SSL_CTX_set_quiet_shutdown', - '#define SSL_CTX_set_read_ahead GRPC_SHADOW_SSL_CTX_set_read_ahead', - '#define SSL_CTX_set_retain_only_sha256_of_client_certs GRPC_SHADOW_SSL_CTX_set_retain_only_sha256_of_client_certs', - '#define SSL_CTX_set_select_certificate_cb GRPC_SHADOW_SSL_CTX_set_select_certificate_cb', - '#define SSL_CTX_set_session_cache_mode GRPC_SHADOW_SSL_CTX_set_session_cache_mode', - '#define SSL_CTX_set_session_id_context GRPC_SHADOW_SSL_CTX_set_session_id_context', - '#define SSL_CTX_set_strict_cipher_list GRPC_SHADOW_SSL_CTX_set_strict_cipher_list', - '#define SSL_CTX_set_ticket_aead_method GRPC_SHADOW_SSL_CTX_set_ticket_aead_method', - '#define SSL_CTX_set_tls13_variant GRPC_SHADOW_SSL_CTX_set_tls13_variant', - '#define SSL_CTX_set_tls_channel_id_enabled GRPC_SHADOW_SSL_CTX_set_tls_channel_id_enabled', - '#define SSL_CTX_set_tlsext_servername_arg GRPC_SHADOW_SSL_CTX_set_tlsext_servername_arg', - '#define SSL_CTX_set_tlsext_servername_callback GRPC_SHADOW_SSL_CTX_set_tlsext_servername_callback', - '#define SSL_CTX_set_tlsext_ticket_key_cb GRPC_SHADOW_SSL_CTX_set_tlsext_ticket_key_cb', - '#define SSL_CTX_set_tlsext_ticket_keys GRPC_SHADOW_SSL_CTX_set_tlsext_ticket_keys', - '#define SSL_CTX_set_tmp_dh GRPC_SHADOW_SSL_CTX_set_tmp_dh', - '#define SSL_CTX_set_tmp_dh_callback GRPC_SHADOW_SSL_CTX_set_tmp_dh_callback', - '#define SSL_CTX_set_tmp_ecdh GRPC_SHADOW_SSL_CTX_set_tmp_ecdh', - '#define SSL_CTX_set_tmp_rsa GRPC_SHADOW_SSL_CTX_set_tmp_rsa', - '#define SSL_CTX_set_tmp_rsa_callback GRPC_SHADOW_SSL_CTX_set_tmp_rsa_callback', - '#define SSL_CTX_up_ref GRPC_SHADOW_SSL_CTX_up_ref', - '#define SSL_CTX_use_psk_identity_hint GRPC_SHADOW_SSL_CTX_use_psk_identity_hint', - '#define SSL_accept GRPC_SHADOW_SSL_accept', - '#define SSL_cache_hit GRPC_SHADOW_SSL_cache_hit', - '#define SSL_certs_clear GRPC_SHADOW_SSL_certs_clear', - '#define SSL_check_private_key GRPC_SHADOW_SSL_check_private_key', - '#define SSL_clear GRPC_SHADOW_SSL_clear', - '#define SSL_clear_mode GRPC_SHADOW_SSL_clear_mode', - '#define SSL_clear_options GRPC_SHADOW_SSL_clear_options', - '#define SSL_connect GRPC_SHADOW_SSL_connect', - '#define SSL_cutthrough_complete GRPC_SHADOW_SSL_cutthrough_complete', - '#define SSL_do_handshake GRPC_SHADOW_SSL_do_handshake', - '#define SSL_dummy_pq_padding_used GRPC_SHADOW_SSL_dummy_pq_padding_used', - '#define SSL_early_data_accepted GRPC_SHADOW_SSL_early_data_accepted', - '#define SSL_enable_ocsp_stapling GRPC_SHADOW_SSL_enable_ocsp_stapling', - '#define SSL_enable_signed_cert_timestamps GRPC_SHADOW_SSL_enable_signed_cert_timestamps', - '#define SSL_enable_tls_channel_id GRPC_SHADOW_SSL_enable_tls_channel_id', - '#define SSL_free GRPC_SHADOW_SSL_free', - '#define SSL_get0_alpn_selected GRPC_SHADOW_SSL_get0_alpn_selected', - '#define SSL_get0_certificate_types GRPC_SHADOW_SSL_get0_certificate_types', - '#define SSL_get0_next_proto_negotiated GRPC_SHADOW_SSL_get0_next_proto_negotiated', - '#define SSL_get0_ocsp_response GRPC_SHADOW_SSL_get0_ocsp_response', - '#define SSL_get0_session_id_context GRPC_SHADOW_SSL_get0_session_id_context', - '#define SSL_get0_signed_cert_timestamp_list GRPC_SHADOW_SSL_get0_signed_cert_timestamp_list', - '#define SSL_get_SSL_CTX GRPC_SHADOW_SSL_get_SSL_CTX', - '#define SSL_get_cipher_list GRPC_SHADOW_SSL_get_cipher_list', - '#define SSL_get_ciphers GRPC_SHADOW_SSL_get_ciphers', - '#define SSL_get_client_random GRPC_SHADOW_SSL_get_client_random', - '#define SSL_get_current_cipher GRPC_SHADOW_SSL_get_current_cipher', - '#define SSL_get_current_compression GRPC_SHADOW_SSL_get_current_compression', - '#define SSL_get_current_expansion GRPC_SHADOW_SSL_get_current_expansion', - '#define SSL_get_curve_id GRPC_SHADOW_SSL_get_curve_id', - '#define SSL_get_default_timeout GRPC_SHADOW_SSL_get_default_timeout', - '#define SSL_get_error GRPC_SHADOW_SSL_get_error', - '#define SSL_get_ex_data GRPC_SHADOW_SSL_get_ex_data', - '#define SSL_get_ex_new_index GRPC_SHADOW_SSL_get_ex_new_index', - '#define SSL_get_extms_support GRPC_SHADOW_SSL_get_extms_support', - '#define SSL_get_fd GRPC_SHADOW_SSL_get_fd', - '#define SSL_get_finished GRPC_SHADOW_SSL_get_finished', - '#define SSL_get_info_callback GRPC_SHADOW_SSL_get_info_callback', - '#define SSL_get_ivs GRPC_SHADOW_SSL_get_ivs', - '#define SSL_get_max_cert_list GRPC_SHADOW_SSL_get_max_cert_list', - '#define SSL_get_mode GRPC_SHADOW_SSL_get_mode', - '#define SSL_get_negotiated_token_binding_param GRPC_SHADOW_SSL_get_negotiated_token_binding_param', - '#define SSL_get_options GRPC_SHADOW_SSL_get_options', - '#define SSL_get_peer_finished GRPC_SHADOW_SSL_get_peer_finished', - '#define SSL_get_peer_quic_transport_params GRPC_SHADOW_SSL_get_peer_quic_transport_params', - '#define SSL_get_peer_signature_algorithm GRPC_SHADOW_SSL_get_peer_signature_algorithm', - '#define SSL_get_pending_cipher GRPC_SHADOW_SSL_get_pending_cipher', - '#define SSL_get_privatekey GRPC_SHADOW_SSL_get_privatekey', - '#define SSL_get_psk_identity GRPC_SHADOW_SSL_get_psk_identity', - '#define SSL_get_psk_identity_hint GRPC_SHADOW_SSL_get_psk_identity_hint', - '#define SSL_get_quiet_shutdown GRPC_SHADOW_SSL_get_quiet_shutdown', - '#define SSL_get_rbio GRPC_SHADOW_SSL_get_rbio', - '#define SSL_get_read_ahead GRPC_SHADOW_SSL_get_read_ahead', - '#define SSL_get_read_sequence GRPC_SHADOW_SSL_get_read_sequence', - '#define SSL_get_rfd GRPC_SHADOW_SSL_get_rfd', - '#define SSL_get_secure_renegotiation_support GRPC_SHADOW_SSL_get_secure_renegotiation_support', - '#define SSL_get_server_random GRPC_SHADOW_SSL_get_server_random', - '#define SSL_get_server_tmp_key GRPC_SHADOW_SSL_get_server_tmp_key', - '#define SSL_get_servername GRPC_SHADOW_SSL_get_servername', - '#define SSL_get_servername_type GRPC_SHADOW_SSL_get_servername_type', - '#define SSL_get_shared_ciphers GRPC_SHADOW_SSL_get_shared_ciphers', - '#define SSL_get_shutdown GRPC_SHADOW_SSL_get_shutdown', - '#define SSL_get_structure_sizes GRPC_SHADOW_SSL_get_structure_sizes', - '#define SSL_get_ticket_age_skew GRPC_SHADOW_SSL_get_ticket_age_skew', - '#define SSL_get_tls_channel_id GRPC_SHADOW_SSL_get_tls_channel_id', - '#define SSL_get_tls_unique GRPC_SHADOW_SSL_get_tls_unique', - '#define SSL_get_verify_mode GRPC_SHADOW_SSL_get_verify_mode', - '#define SSL_get_wbio GRPC_SHADOW_SSL_get_wbio', - '#define SSL_get_wfd GRPC_SHADOW_SSL_get_wfd', - '#define SSL_get_write_sequence GRPC_SHADOW_SSL_get_write_sequence', - '#define SSL_in_early_data GRPC_SHADOW_SSL_in_early_data', - '#define SSL_in_false_start GRPC_SHADOW_SSL_in_false_start', - '#define SSL_in_init GRPC_SHADOW_SSL_in_init', - '#define SSL_is_draft_downgrade GRPC_SHADOW_SSL_is_draft_downgrade', - '#define SSL_is_dtls GRPC_SHADOW_SSL_is_dtls', - '#define SSL_is_init_finished GRPC_SHADOW_SSL_is_init_finished', - '#define SSL_is_server GRPC_SHADOW_SSL_is_server', - '#define SSL_is_token_binding_negotiated GRPC_SHADOW_SSL_is_token_binding_negotiated', - '#define SSL_library_init GRPC_SHADOW_SSL_library_init', - '#define SSL_load_error_strings GRPC_SHADOW_SSL_load_error_strings', - '#define SSL_need_tmp_RSA GRPC_SHADOW_SSL_need_tmp_RSA', - '#define SSL_new GRPC_SHADOW_SSL_new', - '#define SSL_num_renegotiations GRPC_SHADOW_SSL_num_renegotiations', - '#define SSL_peek GRPC_SHADOW_SSL_peek', - '#define SSL_pending GRPC_SHADOW_SSL_pending', - '#define SSL_read GRPC_SHADOW_SSL_read', - '#define SSL_renegotiate GRPC_SHADOW_SSL_renegotiate', - '#define SSL_renegotiate_pending GRPC_SHADOW_SSL_renegotiate_pending', - '#define SSL_reset_early_data_reject GRPC_SHADOW_SSL_reset_early_data_reject', - '#define SSL_select_next_proto GRPC_SHADOW_SSL_select_next_proto', - '#define SSL_send_fatal_alert GRPC_SHADOW_SSL_send_fatal_alert', - '#define SSL_session_reused GRPC_SHADOW_SSL_session_reused', - '#define SSL_set0_rbio GRPC_SHADOW_SSL_set0_rbio', - '#define SSL_set0_wbio GRPC_SHADOW_SSL_set0_wbio', - '#define SSL_set1_curves GRPC_SHADOW_SSL_set1_curves', - '#define SSL_set1_curves_list GRPC_SHADOW_SSL_set1_curves_list', - '#define SSL_set1_tls_channel_id GRPC_SHADOW_SSL_set1_tls_channel_id', - '#define SSL_set_SSL_CTX GRPC_SHADOW_SSL_set_SSL_CTX', - '#define SSL_set_accept_state GRPC_SHADOW_SSL_set_accept_state', - '#define SSL_set_alpn_protos GRPC_SHADOW_SSL_set_alpn_protos', - '#define SSL_set_bio GRPC_SHADOW_SSL_set_bio', - '#define SSL_set_cipher_list GRPC_SHADOW_SSL_set_cipher_list', - '#define SSL_set_connect_state GRPC_SHADOW_SSL_set_connect_state', - '#define SSL_set_custom_verify GRPC_SHADOW_SSL_set_custom_verify', - '#define SSL_set_dummy_pq_padding_size GRPC_SHADOW_SSL_set_dummy_pq_padding_size', - '#define SSL_set_early_data_enabled GRPC_SHADOW_SSL_set_early_data_enabled', - '#define SSL_set_ex_data GRPC_SHADOW_SSL_set_ex_data', - '#define SSL_set_fd GRPC_SHADOW_SSL_set_fd', - '#define SSL_set_info_callback GRPC_SHADOW_SSL_set_info_callback', - '#define SSL_set_max_cert_list GRPC_SHADOW_SSL_set_max_cert_list', - '#define SSL_set_max_send_fragment GRPC_SHADOW_SSL_set_max_send_fragment', - '#define SSL_set_mode GRPC_SHADOW_SSL_set_mode', - '#define SSL_set_msg_callback GRPC_SHADOW_SSL_set_msg_callback', - '#define SSL_set_msg_callback_arg GRPC_SHADOW_SSL_set_msg_callback_arg', - '#define SSL_set_mtu GRPC_SHADOW_SSL_set_mtu', - '#define SSL_set_options GRPC_SHADOW_SSL_set_options', - '#define SSL_set_psk_client_callback GRPC_SHADOW_SSL_set_psk_client_callback', - '#define SSL_set_psk_server_callback GRPC_SHADOW_SSL_set_psk_server_callback', - '#define SSL_set_quic_transport_params GRPC_SHADOW_SSL_set_quic_transport_params', - '#define SSL_set_quiet_shutdown GRPC_SHADOW_SSL_set_quiet_shutdown', - '#define SSL_set_read_ahead GRPC_SHADOW_SSL_set_read_ahead', - '#define SSL_set_renegotiate_mode GRPC_SHADOW_SSL_set_renegotiate_mode', - '#define SSL_set_retain_only_sha256_of_client_certs GRPC_SHADOW_SSL_set_retain_only_sha256_of_client_certs', - '#define SSL_set_rfd GRPC_SHADOW_SSL_set_rfd', - '#define SSL_set_session_id_context GRPC_SHADOW_SSL_set_session_id_context', - '#define SSL_set_shutdown GRPC_SHADOW_SSL_set_shutdown', - '#define SSL_set_state GRPC_SHADOW_SSL_set_state', - '#define SSL_set_strict_cipher_list GRPC_SHADOW_SSL_set_strict_cipher_list', - '#define SSL_set_tls13_variant GRPC_SHADOW_SSL_set_tls13_variant', - '#define SSL_set_tls_channel_id_enabled GRPC_SHADOW_SSL_set_tls_channel_id_enabled', - '#define SSL_set_tlsext_host_name GRPC_SHADOW_SSL_set_tlsext_host_name', - '#define SSL_set_tmp_dh GRPC_SHADOW_SSL_set_tmp_dh', - '#define SSL_set_tmp_dh_callback GRPC_SHADOW_SSL_set_tmp_dh_callback', - '#define SSL_set_tmp_ecdh GRPC_SHADOW_SSL_set_tmp_ecdh', - '#define SSL_set_tmp_rsa GRPC_SHADOW_SSL_set_tmp_rsa', - '#define SSL_set_tmp_rsa_callback GRPC_SHADOW_SSL_set_tmp_rsa_callback', - '#define SSL_set_token_binding_params GRPC_SHADOW_SSL_set_token_binding_params', - '#define SSL_set_wfd GRPC_SHADOW_SSL_set_wfd', - '#define SSL_shutdown GRPC_SHADOW_SSL_shutdown', - '#define SSL_state GRPC_SHADOW_SSL_state', - '#define SSL_total_renegotiations GRPC_SHADOW_SSL_total_renegotiations', - '#define SSL_use_psk_identity_hint GRPC_SHADOW_SSL_use_psk_identity_hint', - '#define SSL_want GRPC_SHADOW_SSL_want', - '#define SSL_write GRPC_SHADOW_SSL_write', - '#define SSL_CTX_set_private_key_method GRPC_SHADOW_SSL_CTX_set_private_key_method', - '#define SSL_CTX_set_signing_algorithm_prefs GRPC_SHADOW_SSL_CTX_set_signing_algorithm_prefs', - '#define SSL_CTX_set_verify_algorithm_prefs GRPC_SHADOW_SSL_CTX_set_verify_algorithm_prefs', - '#define SSL_CTX_use_PrivateKey GRPC_SHADOW_SSL_CTX_use_PrivateKey', - '#define SSL_CTX_use_PrivateKey_ASN1 GRPC_SHADOW_SSL_CTX_use_PrivateKey_ASN1', - '#define SSL_CTX_use_RSAPrivateKey GRPC_SHADOW_SSL_CTX_use_RSAPrivateKey', - '#define SSL_CTX_use_RSAPrivateKey_ASN1 GRPC_SHADOW_SSL_CTX_use_RSAPrivateKey_ASN1', - '#define SSL_get_signature_algorithm_digest GRPC_SHADOW_SSL_get_signature_algorithm_digest', - '#define SSL_get_signature_algorithm_key_type GRPC_SHADOW_SSL_get_signature_algorithm_key_type', - '#define SSL_get_signature_algorithm_name GRPC_SHADOW_SSL_get_signature_algorithm_name', - '#define SSL_is_signature_algorithm_rsa_pss GRPC_SHADOW_SSL_is_signature_algorithm_rsa_pss', - '#define SSL_set_private_key_method GRPC_SHADOW_SSL_set_private_key_method', - '#define SSL_set_signing_algorithm_prefs GRPC_SHADOW_SSL_set_signing_algorithm_prefs', - '#define SSL_use_PrivateKey GRPC_SHADOW_SSL_use_PrivateKey', - '#define SSL_use_PrivateKey_ASN1 GRPC_SHADOW_SSL_use_PrivateKey_ASN1', - '#define SSL_use_RSAPrivateKey GRPC_SHADOW_SSL_use_RSAPrivateKey', - '#define SSL_use_RSAPrivateKey_ASN1 GRPC_SHADOW_SSL_use_RSAPrivateKey_ASN1', - '#define SSL_CTX_add_session GRPC_SHADOW_SSL_CTX_add_session', - '#define SSL_CTX_flush_sessions GRPC_SHADOW_SSL_CTX_flush_sessions', - '#define SSL_CTX_get_channel_id_cb GRPC_SHADOW_SSL_CTX_get_channel_id_cb', - '#define SSL_CTX_get_info_callback GRPC_SHADOW_SSL_CTX_get_info_callback', - '#define SSL_CTX_get_timeout GRPC_SHADOW_SSL_CTX_get_timeout', - '#define SSL_CTX_remove_session GRPC_SHADOW_SSL_CTX_remove_session', - '#define SSL_CTX_sess_get_get_cb GRPC_SHADOW_SSL_CTX_sess_get_get_cb', - '#define SSL_CTX_sess_get_new_cb GRPC_SHADOW_SSL_CTX_sess_get_new_cb', - '#define SSL_CTX_sess_get_remove_cb GRPC_SHADOW_SSL_CTX_sess_get_remove_cb', - '#define SSL_CTX_sess_set_get_cb GRPC_SHADOW_SSL_CTX_sess_set_get_cb', - '#define SSL_CTX_sess_set_new_cb GRPC_SHADOW_SSL_CTX_sess_set_new_cb', - '#define SSL_CTX_sess_set_remove_cb GRPC_SHADOW_SSL_CTX_sess_set_remove_cb', - '#define SSL_CTX_set_channel_id_cb GRPC_SHADOW_SSL_CTX_set_channel_id_cb', - '#define SSL_CTX_set_info_callback GRPC_SHADOW_SSL_CTX_set_info_callback', - '#define SSL_CTX_set_session_psk_dhe_timeout GRPC_SHADOW_SSL_CTX_set_session_psk_dhe_timeout', - '#define SSL_CTX_set_timeout GRPC_SHADOW_SSL_CTX_set_timeout', - '#define SSL_SESSION_free GRPC_SHADOW_SSL_SESSION_free', - '#define SSL_SESSION_get0_peer GRPC_SHADOW_SSL_SESSION_get0_peer', - '#define SSL_SESSION_get0_ticket GRPC_SHADOW_SSL_SESSION_get0_ticket', - '#define SSL_SESSION_get_ex_data GRPC_SHADOW_SSL_SESSION_get_ex_data', - '#define SSL_SESSION_get_ex_new_index GRPC_SHADOW_SSL_SESSION_get_ex_new_index', - '#define SSL_SESSION_get_id GRPC_SHADOW_SSL_SESSION_get_id', - '#define SSL_SESSION_get_master_key GRPC_SHADOW_SSL_SESSION_get_master_key', - '#define SSL_SESSION_get_ticket_lifetime_hint GRPC_SHADOW_SSL_SESSION_get_ticket_lifetime_hint', - '#define SSL_SESSION_get_time GRPC_SHADOW_SSL_SESSION_get_time', - '#define SSL_SESSION_get_timeout GRPC_SHADOW_SSL_SESSION_get_timeout', - '#define SSL_SESSION_has_ticket GRPC_SHADOW_SSL_SESSION_has_ticket', - '#define SSL_SESSION_is_resumable GRPC_SHADOW_SSL_SESSION_is_resumable', - '#define SSL_SESSION_new GRPC_SHADOW_SSL_SESSION_new', - '#define SSL_SESSION_set1_id_context GRPC_SHADOW_SSL_SESSION_set1_id_context', - '#define SSL_SESSION_set_ex_data GRPC_SHADOW_SSL_SESSION_set_ex_data', - '#define SSL_SESSION_set_time GRPC_SHADOW_SSL_SESSION_set_time', - '#define SSL_SESSION_set_timeout GRPC_SHADOW_SSL_SESSION_set_timeout', - '#define SSL_SESSION_should_be_single_use GRPC_SHADOW_SSL_SESSION_should_be_single_use', - '#define SSL_SESSION_up_ref GRPC_SHADOW_SSL_SESSION_up_ref', - '#define SSL_get1_session GRPC_SHADOW_SSL_get1_session', - '#define SSL_get_session GRPC_SHADOW_SSL_get_session', - '#define SSL_magic_pending_session_ptr GRPC_SHADOW_SSL_magic_pending_session_ptr', - '#define SSL_set_session GRPC_SHADOW_SSL_set_session', - '#define SSL_alert_desc_string GRPC_SHADOW_SSL_alert_desc_string', - '#define SSL_alert_desc_string_long GRPC_SHADOW_SSL_alert_desc_string_long', - '#define SSL_alert_type_string GRPC_SHADOW_SSL_alert_type_string', - '#define SSL_alert_type_string_long GRPC_SHADOW_SSL_alert_type_string_long', - '#define SSL_state_string GRPC_SHADOW_SSL_state_string', - '#define SSL_state_string_long GRPC_SHADOW_SSL_state_string_long', - '#define SSL_CTX_set_max_proto_version GRPC_SHADOW_SSL_CTX_set_max_proto_version', - '#define SSL_CTX_set_min_proto_version GRPC_SHADOW_SSL_CTX_set_min_proto_version', - '#define SSL_SESSION_get_protocol_version GRPC_SHADOW_SSL_SESSION_get_protocol_version', - '#define SSL_SESSION_get_version GRPC_SHADOW_SSL_SESSION_get_version', - '#define SSL_SESSION_set_protocol_version GRPC_SHADOW_SSL_SESSION_set_protocol_version', - '#define SSL_get_version GRPC_SHADOW_SSL_get_version', - '#define SSL_set_max_proto_version GRPC_SHADOW_SSL_set_max_proto_version', - '#define SSL_set_min_proto_version GRPC_SHADOW_SSL_set_min_proto_version', - '#define SSL_version GRPC_SHADOW_SSL_version', - '#define PEM_read_SSL_SESSION GRPC_SHADOW_PEM_read_SSL_SESSION', - '#define PEM_read_bio_SSL_SESSION GRPC_SHADOW_PEM_read_bio_SSL_SESSION', - '#define PEM_write_SSL_SESSION GRPC_SHADOW_PEM_write_SSL_SESSION', - '#define PEM_write_bio_SSL_SESSION GRPC_SHADOW_PEM_write_bio_SSL_SESSION', - '#define SSL_CTX_add0_chain_cert GRPC_SHADOW_SSL_CTX_add0_chain_cert', - '#define SSL_CTX_add1_chain_cert GRPC_SHADOW_SSL_CTX_add1_chain_cert', - '#define SSL_CTX_add_client_CA GRPC_SHADOW_SSL_CTX_add_client_CA', - '#define SSL_CTX_add_extra_chain_cert GRPC_SHADOW_SSL_CTX_add_extra_chain_cert', - '#define SSL_CTX_clear_chain_certs GRPC_SHADOW_SSL_CTX_clear_chain_certs', - '#define SSL_CTX_clear_extra_chain_certs GRPC_SHADOW_SSL_CTX_clear_extra_chain_certs', - '#define SSL_CTX_get0_certificate GRPC_SHADOW_SSL_CTX_get0_certificate', - '#define SSL_CTX_get0_chain_certs GRPC_SHADOW_SSL_CTX_get0_chain_certs', - '#define SSL_CTX_get0_param GRPC_SHADOW_SSL_CTX_get0_param', - '#define SSL_CTX_get_cert_store GRPC_SHADOW_SSL_CTX_get_cert_store', - '#define SSL_CTX_get_client_CA_list GRPC_SHADOW_SSL_CTX_get_client_CA_list', - '#define SSL_CTX_get_extra_chain_certs GRPC_SHADOW_SSL_CTX_get_extra_chain_certs', - '#define SSL_CTX_get_verify_callback GRPC_SHADOW_SSL_CTX_get_verify_callback', - '#define SSL_CTX_get_verify_depth GRPC_SHADOW_SSL_CTX_get_verify_depth', - '#define SSL_CTX_get_verify_mode GRPC_SHADOW_SSL_CTX_get_verify_mode', - '#define SSL_CTX_load_verify_locations GRPC_SHADOW_SSL_CTX_load_verify_locations', - '#define SSL_CTX_set0_chain GRPC_SHADOW_SSL_CTX_set0_chain', - '#define SSL_CTX_set0_verify_cert_store GRPC_SHADOW_SSL_CTX_set0_verify_cert_store', - '#define SSL_CTX_set1_chain GRPC_SHADOW_SSL_CTX_set1_chain', - '#define SSL_CTX_set1_param GRPC_SHADOW_SSL_CTX_set1_param', - '#define SSL_CTX_set1_verify_cert_store GRPC_SHADOW_SSL_CTX_set1_verify_cert_store', - '#define SSL_CTX_set_cert_store GRPC_SHADOW_SSL_CTX_set_cert_store', - '#define SSL_CTX_set_cert_verify_callback GRPC_SHADOW_SSL_CTX_set_cert_verify_callback', - '#define SSL_CTX_set_client_CA_list GRPC_SHADOW_SSL_CTX_set_client_CA_list', - '#define SSL_CTX_set_client_cert_cb GRPC_SHADOW_SSL_CTX_set_client_cert_cb', - '#define SSL_CTX_set_default_verify_paths GRPC_SHADOW_SSL_CTX_set_default_verify_paths', - '#define SSL_CTX_set_purpose GRPC_SHADOW_SSL_CTX_set_purpose', - '#define SSL_CTX_set_trust GRPC_SHADOW_SSL_CTX_set_trust', - '#define SSL_CTX_set_verify GRPC_SHADOW_SSL_CTX_set_verify', - '#define SSL_CTX_set_verify_depth GRPC_SHADOW_SSL_CTX_set_verify_depth', - '#define SSL_CTX_use_certificate GRPC_SHADOW_SSL_CTX_use_certificate', - '#define SSL_add0_chain_cert GRPC_SHADOW_SSL_add0_chain_cert', - '#define SSL_add1_chain_cert GRPC_SHADOW_SSL_add1_chain_cert', - '#define SSL_add_client_CA GRPC_SHADOW_SSL_add_client_CA', - '#define SSL_alert_from_verify_result GRPC_SHADOW_SSL_alert_from_verify_result', - '#define SSL_clear_chain_certs GRPC_SHADOW_SSL_clear_chain_certs', - '#define SSL_dup_CA_list GRPC_SHADOW_SSL_dup_CA_list', - '#define SSL_get0_chain_certs GRPC_SHADOW_SSL_get0_chain_certs', - '#define SSL_get0_param GRPC_SHADOW_SSL_get0_param', - '#define SSL_get_certificate GRPC_SHADOW_SSL_get_certificate', - '#define SSL_get_client_CA_list GRPC_SHADOW_SSL_get_client_CA_list', - '#define SSL_get_ex_data_X509_STORE_CTX_idx GRPC_SHADOW_SSL_get_ex_data_X509_STORE_CTX_idx', - '#define SSL_get_peer_cert_chain GRPC_SHADOW_SSL_get_peer_cert_chain', - '#define SSL_get_peer_certificate GRPC_SHADOW_SSL_get_peer_certificate', - '#define SSL_get_peer_full_cert_chain GRPC_SHADOW_SSL_get_peer_full_cert_chain', - '#define SSL_get_verify_callback GRPC_SHADOW_SSL_get_verify_callback', - '#define SSL_get_verify_depth GRPC_SHADOW_SSL_get_verify_depth', - '#define SSL_get_verify_result GRPC_SHADOW_SSL_get_verify_result', - '#define SSL_set0_chain GRPC_SHADOW_SSL_set0_chain', - '#define SSL_set0_verify_cert_store GRPC_SHADOW_SSL_set0_verify_cert_store', - '#define SSL_set1_chain GRPC_SHADOW_SSL_set1_chain', - '#define SSL_set1_param GRPC_SHADOW_SSL_set1_param', - '#define SSL_set1_verify_cert_store GRPC_SHADOW_SSL_set1_verify_cert_store', - '#define SSL_set_client_CA_list GRPC_SHADOW_SSL_set_client_CA_list', - '#define SSL_set_purpose GRPC_SHADOW_SSL_set_purpose', - '#define SSL_set_trust GRPC_SHADOW_SSL_set_trust', - '#define SSL_set_verify GRPC_SHADOW_SSL_set_verify', - '#define SSL_set_verify_depth GRPC_SHADOW_SSL_set_verify_depth', - '#define SSL_set_verify_result GRPC_SHADOW_SSL_set_verify_result', - '#define SSL_use_certificate GRPC_SHADOW_SSL_use_certificate', - '#define d2i_SSL_SESSION GRPC_SHADOW_d2i_SSL_SESSION', - '#define d2i_SSL_SESSION_bio GRPC_SHADOW_d2i_SSL_SESSION_bio', - '#define i2d_SSL_SESSION_bio GRPC_SHADOW_i2d_SSL_SESSION_bio', - '#define SSL_export_early_keying_material GRPC_SHADOW_SSL_export_early_keying_material', - '#define SSL_export_keying_material GRPC_SHADOW_SSL_export_keying_material', - '#define SSL_generate_key_block GRPC_SHADOW_SSL_generate_key_block', - '#define SSL_get_key_block_len GRPC_SHADOW_SSL_get_key_block_len', - '#define SSL_CTX_set_ed25519_enabled GRPC_SHADOW_SSL_CTX_set_ed25519_enabled', - '#define SSL_early_callback_ctx_extension_get GRPC_SHADOW_SSL_early_callback_ctx_extension_get', - '#define SSL_extension_supported GRPC_SHADOW_SSL_extension_supported', - '#define SSLv23_client_method GRPC_SHADOW_SSLv23_client_method', - '#define SSLv23_method GRPC_SHADOW_SSLv23_method', - '#define SSLv23_server_method GRPC_SHADOW_SSLv23_server_method', - '#define TLS_client_method GRPC_SHADOW_TLS_client_method', - '#define TLS_method GRPC_SHADOW_TLS_method', - '#define TLS_server_method GRPC_SHADOW_TLS_server_method', - '#define TLS_with_buffers_method GRPC_SHADOW_TLS_with_buffers_method', - '#define TLSv1_1_client_method GRPC_SHADOW_TLSv1_1_client_method', - '#define TLSv1_1_method GRPC_SHADOW_TLSv1_1_method', - '#define TLSv1_1_server_method GRPC_SHADOW_TLSv1_1_server_method', - '#define TLSv1_2_client_method GRPC_SHADOW_TLSv1_2_client_method', - '#define TLSv1_2_method GRPC_SHADOW_TLSv1_2_method', - '#define TLSv1_2_server_method GRPC_SHADOW_TLSv1_2_server_method', - '#define TLSv1_client_method GRPC_SHADOW_TLSv1_client_method', - '#define TLSv1_method GRPC_SHADOW_TLSv1_method', - '#define TLSv1_server_method GRPC_SHADOW_TLSv1_server_method', - '#define SSL_max_seal_overhead GRPC_SHADOW_SSL_max_seal_overhead', - '#define OPENSSL_cpuid_setup GRPC_SHADOW_OPENSSL_cpuid_setup', - '#define CRYPTO_has_asm GRPC_SHADOW_CRYPTO_has_asm', - '#define CRYPTO_is_confidential_build GRPC_SHADOW_CRYPTO_is_confidential_build', - '#define CRYPTO_library_init GRPC_SHADOW_CRYPTO_library_init', - '#define CRYPTO_malloc_init GRPC_SHADOW_CRYPTO_malloc_init', - '#define ENGINE_load_builtin_engines GRPC_SHADOW_ENGINE_load_builtin_engines', - '#define ENGINE_register_all_complete GRPC_SHADOW_ENGINE_register_all_complete', - '#define OPENSSL_ia32cap_P GRPC_SHADOW_OPENSSL_ia32cap_P', - '#define OPENSSL_init_crypto GRPC_SHADOW_OPENSSL_init_crypto', - '#define OPENSSL_load_builtin_modules GRPC_SHADOW_OPENSSL_load_builtin_modules', - '#define OpenSSL_version GRPC_SHADOW_OpenSSL_version', - '#define OpenSSL_version_num GRPC_SHADOW_OpenSSL_version_num', - '#define SSLeay GRPC_SHADOW_SSLeay', - '#define SSLeay_version GRPC_SHADOW_SSLeay_version', - '#define CRYPTO_cleanup_all_ex_data GRPC_SHADOW_CRYPTO_cleanup_all_ex_data', - '#define CRYPTO_free_ex_data GRPC_SHADOW_CRYPTO_free_ex_data', - '#define CRYPTO_get_ex_data GRPC_SHADOW_CRYPTO_get_ex_data', - '#define CRYPTO_get_ex_new_index GRPC_SHADOW_CRYPTO_get_ex_new_index', - '#define CRYPTO_new_ex_data GRPC_SHADOW_CRYPTO_new_ex_data', - '#define CRYPTO_set_ex_data GRPC_SHADOW_CRYPTO_set_ex_data', - '#define BIO_snprintf GRPC_SHADOW_BIO_snprintf', - '#define BIO_vsnprintf GRPC_SHADOW_BIO_vsnprintf', - '#define CRYPTO_memcmp GRPC_SHADOW_CRYPTO_memcmp', - '#define OPENSSL_cleanse GRPC_SHADOW_OPENSSL_cleanse', - '#define OPENSSL_free GRPC_SHADOW_OPENSSL_free', - '#define OPENSSL_hash32 GRPC_SHADOW_OPENSSL_hash32', - '#define OPENSSL_malloc GRPC_SHADOW_OPENSSL_malloc', - '#define OPENSSL_realloc GRPC_SHADOW_OPENSSL_realloc', - '#define OPENSSL_strcasecmp GRPC_SHADOW_OPENSSL_strcasecmp', - '#define OPENSSL_strdup GRPC_SHADOW_OPENSSL_strdup', - '#define OPENSSL_strncasecmp GRPC_SHADOW_OPENSSL_strncasecmp', - '#define OPENSSL_strnlen GRPC_SHADOW_OPENSSL_strnlen', - '#define OPENSSL_tolower GRPC_SHADOW_OPENSSL_tolower', - '#define CRYPTO_refcount_dec_and_test_zero GRPC_SHADOW_CRYPTO_refcount_dec_and_test_zero', - '#define CRYPTO_refcount_inc GRPC_SHADOW_CRYPTO_refcount_inc', - '#define CRYPTO_THREADID_current GRPC_SHADOW_CRYPTO_THREADID_current', - '#define CRYPTO_THREADID_set_callback GRPC_SHADOW_CRYPTO_THREADID_set_callback', - '#define CRYPTO_THREADID_set_numeric GRPC_SHADOW_CRYPTO_THREADID_set_numeric', - '#define CRYPTO_THREADID_set_pointer GRPC_SHADOW_CRYPTO_THREADID_set_pointer', - '#define CRYPTO_get_dynlock_create_callback GRPC_SHADOW_CRYPTO_get_dynlock_create_callback', - '#define CRYPTO_get_dynlock_destroy_callback GRPC_SHADOW_CRYPTO_get_dynlock_destroy_callback', - '#define CRYPTO_get_dynlock_lock_callback GRPC_SHADOW_CRYPTO_get_dynlock_lock_callback', - '#define CRYPTO_get_lock_name GRPC_SHADOW_CRYPTO_get_lock_name', - '#define CRYPTO_get_locking_callback GRPC_SHADOW_CRYPTO_get_locking_callback', - '#define CRYPTO_num_locks GRPC_SHADOW_CRYPTO_num_locks', - '#define CRYPTO_set_add_lock_callback GRPC_SHADOW_CRYPTO_set_add_lock_callback', - '#define CRYPTO_set_dynlock_create_callback GRPC_SHADOW_CRYPTO_set_dynlock_create_callback', - '#define CRYPTO_set_dynlock_destroy_callback GRPC_SHADOW_CRYPTO_set_dynlock_destroy_callback', - '#define CRYPTO_set_dynlock_lock_callback GRPC_SHADOW_CRYPTO_set_dynlock_lock_callback', - '#define CRYPTO_set_id_callback GRPC_SHADOW_CRYPTO_set_id_callback', - '#define CRYPTO_set_locking_callback GRPC_SHADOW_CRYPTO_set_locking_callback', - '#define CRYPTO_MUTEX_cleanup GRPC_SHADOW_CRYPTO_MUTEX_cleanup', - '#define CRYPTO_MUTEX_init GRPC_SHADOW_CRYPTO_MUTEX_init', - '#define CRYPTO_MUTEX_lock_read GRPC_SHADOW_CRYPTO_MUTEX_lock_read', - '#define CRYPTO_MUTEX_lock_write GRPC_SHADOW_CRYPTO_MUTEX_lock_write', - '#define CRYPTO_MUTEX_unlock_read GRPC_SHADOW_CRYPTO_MUTEX_unlock_read', - '#define CRYPTO_MUTEX_unlock_write GRPC_SHADOW_CRYPTO_MUTEX_unlock_write', - '#define CRYPTO_STATIC_MUTEX_lock_read GRPC_SHADOW_CRYPTO_STATIC_MUTEX_lock_read', - '#define CRYPTO_STATIC_MUTEX_lock_write GRPC_SHADOW_CRYPTO_STATIC_MUTEX_lock_write', - '#define CRYPTO_STATIC_MUTEX_unlock_read GRPC_SHADOW_CRYPTO_STATIC_MUTEX_unlock_read', - '#define CRYPTO_STATIC_MUTEX_unlock_write GRPC_SHADOW_CRYPTO_STATIC_MUTEX_unlock_write', - '#define CRYPTO_get_thread_local GRPC_SHADOW_CRYPTO_get_thread_local', - '#define CRYPTO_once GRPC_SHADOW_CRYPTO_once', - '#define CRYPTO_set_thread_local GRPC_SHADOW_CRYPTO_set_thread_local', - '#define sk_deep_copy GRPC_SHADOW_sk_deep_copy', - '#define sk_delete GRPC_SHADOW_sk_delete', - '#define sk_delete_ptr GRPC_SHADOW_sk_delete_ptr', - '#define sk_dup GRPC_SHADOW_sk_dup', - '#define sk_find GRPC_SHADOW_sk_find', - '#define sk_free GRPC_SHADOW_sk_free', - '#define sk_insert GRPC_SHADOW_sk_insert', - '#define sk_is_sorted GRPC_SHADOW_sk_is_sorted', - '#define sk_new GRPC_SHADOW_sk_new', - '#define sk_new_null GRPC_SHADOW_sk_new_null', - '#define sk_num GRPC_SHADOW_sk_num', - '#define sk_pop GRPC_SHADOW_sk_pop', - '#define sk_pop_free GRPC_SHADOW_sk_pop_free', - '#define sk_push GRPC_SHADOW_sk_push', - '#define sk_set GRPC_SHADOW_sk_set', - '#define sk_set_cmp_func GRPC_SHADOW_sk_set_cmp_func', - '#define sk_shift GRPC_SHADOW_sk_shift', - '#define sk_sort GRPC_SHADOW_sk_sort', - '#define sk_value GRPC_SHADOW_sk_value', - '#define sk_zero GRPC_SHADOW_sk_zero', - '#define lh_delete GRPC_SHADOW_lh_delete', - '#define lh_doall GRPC_SHADOW_lh_doall', - '#define lh_doall_arg GRPC_SHADOW_lh_doall_arg', - '#define lh_free GRPC_SHADOW_lh_free', - '#define lh_insert GRPC_SHADOW_lh_insert', - '#define lh_new GRPC_SHADOW_lh_new', - '#define lh_num_items GRPC_SHADOW_lh_num_items', - '#define lh_retrieve GRPC_SHADOW_lh_retrieve', - '#define lh_strhash GRPC_SHADOW_lh_strhash', - '#define ERR_SAVE_STATE_free GRPC_SHADOW_ERR_SAVE_STATE_free', - '#define ERR_add_error_data GRPC_SHADOW_ERR_add_error_data', - '#define ERR_add_error_dataf GRPC_SHADOW_ERR_add_error_dataf', - '#define ERR_clear_error GRPC_SHADOW_ERR_clear_error', - '#define ERR_clear_system_error GRPC_SHADOW_ERR_clear_system_error', - '#define ERR_error_string GRPC_SHADOW_ERR_error_string', - '#define ERR_error_string_n GRPC_SHADOW_ERR_error_string_n', - '#define ERR_free_strings GRPC_SHADOW_ERR_free_strings', - '#define ERR_func_error_string GRPC_SHADOW_ERR_func_error_string', - '#define ERR_get_error GRPC_SHADOW_ERR_get_error', - '#define ERR_get_error_line GRPC_SHADOW_ERR_get_error_line', - '#define ERR_get_error_line_data GRPC_SHADOW_ERR_get_error_line_data', - '#define ERR_get_next_error_library GRPC_SHADOW_ERR_get_next_error_library', - '#define ERR_lib_error_string GRPC_SHADOW_ERR_lib_error_string', - '#define ERR_load_BIO_strings GRPC_SHADOW_ERR_load_BIO_strings', - '#define ERR_load_ERR_strings GRPC_SHADOW_ERR_load_ERR_strings', - '#define ERR_load_crypto_strings GRPC_SHADOW_ERR_load_crypto_strings', - '#define ERR_peek_error GRPC_SHADOW_ERR_peek_error', - '#define ERR_peek_error_line GRPC_SHADOW_ERR_peek_error_line', - '#define ERR_peek_error_line_data GRPC_SHADOW_ERR_peek_error_line_data', - '#define ERR_peek_last_error GRPC_SHADOW_ERR_peek_last_error', - '#define ERR_peek_last_error_line GRPC_SHADOW_ERR_peek_last_error_line', - '#define ERR_peek_last_error_line_data GRPC_SHADOW_ERR_peek_last_error_line_data', - '#define ERR_pop_to_mark GRPC_SHADOW_ERR_pop_to_mark', - '#define ERR_print_errors_cb GRPC_SHADOW_ERR_print_errors_cb', - '#define ERR_print_errors_fp GRPC_SHADOW_ERR_print_errors_fp', - '#define ERR_put_error GRPC_SHADOW_ERR_put_error', - '#define ERR_reason_error_string GRPC_SHADOW_ERR_reason_error_string', - '#define ERR_remove_state GRPC_SHADOW_ERR_remove_state', - '#define ERR_remove_thread_state GRPC_SHADOW_ERR_remove_thread_state', - '#define ERR_restore_state GRPC_SHADOW_ERR_restore_state', - '#define ERR_save_state GRPC_SHADOW_ERR_save_state', - '#define ERR_set_mark GRPC_SHADOW_ERR_set_mark', - '#define kOpenSSLReasonStringData GRPC_SHADOW_kOpenSSLReasonStringData', - '#define kOpenSSLReasonValues GRPC_SHADOW_kOpenSSLReasonValues', - '#define kOpenSSLReasonValuesLen GRPC_SHADOW_kOpenSSLReasonValuesLen', - '#define EVP_DecodeBase64 GRPC_SHADOW_EVP_DecodeBase64', - '#define EVP_DecodeBlock GRPC_SHADOW_EVP_DecodeBlock', - '#define EVP_DecodeFinal GRPC_SHADOW_EVP_DecodeFinal', - '#define EVP_DecodeInit GRPC_SHADOW_EVP_DecodeInit', - '#define EVP_DecodeUpdate GRPC_SHADOW_EVP_DecodeUpdate', - '#define EVP_DecodedLength GRPC_SHADOW_EVP_DecodedLength', - '#define EVP_EncodeBlock GRPC_SHADOW_EVP_EncodeBlock', - '#define EVP_EncodeFinal GRPC_SHADOW_EVP_EncodeFinal', - '#define EVP_EncodeInit GRPC_SHADOW_EVP_EncodeInit', - '#define EVP_EncodeUpdate GRPC_SHADOW_EVP_EncodeUpdate', - '#define EVP_EncodedLength GRPC_SHADOW_EVP_EncodedLength', - '#define CBB_finish_i2d GRPC_SHADOW_CBB_finish_i2d', - '#define CBS_asn1_ber_to_der GRPC_SHADOW_CBS_asn1_ber_to_der', - '#define CBS_get_asn1_implicit_string GRPC_SHADOW_CBS_get_asn1_implicit_string', - '#define CBS_asn1_bitstring_has_bit GRPC_SHADOW_CBS_asn1_bitstring_has_bit', - '#define CBS_asn1_oid_to_text GRPC_SHADOW_CBS_asn1_oid_to_text', - '#define CBS_contains_zero_byte GRPC_SHADOW_CBS_contains_zero_byte', - '#define CBS_copy_bytes GRPC_SHADOW_CBS_copy_bytes', - '#define CBS_data GRPC_SHADOW_CBS_data', - '#define CBS_get_any_asn1 GRPC_SHADOW_CBS_get_any_asn1', - '#define CBS_get_any_asn1_element GRPC_SHADOW_CBS_get_any_asn1_element', - '#define CBS_get_any_ber_asn1_element GRPC_SHADOW_CBS_get_any_ber_asn1_element', - '#define CBS_get_asn1 GRPC_SHADOW_CBS_get_asn1', - '#define CBS_get_asn1_bool GRPC_SHADOW_CBS_get_asn1_bool', - '#define CBS_get_asn1_element GRPC_SHADOW_CBS_get_asn1_element', - '#define CBS_get_asn1_uint64 GRPC_SHADOW_CBS_get_asn1_uint64', - '#define CBS_get_bytes GRPC_SHADOW_CBS_get_bytes', - '#define CBS_get_last_u8 GRPC_SHADOW_CBS_get_last_u8', - '#define CBS_get_optional_asn1 GRPC_SHADOW_CBS_get_optional_asn1', - '#define CBS_get_optional_asn1_bool GRPC_SHADOW_CBS_get_optional_asn1_bool', - '#define CBS_get_optional_asn1_octet_string GRPC_SHADOW_CBS_get_optional_asn1_octet_string', - '#define CBS_get_optional_asn1_uint64 GRPC_SHADOW_CBS_get_optional_asn1_uint64', - '#define CBS_get_u16 GRPC_SHADOW_CBS_get_u16', - '#define CBS_get_u16_length_prefixed GRPC_SHADOW_CBS_get_u16_length_prefixed', - '#define CBS_get_u24 GRPC_SHADOW_CBS_get_u24', - '#define CBS_get_u24_length_prefixed GRPC_SHADOW_CBS_get_u24_length_prefixed', - '#define CBS_get_u32 GRPC_SHADOW_CBS_get_u32', - '#define CBS_get_u8 GRPC_SHADOW_CBS_get_u8', - '#define CBS_get_u8_length_prefixed GRPC_SHADOW_CBS_get_u8_length_prefixed', - '#define CBS_init GRPC_SHADOW_CBS_init', - '#define CBS_is_valid_asn1_bitstring GRPC_SHADOW_CBS_is_valid_asn1_bitstring', - '#define CBS_len GRPC_SHADOW_CBS_len', - '#define CBS_mem_equal GRPC_SHADOW_CBS_mem_equal', - '#define CBS_peek_asn1_tag GRPC_SHADOW_CBS_peek_asn1_tag', - '#define CBS_skip GRPC_SHADOW_CBS_skip', - '#define CBS_stow GRPC_SHADOW_CBS_stow', - '#define CBS_strdup GRPC_SHADOW_CBS_strdup', - '#define CBB_add_asn1 GRPC_SHADOW_CBB_add_asn1', - '#define CBB_add_asn1_bool GRPC_SHADOW_CBB_add_asn1_bool', - '#define CBB_add_asn1_octet_string GRPC_SHADOW_CBB_add_asn1_octet_string', - '#define CBB_add_asn1_oid_from_text GRPC_SHADOW_CBB_add_asn1_oid_from_text', - '#define CBB_add_asn1_uint64 GRPC_SHADOW_CBB_add_asn1_uint64', - '#define CBB_add_bytes GRPC_SHADOW_CBB_add_bytes', - '#define CBB_add_space GRPC_SHADOW_CBB_add_space', - '#define CBB_add_u16 GRPC_SHADOW_CBB_add_u16', - '#define CBB_add_u16_length_prefixed GRPC_SHADOW_CBB_add_u16_length_prefixed', - '#define CBB_add_u24 GRPC_SHADOW_CBB_add_u24', - '#define CBB_add_u24_length_prefixed GRPC_SHADOW_CBB_add_u24_length_prefixed', - '#define CBB_add_u32 GRPC_SHADOW_CBB_add_u32', - '#define CBB_add_u8 GRPC_SHADOW_CBB_add_u8', - '#define CBB_add_u8_length_prefixed GRPC_SHADOW_CBB_add_u8_length_prefixed', - '#define CBB_cleanup GRPC_SHADOW_CBB_cleanup', - '#define CBB_data GRPC_SHADOW_CBB_data', - '#define CBB_did_write GRPC_SHADOW_CBB_did_write', - '#define CBB_discard_child GRPC_SHADOW_CBB_discard_child', - '#define CBB_finish GRPC_SHADOW_CBB_finish', - '#define CBB_flush GRPC_SHADOW_CBB_flush', - '#define CBB_flush_asn1_set_of GRPC_SHADOW_CBB_flush_asn1_set_of', - '#define CBB_init GRPC_SHADOW_CBB_init', - '#define CBB_init_fixed GRPC_SHADOW_CBB_init_fixed', - '#define CBB_len GRPC_SHADOW_CBB_len', - '#define CBB_reserve GRPC_SHADOW_CBB_reserve', - '#define CBB_zero GRPC_SHADOW_CBB_zero', - '#define CRYPTO_BUFFER_POOL_free GRPC_SHADOW_CRYPTO_BUFFER_POOL_free', - '#define CRYPTO_BUFFER_POOL_new GRPC_SHADOW_CRYPTO_BUFFER_POOL_new', - '#define CRYPTO_BUFFER_data GRPC_SHADOW_CRYPTO_BUFFER_data', - '#define CRYPTO_BUFFER_free GRPC_SHADOW_CRYPTO_BUFFER_free', - '#define CRYPTO_BUFFER_init_CBS GRPC_SHADOW_CRYPTO_BUFFER_init_CBS', - '#define CRYPTO_BUFFER_len GRPC_SHADOW_CRYPTO_BUFFER_len', - '#define CRYPTO_BUFFER_new GRPC_SHADOW_CRYPTO_BUFFER_new', - '#define CRYPTO_BUFFER_new_from_CBS GRPC_SHADOW_CRYPTO_BUFFER_new_from_CBS', - '#define CRYPTO_BUFFER_up_ref GRPC_SHADOW_CRYPTO_BUFFER_up_ref', - '#define AES_cbc_encrypt GRPC_SHADOW_AES_cbc_encrypt', - '#define AES_cfb128_encrypt GRPC_SHADOW_AES_cfb128_encrypt', - '#define AES_ctr128_encrypt GRPC_SHADOW_AES_ctr128_encrypt', - '#define AES_decrypt GRPC_SHADOW_AES_decrypt', - '#define AES_ecb_encrypt GRPC_SHADOW_AES_ecb_encrypt', - '#define AES_encrypt GRPC_SHADOW_AES_encrypt', - '#define AES_ofb128_encrypt GRPC_SHADOW_AES_ofb128_encrypt', - '#define AES_set_decrypt_key GRPC_SHADOW_AES_set_decrypt_key', - '#define AES_set_encrypt_key GRPC_SHADOW_AES_set_encrypt_key', - '#define AES_unwrap_key GRPC_SHADOW_AES_unwrap_key', - '#define AES_wrap_key GRPC_SHADOW_AES_wrap_key', - '#define BN_BLINDING_convert GRPC_SHADOW_BN_BLINDING_convert', - '#define BN_BLINDING_free GRPC_SHADOW_BN_BLINDING_free', - '#define BN_BLINDING_invert GRPC_SHADOW_BN_BLINDING_invert', - '#define BN_BLINDING_new GRPC_SHADOW_BN_BLINDING_new', - '#define BN_CTX_end GRPC_SHADOW_BN_CTX_end', - '#define BN_CTX_free GRPC_SHADOW_BN_CTX_free', - '#define BN_CTX_get GRPC_SHADOW_BN_CTX_get', - '#define BN_CTX_new GRPC_SHADOW_BN_CTX_new', - '#define BN_CTX_start GRPC_SHADOW_BN_CTX_start', - '#define BN_GENCB_call GRPC_SHADOW_BN_GENCB_call', - '#define BN_GENCB_set GRPC_SHADOW_BN_GENCB_set', - '#define BN_MONT_CTX_copy GRPC_SHADOW_BN_MONT_CTX_copy', - '#define BN_MONT_CTX_free GRPC_SHADOW_BN_MONT_CTX_free', - '#define BN_MONT_CTX_new GRPC_SHADOW_BN_MONT_CTX_new', - '#define BN_MONT_CTX_new_for_modulus GRPC_SHADOW_BN_MONT_CTX_new_for_modulus', - '#define BN_MONT_CTX_set GRPC_SHADOW_BN_MONT_CTX_set', - '#define BN_MONT_CTX_set_locked GRPC_SHADOW_BN_MONT_CTX_set_locked', - '#define BN_abs_is_word GRPC_SHADOW_BN_abs_is_word', - '#define BN_add GRPC_SHADOW_BN_add', - '#define BN_add_word GRPC_SHADOW_BN_add_word', - '#define BN_bin2bn GRPC_SHADOW_BN_bin2bn', - '#define BN_bn2bin GRPC_SHADOW_BN_bn2bin', - '#define BN_bn2bin_padded GRPC_SHADOW_BN_bn2bin_padded', - '#define BN_bn2le_padded GRPC_SHADOW_BN_bn2le_padded', - '#define BN_clear GRPC_SHADOW_BN_clear', - '#define BN_clear_bit GRPC_SHADOW_BN_clear_bit', - '#define BN_clear_free GRPC_SHADOW_BN_clear_free', - '#define BN_cmp GRPC_SHADOW_BN_cmp', - '#define BN_cmp_word GRPC_SHADOW_BN_cmp_word', - '#define BN_copy GRPC_SHADOW_BN_copy', - '#define BN_count_low_zero_bits GRPC_SHADOW_BN_count_low_zero_bits', - '#define BN_div GRPC_SHADOW_BN_div', - '#define BN_div_word GRPC_SHADOW_BN_div_word', - '#define BN_dup GRPC_SHADOW_BN_dup', - '#define BN_enhanced_miller_rabin_primality_test GRPC_SHADOW_BN_enhanced_miller_rabin_primality_test', - '#define BN_equal_consttime GRPC_SHADOW_BN_equal_consttime', - '#define BN_exp GRPC_SHADOW_BN_exp', - '#define BN_free GRPC_SHADOW_BN_free', - '#define BN_from_montgomery GRPC_SHADOW_BN_from_montgomery', - '#define BN_gcd GRPC_SHADOW_BN_gcd', - '#define BN_generate_prime_ex GRPC_SHADOW_BN_generate_prime_ex', - '#define BN_get_u64 GRPC_SHADOW_BN_get_u64', - '#define BN_get_word GRPC_SHADOW_BN_get_word', - '#define BN_init GRPC_SHADOW_BN_init', - '#define BN_is_bit_set GRPC_SHADOW_BN_is_bit_set', - '#define BN_is_negative GRPC_SHADOW_BN_is_negative', - '#define BN_is_odd GRPC_SHADOW_BN_is_odd', - '#define BN_is_one GRPC_SHADOW_BN_is_one', - '#define BN_is_pow2 GRPC_SHADOW_BN_is_pow2', - '#define BN_is_prime_ex GRPC_SHADOW_BN_is_prime_ex', - '#define BN_is_prime_fasttest_ex GRPC_SHADOW_BN_is_prime_fasttest_ex', - '#define BN_is_word GRPC_SHADOW_BN_is_word', - '#define BN_is_zero GRPC_SHADOW_BN_is_zero', - '#define BN_le2bn GRPC_SHADOW_BN_le2bn', - '#define BN_lshift GRPC_SHADOW_BN_lshift', - '#define BN_lshift1 GRPC_SHADOW_BN_lshift1', - '#define BN_mask_bits GRPC_SHADOW_BN_mask_bits', - '#define BN_mod_add GRPC_SHADOW_BN_mod_add', - '#define BN_mod_add_quick GRPC_SHADOW_BN_mod_add_quick', - '#define BN_mod_exp GRPC_SHADOW_BN_mod_exp', - '#define BN_mod_exp2_mont GRPC_SHADOW_BN_mod_exp2_mont', - '#define BN_mod_exp_mont GRPC_SHADOW_BN_mod_exp_mont', - '#define BN_mod_exp_mont_consttime GRPC_SHADOW_BN_mod_exp_mont_consttime', - '#define BN_mod_exp_mont_word GRPC_SHADOW_BN_mod_exp_mont_word', - '#define BN_mod_inverse GRPC_SHADOW_BN_mod_inverse', - '#define BN_mod_inverse_blinded GRPC_SHADOW_BN_mod_inverse_blinded', - '#define BN_mod_inverse_odd GRPC_SHADOW_BN_mod_inverse_odd', - '#define BN_mod_lshift GRPC_SHADOW_BN_mod_lshift', - '#define BN_mod_lshift1 GRPC_SHADOW_BN_mod_lshift1', - '#define BN_mod_lshift1_quick GRPC_SHADOW_BN_mod_lshift1_quick', - '#define BN_mod_lshift_quick GRPC_SHADOW_BN_mod_lshift_quick', - '#define BN_mod_mul GRPC_SHADOW_BN_mod_mul', - '#define BN_mod_mul_montgomery GRPC_SHADOW_BN_mod_mul_montgomery', - '#define BN_mod_pow2 GRPC_SHADOW_BN_mod_pow2', - '#define BN_mod_sqr GRPC_SHADOW_BN_mod_sqr', - '#define BN_mod_sqrt GRPC_SHADOW_BN_mod_sqrt', - '#define BN_mod_sub GRPC_SHADOW_BN_mod_sub', - '#define BN_mod_sub_quick GRPC_SHADOW_BN_mod_sub_quick', - '#define BN_mod_word GRPC_SHADOW_BN_mod_word', - '#define BN_mul GRPC_SHADOW_BN_mul', - '#define BN_mul_word GRPC_SHADOW_BN_mul_word', - '#define BN_new GRPC_SHADOW_BN_new', - '#define BN_nnmod GRPC_SHADOW_BN_nnmod', - '#define BN_nnmod_pow2 GRPC_SHADOW_BN_nnmod_pow2', - '#define BN_num_bits GRPC_SHADOW_BN_num_bits', - '#define BN_num_bits_word GRPC_SHADOW_BN_num_bits_word', - '#define BN_num_bytes GRPC_SHADOW_BN_num_bytes', - '#define BN_one GRPC_SHADOW_BN_one', - '#define BN_primality_test GRPC_SHADOW_BN_primality_test', - '#define BN_pseudo_rand GRPC_SHADOW_BN_pseudo_rand', - '#define BN_pseudo_rand_range GRPC_SHADOW_BN_pseudo_rand_range', - '#define BN_rand GRPC_SHADOW_BN_rand', - '#define BN_rand_range GRPC_SHADOW_BN_rand_range', - '#define BN_rand_range_ex GRPC_SHADOW_BN_rand_range_ex', - '#define BN_rshift GRPC_SHADOW_BN_rshift', - '#define BN_rshift1 GRPC_SHADOW_BN_rshift1', - '#define BN_set_bit GRPC_SHADOW_BN_set_bit', - '#define BN_set_negative GRPC_SHADOW_BN_set_negative', - '#define BN_set_u64 GRPC_SHADOW_BN_set_u64', - '#define BN_set_word GRPC_SHADOW_BN_set_word', - '#define BN_sqr GRPC_SHADOW_BN_sqr', - '#define BN_sqrt GRPC_SHADOW_BN_sqrt', - '#define BN_sub GRPC_SHADOW_BN_sub', - '#define BN_sub_word GRPC_SHADOW_BN_sub_word', - '#define BN_to_montgomery GRPC_SHADOW_BN_to_montgomery', - '#define BN_uadd GRPC_SHADOW_BN_uadd', - '#define BN_ucmp GRPC_SHADOW_BN_ucmp', - '#define BN_usub GRPC_SHADOW_BN_usub', - '#define BN_value_one GRPC_SHADOW_BN_value_one', - '#define BN_zero GRPC_SHADOW_BN_zero', - '#define BORINGSSL_self_test GRPC_SHADOW_BORINGSSL_self_test', - '#define CRYPTO_POLYVAL_finish GRPC_SHADOW_CRYPTO_POLYVAL_finish', - '#define CRYPTO_POLYVAL_init GRPC_SHADOW_CRYPTO_POLYVAL_init', - '#define CRYPTO_POLYVAL_update_blocks GRPC_SHADOW_CRYPTO_POLYVAL_update_blocks', - '#define CRYPTO_cbc128_decrypt GRPC_SHADOW_CRYPTO_cbc128_decrypt', - '#define CRYPTO_cbc128_encrypt GRPC_SHADOW_CRYPTO_cbc128_encrypt', - '#define CRYPTO_ccm128_decrypt GRPC_SHADOW_CRYPTO_ccm128_decrypt', - '#define CRYPTO_ccm128_encrypt GRPC_SHADOW_CRYPTO_ccm128_encrypt', - '#define CRYPTO_ccm128_init GRPC_SHADOW_CRYPTO_ccm128_init', - '#define CRYPTO_ccm128_max_input GRPC_SHADOW_CRYPTO_ccm128_max_input', - '#define CRYPTO_cfb128_1_encrypt GRPC_SHADOW_CRYPTO_cfb128_1_encrypt', - '#define CRYPTO_cfb128_8_encrypt GRPC_SHADOW_CRYPTO_cfb128_8_encrypt', - '#define CRYPTO_cfb128_encrypt GRPC_SHADOW_CRYPTO_cfb128_encrypt', - '#define CRYPTO_ctr128_encrypt GRPC_SHADOW_CRYPTO_ctr128_encrypt', - '#define CRYPTO_ctr128_encrypt_ctr32 GRPC_SHADOW_CRYPTO_ctr128_encrypt_ctr32', - '#define CRYPTO_gcm128_aad GRPC_SHADOW_CRYPTO_gcm128_aad', - '#define CRYPTO_gcm128_decrypt GRPC_SHADOW_CRYPTO_gcm128_decrypt', - '#define CRYPTO_gcm128_decrypt_ctr32 GRPC_SHADOW_CRYPTO_gcm128_decrypt_ctr32', - '#define CRYPTO_gcm128_encrypt GRPC_SHADOW_CRYPTO_gcm128_encrypt', - '#define CRYPTO_gcm128_encrypt_ctr32 GRPC_SHADOW_CRYPTO_gcm128_encrypt_ctr32', - '#define CRYPTO_gcm128_finish GRPC_SHADOW_CRYPTO_gcm128_finish', - '#define CRYPTO_gcm128_init GRPC_SHADOW_CRYPTO_gcm128_init', - '#define CRYPTO_gcm128_setiv GRPC_SHADOW_CRYPTO_gcm128_setiv', - '#define CRYPTO_gcm128_tag GRPC_SHADOW_CRYPTO_gcm128_tag', - '#define CRYPTO_ghash_init GRPC_SHADOW_CRYPTO_ghash_init', - '#define CRYPTO_ofb128_encrypt GRPC_SHADOW_CRYPTO_ofb128_encrypt', - '#define CRYPTO_sysrand GRPC_SHADOW_CRYPTO_sysrand', - '#define CRYPTO_tls1_prf GRPC_SHADOW_CRYPTO_tls1_prf', - '#define CTR_DRBG_clear GRPC_SHADOW_CTR_DRBG_clear', - '#define CTR_DRBG_generate GRPC_SHADOW_CTR_DRBG_generate', - '#define CTR_DRBG_init GRPC_SHADOW_CTR_DRBG_init', - '#define CTR_DRBG_reseed GRPC_SHADOW_CTR_DRBG_reseed', - '#define DES_decrypt3 GRPC_SHADOW_DES_decrypt3', - '#define DES_ecb3_encrypt GRPC_SHADOW_DES_ecb3_encrypt', - '#define DES_ecb_encrypt GRPC_SHADOW_DES_ecb_encrypt', - '#define DES_ede2_cbc_encrypt GRPC_SHADOW_DES_ede2_cbc_encrypt', - '#define DES_ede3_cbc_encrypt GRPC_SHADOW_DES_ede3_cbc_encrypt', - '#define DES_encrypt3 GRPC_SHADOW_DES_encrypt3', - '#define DES_ncbc_encrypt GRPC_SHADOW_DES_ncbc_encrypt', - '#define DES_set_key GRPC_SHADOW_DES_set_key', - '#define DES_set_key_unchecked GRPC_SHADOW_DES_set_key_unchecked', - '#define DES_set_odd_parity GRPC_SHADOW_DES_set_odd_parity', - '#define ECDSA_SIG_free GRPC_SHADOW_ECDSA_SIG_free', - '#define ECDSA_SIG_get0 GRPC_SHADOW_ECDSA_SIG_get0', - '#define ECDSA_SIG_new GRPC_SHADOW_ECDSA_SIG_new', - '#define ECDSA_SIG_set0 GRPC_SHADOW_ECDSA_SIG_set0', - '#define ECDSA_do_sign GRPC_SHADOW_ECDSA_do_sign', - '#define ECDSA_do_verify GRPC_SHADOW_ECDSA_do_verify', - '#define EC_GFp_mont_method GRPC_SHADOW_EC_GFp_mont_method', - '#define EC_GFp_nistp224_method GRPC_SHADOW_EC_GFp_nistp224_method', - '#define EC_GFp_nistp256_method GRPC_SHADOW_EC_GFp_nistp256_method', - '#define EC_GFp_nistz256_method GRPC_SHADOW_EC_GFp_nistz256_method', - '#define EC_GROUP_cmp GRPC_SHADOW_EC_GROUP_cmp', - '#define EC_GROUP_dup GRPC_SHADOW_EC_GROUP_dup', - '#define EC_GROUP_free GRPC_SHADOW_EC_GROUP_free', - '#define EC_GROUP_get0_generator GRPC_SHADOW_EC_GROUP_get0_generator', - '#define EC_GROUP_get0_order GRPC_SHADOW_EC_GROUP_get0_order', - '#define EC_GROUP_get_cofactor GRPC_SHADOW_EC_GROUP_get_cofactor', - '#define EC_GROUP_get_curve_GFp GRPC_SHADOW_EC_GROUP_get_curve_GFp', - '#define EC_GROUP_get_curve_name GRPC_SHADOW_EC_GROUP_get_curve_name', - '#define EC_GROUP_get_degree GRPC_SHADOW_EC_GROUP_get_degree', - '#define EC_GROUP_get_order GRPC_SHADOW_EC_GROUP_get_order', - '#define EC_GROUP_method_of GRPC_SHADOW_EC_GROUP_method_of', - '#define EC_GROUP_new_by_curve_name GRPC_SHADOW_EC_GROUP_new_by_curve_name', - '#define EC_GROUP_new_curve_GFp GRPC_SHADOW_EC_GROUP_new_curve_GFp', - '#define EC_GROUP_set_asn1_flag GRPC_SHADOW_EC_GROUP_set_asn1_flag', - '#define EC_GROUP_set_generator GRPC_SHADOW_EC_GROUP_set_generator', - '#define EC_GROUP_set_point_conversion_form GRPC_SHADOW_EC_GROUP_set_point_conversion_form', - '#define EC_KEY_check_fips GRPC_SHADOW_EC_KEY_check_fips', - '#define EC_KEY_check_key GRPC_SHADOW_EC_KEY_check_key', - '#define EC_KEY_dup GRPC_SHADOW_EC_KEY_dup', - '#define EC_KEY_free GRPC_SHADOW_EC_KEY_free', - '#define EC_KEY_generate_key GRPC_SHADOW_EC_KEY_generate_key', - '#define EC_KEY_generate_key_fips GRPC_SHADOW_EC_KEY_generate_key_fips', - '#define EC_KEY_get0_group GRPC_SHADOW_EC_KEY_get0_group', - '#define EC_KEY_get0_private_key GRPC_SHADOW_EC_KEY_get0_private_key', - '#define EC_KEY_get0_public_key GRPC_SHADOW_EC_KEY_get0_public_key', - '#define EC_KEY_get_conv_form GRPC_SHADOW_EC_KEY_get_conv_form', - '#define EC_KEY_get_enc_flags GRPC_SHADOW_EC_KEY_get_enc_flags', - '#define EC_KEY_get_ex_data GRPC_SHADOW_EC_KEY_get_ex_data', - '#define EC_KEY_get_ex_new_index GRPC_SHADOW_EC_KEY_get_ex_new_index', - '#define EC_KEY_is_opaque GRPC_SHADOW_EC_KEY_is_opaque', - '#define EC_KEY_new GRPC_SHADOW_EC_KEY_new', - '#define EC_KEY_new_by_curve_name GRPC_SHADOW_EC_KEY_new_by_curve_name', - '#define EC_KEY_new_method GRPC_SHADOW_EC_KEY_new_method', - '#define EC_KEY_set_asn1_flag GRPC_SHADOW_EC_KEY_set_asn1_flag', - '#define EC_KEY_set_conv_form GRPC_SHADOW_EC_KEY_set_conv_form', - '#define EC_KEY_set_enc_flags GRPC_SHADOW_EC_KEY_set_enc_flags', - '#define EC_KEY_set_ex_data GRPC_SHADOW_EC_KEY_set_ex_data', - '#define EC_KEY_set_group GRPC_SHADOW_EC_KEY_set_group', - '#define EC_KEY_set_private_key GRPC_SHADOW_EC_KEY_set_private_key', - '#define EC_KEY_set_public_key GRPC_SHADOW_EC_KEY_set_public_key', - '#define EC_KEY_set_public_key_affine_coordinates GRPC_SHADOW_EC_KEY_set_public_key_affine_coordinates', - '#define EC_KEY_up_ref GRPC_SHADOW_EC_KEY_up_ref', - '#define EC_METHOD_get_field_type GRPC_SHADOW_EC_METHOD_get_field_type', - '#define EC_POINT_add GRPC_SHADOW_EC_POINT_add', - '#define EC_POINT_clear_free GRPC_SHADOW_EC_POINT_clear_free', - '#define EC_POINT_cmp GRPC_SHADOW_EC_POINT_cmp', - '#define EC_POINT_copy GRPC_SHADOW_EC_POINT_copy', - '#define EC_POINT_dbl GRPC_SHADOW_EC_POINT_dbl', - '#define EC_POINT_dup GRPC_SHADOW_EC_POINT_dup', - '#define EC_POINT_free GRPC_SHADOW_EC_POINT_free', - '#define EC_POINT_get_affine_coordinates_GFp GRPC_SHADOW_EC_POINT_get_affine_coordinates_GFp', - '#define EC_POINT_invert GRPC_SHADOW_EC_POINT_invert', - '#define EC_POINT_is_at_infinity GRPC_SHADOW_EC_POINT_is_at_infinity', - '#define EC_POINT_is_on_curve GRPC_SHADOW_EC_POINT_is_on_curve', - '#define EC_POINT_make_affine GRPC_SHADOW_EC_POINT_make_affine', - '#define EC_POINT_mul GRPC_SHADOW_EC_POINT_mul', - '#define EC_POINT_new GRPC_SHADOW_EC_POINT_new', - '#define EC_POINT_oct2point GRPC_SHADOW_EC_POINT_oct2point', - '#define EC_POINT_point2oct GRPC_SHADOW_EC_POINT_point2oct', - '#define EC_POINT_set_affine_coordinates_GFp GRPC_SHADOW_EC_POINT_set_affine_coordinates_GFp', - '#define EC_POINT_set_compressed_coordinates_GFp GRPC_SHADOW_EC_POINT_set_compressed_coordinates_GFp', - '#define EC_POINT_set_to_infinity GRPC_SHADOW_EC_POINT_set_to_infinity', - '#define EC_POINTs_make_affine GRPC_SHADOW_EC_POINTs_make_affine', - '#define EC_get_builtin_curves GRPC_SHADOW_EC_get_builtin_curves', - '#define EVP_AEAD_CTX_aead GRPC_SHADOW_EVP_AEAD_CTX_aead', - '#define EVP_AEAD_CTX_cleanup GRPC_SHADOW_EVP_AEAD_CTX_cleanup', - '#define EVP_AEAD_CTX_free GRPC_SHADOW_EVP_AEAD_CTX_free', - '#define EVP_AEAD_CTX_get_iv GRPC_SHADOW_EVP_AEAD_CTX_get_iv', - '#define EVP_AEAD_CTX_init GRPC_SHADOW_EVP_AEAD_CTX_init', - '#define EVP_AEAD_CTX_init_with_direction GRPC_SHADOW_EVP_AEAD_CTX_init_with_direction', - '#define EVP_AEAD_CTX_new GRPC_SHADOW_EVP_AEAD_CTX_new', - '#define EVP_AEAD_CTX_open GRPC_SHADOW_EVP_AEAD_CTX_open', - '#define EVP_AEAD_CTX_open_gather GRPC_SHADOW_EVP_AEAD_CTX_open_gather', - '#define EVP_AEAD_CTX_seal GRPC_SHADOW_EVP_AEAD_CTX_seal', - '#define EVP_AEAD_CTX_seal_scatter GRPC_SHADOW_EVP_AEAD_CTX_seal_scatter', - '#define EVP_AEAD_CTX_tag_len GRPC_SHADOW_EVP_AEAD_CTX_tag_len', - '#define EVP_AEAD_CTX_zero GRPC_SHADOW_EVP_AEAD_CTX_zero', - '#define EVP_AEAD_key_length GRPC_SHADOW_EVP_AEAD_key_length', - '#define EVP_AEAD_max_overhead GRPC_SHADOW_EVP_AEAD_max_overhead', - '#define EVP_AEAD_max_tag_len GRPC_SHADOW_EVP_AEAD_max_tag_len', - '#define EVP_AEAD_nonce_length GRPC_SHADOW_EVP_AEAD_nonce_length', - '#define EVP_CIPHER_CTX_block_size GRPC_SHADOW_EVP_CIPHER_CTX_block_size', - '#define EVP_CIPHER_CTX_cipher GRPC_SHADOW_EVP_CIPHER_CTX_cipher', - '#define EVP_CIPHER_CTX_cleanup GRPC_SHADOW_EVP_CIPHER_CTX_cleanup', - '#define EVP_CIPHER_CTX_copy GRPC_SHADOW_EVP_CIPHER_CTX_copy', - '#define EVP_CIPHER_CTX_ctrl GRPC_SHADOW_EVP_CIPHER_CTX_ctrl', - '#define EVP_CIPHER_CTX_flags GRPC_SHADOW_EVP_CIPHER_CTX_flags', - '#define EVP_CIPHER_CTX_free GRPC_SHADOW_EVP_CIPHER_CTX_free', - '#define EVP_CIPHER_CTX_get_app_data GRPC_SHADOW_EVP_CIPHER_CTX_get_app_data', - '#define EVP_CIPHER_CTX_init GRPC_SHADOW_EVP_CIPHER_CTX_init', - '#define EVP_CIPHER_CTX_iv_length GRPC_SHADOW_EVP_CIPHER_CTX_iv_length', - '#define EVP_CIPHER_CTX_key_length GRPC_SHADOW_EVP_CIPHER_CTX_key_length', - '#define EVP_CIPHER_CTX_mode GRPC_SHADOW_EVP_CIPHER_CTX_mode', - '#define EVP_CIPHER_CTX_new GRPC_SHADOW_EVP_CIPHER_CTX_new', - '#define EVP_CIPHER_CTX_nid GRPC_SHADOW_EVP_CIPHER_CTX_nid', - '#define EVP_CIPHER_CTX_reset GRPC_SHADOW_EVP_CIPHER_CTX_reset', - '#define EVP_CIPHER_CTX_set_app_data GRPC_SHADOW_EVP_CIPHER_CTX_set_app_data', - '#define EVP_CIPHER_CTX_set_flags GRPC_SHADOW_EVP_CIPHER_CTX_set_flags', - '#define EVP_CIPHER_CTX_set_key_length GRPC_SHADOW_EVP_CIPHER_CTX_set_key_length', - '#define EVP_CIPHER_CTX_set_padding GRPC_SHADOW_EVP_CIPHER_CTX_set_padding', - '#define EVP_CIPHER_block_size GRPC_SHADOW_EVP_CIPHER_block_size', - '#define EVP_CIPHER_flags GRPC_SHADOW_EVP_CIPHER_flags', - '#define EVP_CIPHER_iv_length GRPC_SHADOW_EVP_CIPHER_iv_length', - '#define EVP_CIPHER_key_length GRPC_SHADOW_EVP_CIPHER_key_length', - '#define EVP_CIPHER_mode GRPC_SHADOW_EVP_CIPHER_mode', - '#define EVP_CIPHER_nid GRPC_SHADOW_EVP_CIPHER_nid', - '#define EVP_Cipher GRPC_SHADOW_EVP_Cipher', - '#define EVP_CipherFinal_ex GRPC_SHADOW_EVP_CipherFinal_ex', - '#define EVP_CipherInit GRPC_SHADOW_EVP_CipherInit', - '#define EVP_CipherInit_ex GRPC_SHADOW_EVP_CipherInit_ex', - '#define EVP_CipherUpdate GRPC_SHADOW_EVP_CipherUpdate', - '#define EVP_DecryptFinal_ex GRPC_SHADOW_EVP_DecryptFinal_ex', - '#define EVP_DecryptInit GRPC_SHADOW_EVP_DecryptInit', - '#define EVP_DecryptInit_ex GRPC_SHADOW_EVP_DecryptInit_ex', - '#define EVP_DecryptUpdate GRPC_SHADOW_EVP_DecryptUpdate', - '#define EVP_Digest GRPC_SHADOW_EVP_Digest', - '#define EVP_DigestFinal GRPC_SHADOW_EVP_DigestFinal', - '#define EVP_DigestFinal_ex GRPC_SHADOW_EVP_DigestFinal_ex', - '#define EVP_DigestInit GRPC_SHADOW_EVP_DigestInit', - '#define EVP_DigestInit_ex GRPC_SHADOW_EVP_DigestInit_ex', - '#define EVP_DigestUpdate GRPC_SHADOW_EVP_DigestUpdate', - '#define EVP_EncryptFinal_ex GRPC_SHADOW_EVP_EncryptFinal_ex', - '#define EVP_EncryptInit GRPC_SHADOW_EVP_EncryptInit', - '#define EVP_EncryptInit_ex GRPC_SHADOW_EVP_EncryptInit_ex', - '#define EVP_EncryptUpdate GRPC_SHADOW_EVP_EncryptUpdate', - '#define EVP_MD_CTX_block_size GRPC_SHADOW_EVP_MD_CTX_block_size', - '#define EVP_MD_CTX_cleanup GRPC_SHADOW_EVP_MD_CTX_cleanup', - '#define EVP_MD_CTX_copy GRPC_SHADOW_EVP_MD_CTX_copy', - '#define EVP_MD_CTX_copy_ex GRPC_SHADOW_EVP_MD_CTX_copy_ex', - '#define EVP_MD_CTX_create GRPC_SHADOW_EVP_MD_CTX_create', - '#define EVP_MD_CTX_destroy GRPC_SHADOW_EVP_MD_CTX_destroy', - '#define EVP_MD_CTX_free GRPC_SHADOW_EVP_MD_CTX_free', - '#define EVP_MD_CTX_init GRPC_SHADOW_EVP_MD_CTX_init', - '#define EVP_MD_CTX_md GRPC_SHADOW_EVP_MD_CTX_md', - '#define EVP_MD_CTX_new GRPC_SHADOW_EVP_MD_CTX_new', - '#define EVP_MD_CTX_reset GRPC_SHADOW_EVP_MD_CTX_reset', - '#define EVP_MD_CTX_size GRPC_SHADOW_EVP_MD_CTX_size', - '#define EVP_MD_CTX_type GRPC_SHADOW_EVP_MD_CTX_type', - '#define EVP_MD_block_size GRPC_SHADOW_EVP_MD_block_size', - '#define EVP_MD_flags GRPC_SHADOW_EVP_MD_flags', - '#define EVP_MD_size GRPC_SHADOW_EVP_MD_size', - '#define EVP_MD_type GRPC_SHADOW_EVP_MD_type', - '#define EVP_add_cipher_alias GRPC_SHADOW_EVP_add_cipher_alias', - '#define EVP_add_digest GRPC_SHADOW_EVP_add_digest', - '#define EVP_aead_aes_128_gcm GRPC_SHADOW_EVP_aead_aes_128_gcm', - '#define EVP_aead_aes_128_gcm_tls12 GRPC_SHADOW_EVP_aead_aes_128_gcm_tls12', - '#define EVP_aead_aes_256_gcm GRPC_SHADOW_EVP_aead_aes_256_gcm', - '#define EVP_aead_aes_256_gcm_tls12 GRPC_SHADOW_EVP_aead_aes_256_gcm_tls12', - '#define EVP_aes_128_cbc GRPC_SHADOW_EVP_aes_128_cbc', - '#define EVP_aes_128_ctr GRPC_SHADOW_EVP_aes_128_ctr', - '#define EVP_aes_128_ecb GRPC_SHADOW_EVP_aes_128_ecb', - '#define EVP_aes_128_gcm GRPC_SHADOW_EVP_aes_128_gcm', - '#define EVP_aes_128_ofb GRPC_SHADOW_EVP_aes_128_ofb', - '#define EVP_aes_192_cbc GRPC_SHADOW_EVP_aes_192_cbc', - '#define EVP_aes_192_ctr GRPC_SHADOW_EVP_aes_192_ctr', - '#define EVP_aes_192_ecb GRPC_SHADOW_EVP_aes_192_ecb', - '#define EVP_aes_192_gcm GRPC_SHADOW_EVP_aes_192_gcm', - '#define EVP_aes_256_cbc GRPC_SHADOW_EVP_aes_256_cbc', - '#define EVP_aes_256_ctr GRPC_SHADOW_EVP_aes_256_ctr', - '#define EVP_aes_256_ecb GRPC_SHADOW_EVP_aes_256_ecb', - '#define EVP_aes_256_gcm GRPC_SHADOW_EVP_aes_256_gcm', - '#define EVP_aes_256_ofb GRPC_SHADOW_EVP_aes_256_ofb', - '#define EVP_des_cbc GRPC_SHADOW_EVP_des_cbc', - '#define EVP_des_ecb GRPC_SHADOW_EVP_des_ecb', - '#define EVP_des_ede GRPC_SHADOW_EVP_des_ede', - '#define EVP_des_ede3 GRPC_SHADOW_EVP_des_ede3', - '#define EVP_des_ede3_cbc GRPC_SHADOW_EVP_des_ede3_cbc', - '#define EVP_des_ede_cbc GRPC_SHADOW_EVP_des_ede_cbc', - '#define EVP_has_aes_hardware GRPC_SHADOW_EVP_has_aes_hardware', - '#define EVP_md4 GRPC_SHADOW_EVP_md4', - '#define EVP_md5 GRPC_SHADOW_EVP_md5', - '#define EVP_md5_sha1 GRPC_SHADOW_EVP_md5_sha1', - '#define EVP_sha1 GRPC_SHADOW_EVP_sha1', - '#define EVP_sha224 GRPC_SHADOW_EVP_sha224', - '#define EVP_sha256 GRPC_SHADOW_EVP_sha256', - '#define EVP_sha384 GRPC_SHADOW_EVP_sha384', - '#define EVP_sha512 GRPC_SHADOW_EVP_sha512', - '#define HMAC GRPC_SHADOW_HMAC', - '#define HMAC_CTX_cleanup GRPC_SHADOW_HMAC_CTX_cleanup', - '#define HMAC_CTX_copy GRPC_SHADOW_HMAC_CTX_copy', - '#define HMAC_CTX_copy_ex GRPC_SHADOW_HMAC_CTX_copy_ex', - '#define HMAC_CTX_free GRPC_SHADOW_HMAC_CTX_free', - '#define HMAC_CTX_init GRPC_SHADOW_HMAC_CTX_init', - '#define HMAC_CTX_new GRPC_SHADOW_HMAC_CTX_new', - '#define HMAC_CTX_reset GRPC_SHADOW_HMAC_CTX_reset', - '#define HMAC_Final GRPC_SHADOW_HMAC_Final', - '#define HMAC_Init GRPC_SHADOW_HMAC_Init', - '#define HMAC_Init_ex GRPC_SHADOW_HMAC_Init_ex', - '#define HMAC_Update GRPC_SHADOW_HMAC_Update', - '#define HMAC_size GRPC_SHADOW_HMAC_size', - '#define MD4 GRPC_SHADOW_MD4', - '#define MD4_Final GRPC_SHADOW_MD4_Final', - '#define MD4_Init GRPC_SHADOW_MD4_Init', - '#define MD4_Transform GRPC_SHADOW_MD4_Transform', - '#define MD4_Update GRPC_SHADOW_MD4_Update', - '#define MD5 GRPC_SHADOW_MD5', - '#define MD5_Final GRPC_SHADOW_MD5_Final', - '#define MD5_Init GRPC_SHADOW_MD5_Init', - '#define MD5_Transform GRPC_SHADOW_MD5_Transform', - '#define MD5_Update GRPC_SHADOW_MD5_Update', - '#define OPENSSL_built_in_curves GRPC_SHADOW_OPENSSL_built_in_curves', - '#define RAND_bytes GRPC_SHADOW_RAND_bytes', - '#define RAND_bytes_with_additional_data GRPC_SHADOW_RAND_bytes_with_additional_data', - '#define RAND_pseudo_bytes GRPC_SHADOW_RAND_pseudo_bytes', - '#define RAND_set_urandom_fd GRPC_SHADOW_RAND_set_urandom_fd', - '#define RSAZ_1024_mod_exp_avx2 GRPC_SHADOW_RSAZ_1024_mod_exp_avx2', - '#define RSA_add_pkcs1_prefix GRPC_SHADOW_RSA_add_pkcs1_prefix', - '#define RSA_bits GRPC_SHADOW_RSA_bits', - '#define RSA_blinding_on GRPC_SHADOW_RSA_blinding_on', - '#define RSA_check_fips GRPC_SHADOW_RSA_check_fips', - '#define RSA_check_key GRPC_SHADOW_RSA_check_key', - '#define RSA_decrypt GRPC_SHADOW_RSA_decrypt', - '#define RSA_default_method GRPC_SHADOW_RSA_default_method', - '#define RSA_encrypt GRPC_SHADOW_RSA_encrypt', - '#define RSA_flags GRPC_SHADOW_RSA_flags', - '#define RSA_free GRPC_SHADOW_RSA_free', - '#define RSA_generate_key_ex GRPC_SHADOW_RSA_generate_key_ex', - '#define RSA_generate_key_fips GRPC_SHADOW_RSA_generate_key_fips', - '#define RSA_get0_crt_params GRPC_SHADOW_RSA_get0_crt_params', - '#define RSA_get0_factors GRPC_SHADOW_RSA_get0_factors', - '#define RSA_get0_key GRPC_SHADOW_RSA_get0_key', - '#define RSA_get_ex_data GRPC_SHADOW_RSA_get_ex_data', - '#define RSA_get_ex_new_index GRPC_SHADOW_RSA_get_ex_new_index', - '#define RSA_is_opaque GRPC_SHADOW_RSA_is_opaque', - '#define RSA_new GRPC_SHADOW_RSA_new', - '#define RSA_new_method GRPC_SHADOW_RSA_new_method', - '#define RSA_padding_add_PKCS1_OAEP_mgf1 GRPC_SHADOW_RSA_padding_add_PKCS1_OAEP_mgf1', - '#define RSA_padding_add_PKCS1_PSS_mgf1 GRPC_SHADOW_RSA_padding_add_PKCS1_PSS_mgf1', - '#define RSA_padding_add_PKCS1_type_1 GRPC_SHADOW_RSA_padding_add_PKCS1_type_1', - '#define RSA_padding_add_PKCS1_type_2 GRPC_SHADOW_RSA_padding_add_PKCS1_type_2', - '#define RSA_padding_add_none GRPC_SHADOW_RSA_padding_add_none', - '#define RSA_padding_check_PKCS1_OAEP_mgf1 GRPC_SHADOW_RSA_padding_check_PKCS1_OAEP_mgf1', - '#define RSA_padding_check_PKCS1_type_1 GRPC_SHADOW_RSA_padding_check_PKCS1_type_1', - '#define RSA_padding_check_PKCS1_type_2 GRPC_SHADOW_RSA_padding_check_PKCS1_type_2', - '#define RSA_private_decrypt GRPC_SHADOW_RSA_private_decrypt', - '#define RSA_private_encrypt GRPC_SHADOW_RSA_private_encrypt', - '#define RSA_private_transform GRPC_SHADOW_RSA_private_transform', - '#define RSA_public_decrypt GRPC_SHADOW_RSA_public_decrypt', - '#define RSA_public_encrypt GRPC_SHADOW_RSA_public_encrypt', - '#define RSA_set0_crt_params GRPC_SHADOW_RSA_set0_crt_params', - '#define RSA_set0_factors GRPC_SHADOW_RSA_set0_factors', - '#define RSA_set0_key GRPC_SHADOW_RSA_set0_key', - '#define RSA_set_ex_data GRPC_SHADOW_RSA_set_ex_data', - '#define RSA_sign GRPC_SHADOW_RSA_sign', - '#define RSA_sign_pss_mgf1 GRPC_SHADOW_RSA_sign_pss_mgf1', - '#define RSA_sign_raw GRPC_SHADOW_RSA_sign_raw', - '#define RSA_size GRPC_SHADOW_RSA_size', - '#define RSA_up_ref GRPC_SHADOW_RSA_up_ref', - '#define RSA_verify GRPC_SHADOW_RSA_verify', - '#define RSA_verify_PKCS1_PSS_mgf1 GRPC_SHADOW_RSA_verify_PKCS1_PSS_mgf1', - '#define RSA_verify_pss_mgf1 GRPC_SHADOW_RSA_verify_pss_mgf1', - '#define RSA_verify_raw GRPC_SHADOW_RSA_verify_raw', - '#define SHA1 GRPC_SHADOW_SHA1', - '#define SHA1_Final GRPC_SHADOW_SHA1_Final', - '#define SHA1_Init GRPC_SHADOW_SHA1_Init', - '#define SHA1_Transform GRPC_SHADOW_SHA1_Transform', - '#define SHA1_Update GRPC_SHADOW_SHA1_Update', - '#define SHA224 GRPC_SHADOW_SHA224', - '#define SHA224_Final GRPC_SHADOW_SHA224_Final', - '#define SHA224_Init GRPC_SHADOW_SHA224_Init', - '#define SHA224_Update GRPC_SHADOW_SHA224_Update', - '#define SHA256 GRPC_SHADOW_SHA256', - '#define SHA256_Final GRPC_SHADOW_SHA256_Final', - '#define SHA256_Init GRPC_SHADOW_SHA256_Init', - '#define SHA256_Transform GRPC_SHADOW_SHA256_Transform', - '#define SHA256_Update GRPC_SHADOW_SHA256_Update', - '#define SHA384 GRPC_SHADOW_SHA384', - '#define SHA384_Final GRPC_SHADOW_SHA384_Final', - '#define SHA384_Init GRPC_SHADOW_SHA384_Init', - '#define SHA384_Update GRPC_SHADOW_SHA384_Update', - '#define SHA512 GRPC_SHADOW_SHA512', - '#define SHA512_Final GRPC_SHADOW_SHA512_Final', - '#define SHA512_Init GRPC_SHADOW_SHA512_Init', - '#define SHA512_Transform GRPC_SHADOW_SHA512_Transform', - '#define SHA512_Update GRPC_SHADOW_SHA512_Update', - '#define aes_ctr_set_key GRPC_SHADOW_aes_ctr_set_key', - '#define bn_abs_sub_consttime GRPC_SHADOW_bn_abs_sub_consttime', - '#define bn_add_words GRPC_SHADOW_bn_add_words', - '#define bn_copy_words GRPC_SHADOW_bn_copy_words', - '#define bn_div_consttime GRPC_SHADOW_bn_div_consttime', - '#define bn_expand GRPC_SHADOW_bn_expand', - '#define bn_fits_in_words GRPC_SHADOW_bn_fits_in_words', - '#define bn_from_montgomery_small GRPC_SHADOW_bn_from_montgomery_small', - '#define bn_in_range_words GRPC_SHADOW_bn_in_range_words', - '#define bn_is_bit_set_words GRPC_SHADOW_bn_is_bit_set_words', - '#define bn_is_relatively_prime GRPC_SHADOW_bn_is_relatively_prime', - '#define bn_jacobi GRPC_SHADOW_bn_jacobi', - '#define bn_lcm_consttime GRPC_SHADOW_bn_lcm_consttime', - '#define bn_less_than_montgomery_R GRPC_SHADOW_bn_less_than_montgomery_R', - '#define bn_less_than_words GRPC_SHADOW_bn_less_than_words', - '#define bn_minimal_width GRPC_SHADOW_bn_minimal_width', - '#define bn_mod_add_consttime GRPC_SHADOW_bn_mod_add_consttime', - '#define bn_mod_exp_base_2_consttime GRPC_SHADOW_bn_mod_exp_base_2_consttime', - '#define bn_mod_exp_mont_small GRPC_SHADOW_bn_mod_exp_mont_small', - '#define bn_mod_inverse_consttime GRPC_SHADOW_bn_mod_inverse_consttime', - '#define bn_mod_inverse_prime GRPC_SHADOW_bn_mod_inverse_prime', - '#define bn_mod_inverse_prime_mont_small GRPC_SHADOW_bn_mod_inverse_prime_mont_small', - '#define bn_mod_inverse_secret_prime GRPC_SHADOW_bn_mod_inverse_secret_prime', - '#define bn_mod_lshift1_consttime GRPC_SHADOW_bn_mod_lshift1_consttime', - '#define bn_mod_lshift_consttime GRPC_SHADOW_bn_mod_lshift_consttime', - '#define bn_mod_mul_montgomery_small GRPC_SHADOW_bn_mod_mul_montgomery_small', - '#define bn_mod_sub_consttime GRPC_SHADOW_bn_mod_sub_consttime', - '#define bn_mod_u16_consttime GRPC_SHADOW_bn_mod_u16_consttime', - '#define bn_mont_n0 GRPC_SHADOW_bn_mont_n0', - '#define bn_mul_add_words GRPC_SHADOW_bn_mul_add_words', - '#define bn_mul_comba4 GRPC_SHADOW_bn_mul_comba4', - '#define bn_mul_comba8 GRPC_SHADOW_bn_mul_comba8', - '#define bn_mul_consttime GRPC_SHADOW_bn_mul_consttime', - '#define bn_mul_small GRPC_SHADOW_bn_mul_small', - '#define bn_mul_words GRPC_SHADOW_bn_mul_words', - '#define bn_odd_number_is_obviously_composite GRPC_SHADOW_bn_odd_number_is_obviously_composite', - '#define bn_one_to_montgomery GRPC_SHADOW_bn_one_to_montgomery', - '#define bn_one_to_montgomery_small GRPC_SHADOW_bn_one_to_montgomery_small', - '#define bn_rand_range_words GRPC_SHADOW_bn_rand_range_words', - '#define bn_rand_secret_range GRPC_SHADOW_bn_rand_secret_range', - '#define bn_resize_words GRPC_SHADOW_bn_resize_words', - '#define bn_rshift1_words GRPC_SHADOW_bn_rshift1_words', - '#define bn_rshift_secret_shift GRPC_SHADOW_bn_rshift_secret_shift', - '#define bn_select_words GRPC_SHADOW_bn_select_words', - '#define bn_set_minimal_width GRPC_SHADOW_bn_set_minimal_width', - '#define bn_set_words GRPC_SHADOW_bn_set_words', - '#define bn_sqr_comba4 GRPC_SHADOW_bn_sqr_comba4', - '#define bn_sqr_comba8 GRPC_SHADOW_bn_sqr_comba8', - '#define bn_sqr_consttime GRPC_SHADOW_bn_sqr_consttime', - '#define bn_sqr_small GRPC_SHADOW_bn_sqr_small', - '#define bn_sqr_words GRPC_SHADOW_bn_sqr_words', - '#define bn_sub_words GRPC_SHADOW_bn_sub_words', - '#define bn_to_montgomery_small GRPC_SHADOW_bn_to_montgomery_small', - '#define bn_uadd_consttime GRPC_SHADOW_bn_uadd_consttime', - '#define bn_usub_consttime GRPC_SHADOW_bn_usub_consttime', - '#define bn_wexpand GRPC_SHADOW_bn_wexpand', - '#define crypto_gcm_clmul_enabled GRPC_SHADOW_crypto_gcm_clmul_enabled', - '#define ec_GFp_mont_field_decode GRPC_SHADOW_ec_GFp_mont_field_decode', - '#define ec_GFp_mont_field_encode GRPC_SHADOW_ec_GFp_mont_field_encode', - '#define ec_GFp_mont_field_mul GRPC_SHADOW_ec_GFp_mont_field_mul', - '#define ec_GFp_mont_field_sqr GRPC_SHADOW_ec_GFp_mont_field_sqr', - '#define ec_GFp_mont_group_finish GRPC_SHADOW_ec_GFp_mont_group_finish', - '#define ec_GFp_mont_group_init GRPC_SHADOW_ec_GFp_mont_group_init', - '#define ec_GFp_mont_group_set_curve GRPC_SHADOW_ec_GFp_mont_group_set_curve', - '#define ec_GFp_nistp_recode_scalar_bits GRPC_SHADOW_ec_GFp_nistp_recode_scalar_bits', - '#define ec_GFp_simple_add GRPC_SHADOW_ec_GFp_simple_add', - '#define ec_GFp_simple_cmp GRPC_SHADOW_ec_GFp_simple_cmp', - '#define ec_GFp_simple_dbl GRPC_SHADOW_ec_GFp_simple_dbl', - '#define ec_GFp_simple_field_mul GRPC_SHADOW_ec_GFp_simple_field_mul', - '#define ec_GFp_simple_field_sqr GRPC_SHADOW_ec_GFp_simple_field_sqr', - '#define ec_GFp_simple_group_finish GRPC_SHADOW_ec_GFp_simple_group_finish', - '#define ec_GFp_simple_group_get_curve GRPC_SHADOW_ec_GFp_simple_group_get_curve', - '#define ec_GFp_simple_group_get_degree GRPC_SHADOW_ec_GFp_simple_group_get_degree', - '#define ec_GFp_simple_group_init GRPC_SHADOW_ec_GFp_simple_group_init', - '#define ec_GFp_simple_group_set_curve GRPC_SHADOW_ec_GFp_simple_group_set_curve', - '#define ec_GFp_simple_invert GRPC_SHADOW_ec_GFp_simple_invert', - '#define ec_GFp_simple_is_at_infinity GRPC_SHADOW_ec_GFp_simple_is_at_infinity', - '#define ec_GFp_simple_is_on_curve GRPC_SHADOW_ec_GFp_simple_is_on_curve', - '#define ec_GFp_simple_make_affine GRPC_SHADOW_ec_GFp_simple_make_affine', - '#define ec_GFp_simple_point_copy GRPC_SHADOW_ec_GFp_simple_point_copy', - '#define ec_GFp_simple_point_finish GRPC_SHADOW_ec_GFp_simple_point_finish', - '#define ec_GFp_simple_point_init GRPC_SHADOW_ec_GFp_simple_point_init', - '#define ec_GFp_simple_point_set_affine_coordinates GRPC_SHADOW_ec_GFp_simple_point_set_affine_coordinates', - '#define ec_GFp_simple_point_set_to_infinity GRPC_SHADOW_ec_GFp_simple_point_set_to_infinity', - '#define ec_GFp_simple_points_make_affine GRPC_SHADOW_ec_GFp_simple_points_make_affine', - '#define ec_bignum_to_scalar GRPC_SHADOW_ec_bignum_to_scalar', - '#define ec_bignum_to_scalar_unchecked GRPC_SHADOW_ec_bignum_to_scalar_unchecked', - '#define ec_compute_wNAF GRPC_SHADOW_ec_compute_wNAF', - '#define ec_group_new GRPC_SHADOW_ec_group_new', - '#define ec_point_mul_scalar GRPC_SHADOW_ec_point_mul_scalar', - '#define ec_point_mul_scalar_public GRPC_SHADOW_ec_point_mul_scalar_public', - '#define ec_random_nonzero_scalar GRPC_SHADOW_ec_random_nonzero_scalar', - '#define ec_wNAF_mul GRPC_SHADOW_ec_wNAF_mul', - '#define kBoringSSLRSASqrtTwo GRPC_SHADOW_kBoringSSLRSASqrtTwo', - '#define kBoringSSLRSASqrtTwoLen GRPC_SHADOW_kBoringSSLRSASqrtTwoLen', - '#define md4_block_data_order GRPC_SHADOW_md4_block_data_order', - '#define rsa_default_decrypt GRPC_SHADOW_rsa_default_decrypt', - '#define rsa_default_private_transform GRPC_SHADOW_rsa_default_private_transform', - '#define rsa_default_sign_raw GRPC_SHADOW_rsa_default_sign_raw', - '#define rsa_default_size GRPC_SHADOW_rsa_default_size', - '#define FIPS_mode GRPC_SHADOW_FIPS_mode', - '#define aesni_gcm_decrypt GRPC_SHADOW_aesni_gcm_decrypt', - '#define aesni_gcm_encrypt GRPC_SHADOW_aesni_gcm_encrypt', - '#define aesni_cbc_encrypt GRPC_SHADOW_aesni_cbc_encrypt', - '#define aesni_ccm64_decrypt_blocks GRPC_SHADOW_aesni_ccm64_decrypt_blocks', - '#define aesni_ccm64_encrypt_blocks GRPC_SHADOW_aesni_ccm64_encrypt_blocks', - '#define aesni_ctr32_encrypt_blocks GRPC_SHADOW_aesni_ctr32_encrypt_blocks', - '#define aesni_decrypt GRPC_SHADOW_aesni_decrypt', - '#define aesni_ecb_encrypt GRPC_SHADOW_aesni_ecb_encrypt', - '#define aesni_encrypt GRPC_SHADOW_aesni_encrypt', - '#define aesni_ocb_decrypt GRPC_SHADOW_aesni_ocb_decrypt', - '#define aesni_ocb_encrypt GRPC_SHADOW_aesni_ocb_encrypt', - '#define aesni_set_decrypt_key GRPC_SHADOW_aesni_set_decrypt_key', - '#define aesni_set_encrypt_key GRPC_SHADOW_aesni_set_encrypt_key', - '#define aesni_xts_decrypt GRPC_SHADOW_aesni_xts_decrypt', - '#define aesni_xts_encrypt GRPC_SHADOW_aesni_xts_encrypt', - '#define asm_AES_cbc_encrypt GRPC_SHADOW_asm_AES_cbc_encrypt', - '#define asm_AES_decrypt GRPC_SHADOW_asm_AES_decrypt', - '#define asm_AES_encrypt GRPC_SHADOW_asm_AES_encrypt', - '#define asm_AES_set_decrypt_key GRPC_SHADOW_asm_AES_set_decrypt_key', - '#define asm_AES_set_encrypt_key GRPC_SHADOW_asm_AES_set_encrypt_key', - '#define bsaes_cbc_encrypt GRPC_SHADOW_bsaes_cbc_encrypt', - '#define bsaes_ctr32_encrypt_blocks GRPC_SHADOW_bsaes_ctr32_encrypt_blocks', - '#define bsaes_xts_decrypt GRPC_SHADOW_bsaes_xts_decrypt', - '#define bsaes_xts_encrypt GRPC_SHADOW_bsaes_xts_encrypt', - '#define gcm_ghash_4bit GRPC_SHADOW_gcm_ghash_4bit', - '#define gcm_ghash_avx GRPC_SHADOW_gcm_ghash_avx', - '#define gcm_ghash_clmul GRPC_SHADOW_gcm_ghash_clmul', - '#define gcm_gmult_4bit GRPC_SHADOW_gcm_gmult_4bit', - '#define gcm_gmult_avx GRPC_SHADOW_gcm_gmult_avx', - '#define gcm_gmult_clmul GRPC_SHADOW_gcm_gmult_clmul', - '#define gcm_init_avx GRPC_SHADOW_gcm_init_avx', - '#define gcm_init_clmul GRPC_SHADOW_gcm_init_clmul', - '#define md5_block_asm_data_order GRPC_SHADOW_md5_block_asm_data_order', - '#define ecp_nistz256_avx2_select_w7 GRPC_SHADOW_ecp_nistz256_avx2_select_w7', - '#define ecp_nistz256_mul_mont GRPC_SHADOW_ecp_nistz256_mul_mont', - '#define ecp_nistz256_neg GRPC_SHADOW_ecp_nistz256_neg', - '#define ecp_nistz256_point_add GRPC_SHADOW_ecp_nistz256_point_add', - '#define ecp_nistz256_point_add_affine GRPC_SHADOW_ecp_nistz256_point_add_affine', - '#define ecp_nistz256_point_double GRPC_SHADOW_ecp_nistz256_point_double', - '#define ecp_nistz256_select_w5 GRPC_SHADOW_ecp_nistz256_select_w5', - '#define ecp_nistz256_select_w7 GRPC_SHADOW_ecp_nistz256_select_w7', - '#define ecp_nistz256_sqr_mont GRPC_SHADOW_ecp_nistz256_sqr_mont', - '#define CRYPTO_rdrand GRPC_SHADOW_CRYPTO_rdrand', - '#define CRYPTO_rdrand_multiple8_buf GRPC_SHADOW_CRYPTO_rdrand_multiple8_buf', - '#define rsaz_1024_gather5_avx2 GRPC_SHADOW_rsaz_1024_gather5_avx2', - '#define rsaz_1024_mul_avx2 GRPC_SHADOW_rsaz_1024_mul_avx2', - '#define rsaz_1024_norm2red_avx2 GRPC_SHADOW_rsaz_1024_norm2red_avx2', - '#define rsaz_1024_red2norm_avx2 GRPC_SHADOW_rsaz_1024_red2norm_avx2', - '#define rsaz_1024_scatter5_avx2 GRPC_SHADOW_rsaz_1024_scatter5_avx2', - '#define rsaz_1024_sqr_avx2 GRPC_SHADOW_rsaz_1024_sqr_avx2', - '#define rsaz_avx2_eligible GRPC_SHADOW_rsaz_avx2_eligible', - '#define sha1_block_data_order GRPC_SHADOW_sha1_block_data_order', - '#define sha256_block_data_order GRPC_SHADOW_sha256_block_data_order', - '#define sha512_block_data_order GRPC_SHADOW_sha512_block_data_order', - '#define vpaes_cbc_encrypt GRPC_SHADOW_vpaes_cbc_encrypt', - '#define vpaes_decrypt GRPC_SHADOW_vpaes_decrypt', - '#define vpaes_encrypt GRPC_SHADOW_vpaes_encrypt', - '#define vpaes_set_decrypt_key GRPC_SHADOW_vpaes_set_decrypt_key', - '#define vpaes_set_encrypt_key GRPC_SHADOW_vpaes_set_encrypt_key', - '#define bn_from_montgomery GRPC_SHADOW_bn_from_montgomery', - '#define bn_gather5 GRPC_SHADOW_bn_gather5', - '#define bn_mul_mont_gather5 GRPC_SHADOW_bn_mul_mont_gather5', - '#define bn_power5 GRPC_SHADOW_bn_power5', - '#define bn_scatter5 GRPC_SHADOW_bn_scatter5', - '#define bn_sqr8x_internal GRPC_SHADOW_bn_sqr8x_internal', - '#define bn_mul_mont GRPC_SHADOW_bn_mul_mont', - '#define EVP_get_digestbyname GRPC_SHADOW_EVP_get_digestbyname', - '#define EVP_get_digestbynid GRPC_SHADOW_EVP_get_digestbynid', - '#define EVP_get_digestbyobj GRPC_SHADOW_EVP_get_digestbyobj', - '#define EVP_marshal_digest_algorithm GRPC_SHADOW_EVP_marshal_digest_algorithm', - '#define EVP_parse_digest_algorithm GRPC_SHADOW_EVP_parse_digest_algorithm', - '#define EVP_get_cipherbyname GRPC_SHADOW_EVP_get_cipherbyname', - '#define EVP_get_cipherbynid GRPC_SHADOW_EVP_get_cipherbynid', - '#define EVP_BytesToKey GRPC_SHADOW_EVP_BytesToKey', - '#define EVP_enc_null GRPC_SHADOW_EVP_enc_null', - '#define EVP_rc2_40_cbc GRPC_SHADOW_EVP_rc2_40_cbc', - '#define EVP_rc2_cbc GRPC_SHADOW_EVP_rc2_cbc', - '#define EVP_rc4 GRPC_SHADOW_EVP_rc4', - '#define EVP_aead_aes_128_gcm_siv GRPC_SHADOW_EVP_aead_aes_128_gcm_siv', - '#define EVP_aead_aes_256_gcm_siv GRPC_SHADOW_EVP_aead_aes_256_gcm_siv', - '#define EVP_aead_aes_128_ctr_hmac_sha256 GRPC_SHADOW_EVP_aead_aes_128_ctr_hmac_sha256', - '#define EVP_aead_aes_256_ctr_hmac_sha256 GRPC_SHADOW_EVP_aead_aes_256_ctr_hmac_sha256', - '#define EVP_aead_aes_128_ccm_bluetooth GRPC_SHADOW_EVP_aead_aes_128_ccm_bluetooth', - '#define EVP_aead_aes_128_ccm_bluetooth_8 GRPC_SHADOW_EVP_aead_aes_128_ccm_bluetooth_8', - '#define EVP_aead_chacha20_poly1305 GRPC_SHADOW_EVP_aead_chacha20_poly1305', - '#define EVP_tls_cbc_copy_mac GRPC_SHADOW_EVP_tls_cbc_copy_mac', - '#define EVP_tls_cbc_digest_record GRPC_SHADOW_EVP_tls_cbc_digest_record', - '#define EVP_tls_cbc_record_digest_supported GRPC_SHADOW_EVP_tls_cbc_record_digest_supported', - '#define EVP_tls_cbc_remove_padding GRPC_SHADOW_EVP_tls_cbc_remove_padding', - '#define EVP_aead_aes_128_cbc_sha1_tls GRPC_SHADOW_EVP_aead_aes_128_cbc_sha1_tls', - '#define EVP_aead_aes_128_cbc_sha1_tls_implicit_iv GRPC_SHADOW_EVP_aead_aes_128_cbc_sha1_tls_implicit_iv', - '#define EVP_aead_aes_128_cbc_sha256_tls GRPC_SHADOW_EVP_aead_aes_128_cbc_sha256_tls', - '#define EVP_aead_aes_256_cbc_sha1_tls GRPC_SHADOW_EVP_aead_aes_256_cbc_sha1_tls', - '#define EVP_aead_aes_256_cbc_sha1_tls_implicit_iv GRPC_SHADOW_EVP_aead_aes_256_cbc_sha1_tls_implicit_iv', - '#define EVP_aead_aes_256_cbc_sha256_tls GRPC_SHADOW_EVP_aead_aes_256_cbc_sha256_tls', - '#define EVP_aead_aes_256_cbc_sha384_tls GRPC_SHADOW_EVP_aead_aes_256_cbc_sha384_tls', - '#define EVP_aead_des_ede3_cbc_sha1_tls GRPC_SHADOW_EVP_aead_des_ede3_cbc_sha1_tls', - '#define EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv GRPC_SHADOW_EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv', - '#define EVP_aead_null_sha1_tls GRPC_SHADOW_EVP_aead_null_sha1_tls', - '#define EVP_aead_aes_128_cbc_sha1_ssl3 GRPC_SHADOW_EVP_aead_aes_128_cbc_sha1_ssl3', - '#define EVP_aead_aes_256_cbc_sha1_ssl3 GRPC_SHADOW_EVP_aead_aes_256_cbc_sha1_ssl3', - '#define EVP_aead_des_ede3_cbc_sha1_ssl3 GRPC_SHADOW_EVP_aead_des_ede3_cbc_sha1_ssl3', - '#define EVP_aead_null_sha1_ssl3 GRPC_SHADOW_EVP_aead_null_sha1_ssl3', - '#define aes128gcmsiv_aes_ks GRPC_SHADOW_aes128gcmsiv_aes_ks', - '#define aes128gcmsiv_aes_ks_enc_x1 GRPC_SHADOW_aes128gcmsiv_aes_ks_enc_x1', - '#define aes128gcmsiv_dec GRPC_SHADOW_aes128gcmsiv_dec', - '#define aes128gcmsiv_ecb_enc_block GRPC_SHADOW_aes128gcmsiv_ecb_enc_block', - '#define aes128gcmsiv_enc_msg_x4 GRPC_SHADOW_aes128gcmsiv_enc_msg_x4', - '#define aes128gcmsiv_enc_msg_x8 GRPC_SHADOW_aes128gcmsiv_enc_msg_x8', - '#define aes128gcmsiv_kdf GRPC_SHADOW_aes128gcmsiv_kdf', - '#define aes256gcmsiv_aes_ks GRPC_SHADOW_aes256gcmsiv_aes_ks', - '#define aes256gcmsiv_aes_ks_enc_x1 GRPC_SHADOW_aes256gcmsiv_aes_ks_enc_x1', - '#define aes256gcmsiv_dec GRPC_SHADOW_aes256gcmsiv_dec', - '#define aes256gcmsiv_ecb_enc_block GRPC_SHADOW_aes256gcmsiv_ecb_enc_block', - '#define aes256gcmsiv_enc_msg_x4 GRPC_SHADOW_aes256gcmsiv_enc_msg_x4', - '#define aes256gcmsiv_enc_msg_x8 GRPC_SHADOW_aes256gcmsiv_enc_msg_x8', - '#define aes256gcmsiv_kdf GRPC_SHADOW_aes256gcmsiv_kdf', - '#define aesgcmsiv_htable6_init GRPC_SHADOW_aesgcmsiv_htable6_init', - '#define aesgcmsiv_htable_init GRPC_SHADOW_aesgcmsiv_htable_init', - '#define aesgcmsiv_htable_polyval GRPC_SHADOW_aesgcmsiv_htable_polyval', - '#define aesgcmsiv_polyval_horner GRPC_SHADOW_aesgcmsiv_polyval_horner', - '#define chacha20_poly1305_open GRPC_SHADOW_chacha20_poly1305_open', - '#define chacha20_poly1305_seal GRPC_SHADOW_chacha20_poly1305_seal', - '#define RC4 GRPC_SHADOW_RC4', - '#define RC4_set_key GRPC_SHADOW_RC4_set_key', - '#define CONF_VALUE_new GRPC_SHADOW_CONF_VALUE_new', - '#define CONF_modules_free GRPC_SHADOW_CONF_modules_free', - '#define CONF_modules_load_file GRPC_SHADOW_CONF_modules_load_file', - '#define CONF_parse_list GRPC_SHADOW_CONF_parse_list', - '#define NCONF_free GRPC_SHADOW_NCONF_free', - '#define NCONF_get_section GRPC_SHADOW_NCONF_get_section', - '#define NCONF_get_string GRPC_SHADOW_NCONF_get_string', - '#define NCONF_load GRPC_SHADOW_NCONF_load', - '#define NCONF_load_bio GRPC_SHADOW_NCONF_load_bio', - '#define NCONF_new GRPC_SHADOW_NCONF_new', - '#define OPENSSL_config GRPC_SHADOW_OPENSSL_config', - '#define OPENSSL_no_config GRPC_SHADOW_OPENSSL_no_config', - '#define CRYPTO_chacha_20 GRPC_SHADOW_CRYPTO_chacha_20', - '#define ChaCha20_ctr32 GRPC_SHADOW_ChaCha20_ctr32', - '#define CRYPTO_poly1305_finish GRPC_SHADOW_CRYPTO_poly1305_finish', - '#define CRYPTO_poly1305_init GRPC_SHADOW_CRYPTO_poly1305_init', - '#define CRYPTO_poly1305_update GRPC_SHADOW_CRYPTO_poly1305_update', - '#define SPAKE2_CTX_free GRPC_SHADOW_SPAKE2_CTX_free', - '#define SPAKE2_CTX_new GRPC_SHADOW_SPAKE2_CTX_new', - '#define SPAKE2_generate_msg GRPC_SHADOW_SPAKE2_generate_msg', - '#define SPAKE2_process_msg GRPC_SHADOW_SPAKE2_process_msg', - '#define ED25519_keypair GRPC_SHADOW_ED25519_keypair', - '#define ED25519_keypair_from_seed GRPC_SHADOW_ED25519_keypair_from_seed', - '#define ED25519_sign GRPC_SHADOW_ED25519_sign', - '#define ED25519_verify GRPC_SHADOW_ED25519_verify', - '#define X25519 GRPC_SHADOW_X25519', - '#define X25519_keypair GRPC_SHADOW_X25519_keypair', - '#define X25519_public_from_private GRPC_SHADOW_X25519_public_from_private', - '#define x25519_ge_add GRPC_SHADOW_x25519_ge_add', - '#define x25519_ge_frombytes_vartime GRPC_SHADOW_x25519_ge_frombytes_vartime', - '#define x25519_ge_p1p1_to_p2 GRPC_SHADOW_x25519_ge_p1p1_to_p2', - '#define x25519_ge_p1p1_to_p3 GRPC_SHADOW_x25519_ge_p1p1_to_p3', - '#define x25519_ge_p3_to_cached GRPC_SHADOW_x25519_ge_p3_to_cached', - '#define x25519_ge_scalarmult GRPC_SHADOW_x25519_ge_scalarmult', - '#define x25519_ge_scalarmult_base GRPC_SHADOW_x25519_ge_scalarmult_base', - '#define x25519_ge_scalarmult_small_precomp GRPC_SHADOW_x25519_ge_scalarmult_small_precomp', - '#define x25519_ge_sub GRPC_SHADOW_x25519_ge_sub', - '#define x25519_ge_tobytes GRPC_SHADOW_x25519_ge_tobytes', - '#define x25519_sc_reduce GRPC_SHADOW_x25519_sc_reduce', - '#define BUF_MEM_append GRPC_SHADOW_BUF_MEM_append', - '#define BUF_MEM_free GRPC_SHADOW_BUF_MEM_free', - '#define BUF_MEM_grow GRPC_SHADOW_BUF_MEM_grow', - '#define BUF_MEM_grow_clean GRPC_SHADOW_BUF_MEM_grow_clean', - '#define BUF_MEM_new GRPC_SHADOW_BUF_MEM_new', - '#define BUF_MEM_reserve GRPC_SHADOW_BUF_MEM_reserve', - '#define BUF_memdup GRPC_SHADOW_BUF_memdup', - '#define BUF_strdup GRPC_SHADOW_BUF_strdup', - '#define BUF_strlcat GRPC_SHADOW_BUF_strlcat', - '#define BUF_strlcpy GRPC_SHADOW_BUF_strlcpy', - '#define BUF_strndup GRPC_SHADOW_BUF_strndup', - '#define BUF_strnlen GRPC_SHADOW_BUF_strnlen', - '#define BN_marshal_asn1 GRPC_SHADOW_BN_marshal_asn1', - '#define BN_parse_asn1_unsigned GRPC_SHADOW_BN_parse_asn1_unsigned', - '#define BN_asc2bn GRPC_SHADOW_BN_asc2bn', - '#define BN_bn2cbb_padded GRPC_SHADOW_BN_bn2cbb_padded', - '#define BN_bn2dec GRPC_SHADOW_BN_bn2dec', - '#define BN_bn2hex GRPC_SHADOW_BN_bn2hex', - '#define BN_bn2mpi GRPC_SHADOW_BN_bn2mpi', - '#define BN_dec2bn GRPC_SHADOW_BN_dec2bn', - '#define BN_hex2bn GRPC_SHADOW_BN_hex2bn', - '#define BN_mpi2bn GRPC_SHADOW_BN_mpi2bn', - '#define BN_print GRPC_SHADOW_BN_print', - '#define BN_print_fp GRPC_SHADOW_BN_print_fp', - '#define BIO_callback_ctrl GRPC_SHADOW_BIO_callback_ctrl', - '#define BIO_clear_flags GRPC_SHADOW_BIO_clear_flags', - '#define BIO_clear_retry_flags GRPC_SHADOW_BIO_clear_retry_flags', - '#define BIO_copy_next_retry GRPC_SHADOW_BIO_copy_next_retry', - '#define BIO_ctrl GRPC_SHADOW_BIO_ctrl', - '#define BIO_ctrl_pending GRPC_SHADOW_BIO_ctrl_pending', - '#define BIO_eof GRPC_SHADOW_BIO_eof', - '#define BIO_find_type GRPC_SHADOW_BIO_find_type', - '#define BIO_flush GRPC_SHADOW_BIO_flush', - '#define BIO_free GRPC_SHADOW_BIO_free', - '#define BIO_free_all GRPC_SHADOW_BIO_free_all', - '#define BIO_get_data GRPC_SHADOW_BIO_get_data', - '#define BIO_get_init GRPC_SHADOW_BIO_get_init', - '#define BIO_get_new_index GRPC_SHADOW_BIO_get_new_index', - '#define BIO_get_retry_flags GRPC_SHADOW_BIO_get_retry_flags', - '#define BIO_get_retry_reason GRPC_SHADOW_BIO_get_retry_reason', - '#define BIO_get_shutdown GRPC_SHADOW_BIO_get_shutdown', - '#define BIO_gets GRPC_SHADOW_BIO_gets', - '#define BIO_indent GRPC_SHADOW_BIO_indent', - '#define BIO_int_ctrl GRPC_SHADOW_BIO_int_ctrl', - '#define BIO_meth_free GRPC_SHADOW_BIO_meth_free', - '#define BIO_meth_new GRPC_SHADOW_BIO_meth_new', - '#define BIO_meth_set_create GRPC_SHADOW_BIO_meth_set_create', - '#define BIO_meth_set_ctrl GRPC_SHADOW_BIO_meth_set_ctrl', - '#define BIO_meth_set_destroy GRPC_SHADOW_BIO_meth_set_destroy', - '#define BIO_meth_set_gets GRPC_SHADOW_BIO_meth_set_gets', - '#define BIO_meth_set_puts GRPC_SHADOW_BIO_meth_set_puts', - '#define BIO_meth_set_read GRPC_SHADOW_BIO_meth_set_read', - '#define BIO_meth_set_write GRPC_SHADOW_BIO_meth_set_write', - '#define BIO_method_type GRPC_SHADOW_BIO_method_type', - '#define BIO_new GRPC_SHADOW_BIO_new', - '#define BIO_next GRPC_SHADOW_BIO_next', - '#define BIO_number_read GRPC_SHADOW_BIO_number_read', - '#define BIO_number_written GRPC_SHADOW_BIO_number_written', - '#define BIO_pending GRPC_SHADOW_BIO_pending', - '#define BIO_pop GRPC_SHADOW_BIO_pop', - '#define BIO_ptr_ctrl GRPC_SHADOW_BIO_ptr_ctrl', - '#define BIO_push GRPC_SHADOW_BIO_push', - '#define BIO_puts GRPC_SHADOW_BIO_puts', - '#define BIO_read GRPC_SHADOW_BIO_read', - '#define BIO_read_asn1 GRPC_SHADOW_BIO_read_asn1', - '#define BIO_reset GRPC_SHADOW_BIO_reset', - '#define BIO_set_close GRPC_SHADOW_BIO_set_close', - '#define BIO_set_data GRPC_SHADOW_BIO_set_data', - '#define BIO_set_flags GRPC_SHADOW_BIO_set_flags', - '#define BIO_set_init GRPC_SHADOW_BIO_set_init', - '#define BIO_set_retry_read GRPC_SHADOW_BIO_set_retry_read', - '#define BIO_set_retry_special GRPC_SHADOW_BIO_set_retry_special', - '#define BIO_set_retry_write GRPC_SHADOW_BIO_set_retry_write', - '#define BIO_set_shutdown GRPC_SHADOW_BIO_set_shutdown', - '#define BIO_set_write_buffer_size GRPC_SHADOW_BIO_set_write_buffer_size', - '#define BIO_should_io_special GRPC_SHADOW_BIO_should_io_special', - '#define BIO_should_read GRPC_SHADOW_BIO_should_read', - '#define BIO_should_retry GRPC_SHADOW_BIO_should_retry', - '#define BIO_should_write GRPC_SHADOW_BIO_should_write', - '#define BIO_test_flags GRPC_SHADOW_BIO_test_flags', - '#define BIO_up_ref GRPC_SHADOW_BIO_up_ref', - '#define BIO_vfree GRPC_SHADOW_BIO_vfree', - '#define BIO_wpending GRPC_SHADOW_BIO_wpending', - '#define BIO_write GRPC_SHADOW_BIO_write', - '#define ERR_print_errors GRPC_SHADOW_ERR_print_errors', - '#define BIO_get_mem_data GRPC_SHADOW_BIO_get_mem_data', - '#define BIO_get_mem_ptr GRPC_SHADOW_BIO_get_mem_ptr', - '#define BIO_mem_contents GRPC_SHADOW_BIO_mem_contents', - '#define BIO_new_mem_buf GRPC_SHADOW_BIO_new_mem_buf', - '#define BIO_s_mem GRPC_SHADOW_BIO_s_mem', - '#define BIO_set_mem_buf GRPC_SHADOW_BIO_set_mem_buf', - '#define BIO_set_mem_eof_return GRPC_SHADOW_BIO_set_mem_eof_return', - '#define BIO_do_connect GRPC_SHADOW_BIO_do_connect', - '#define BIO_new_connect GRPC_SHADOW_BIO_new_connect', - '#define BIO_s_connect GRPC_SHADOW_BIO_s_connect', - '#define BIO_set_conn_hostname GRPC_SHADOW_BIO_set_conn_hostname', - '#define BIO_set_conn_int_port GRPC_SHADOW_BIO_set_conn_int_port', - '#define BIO_set_conn_port GRPC_SHADOW_BIO_set_conn_port', - '#define BIO_set_nbio GRPC_SHADOW_BIO_set_nbio', - '#define BIO_get_fd GRPC_SHADOW_BIO_get_fd', - '#define BIO_new_fd GRPC_SHADOW_BIO_new_fd', - '#define BIO_s_fd GRPC_SHADOW_BIO_s_fd', - '#define BIO_set_fd GRPC_SHADOW_BIO_set_fd', - '#define bio_fd_should_retry GRPC_SHADOW_bio_fd_should_retry', - '#define BIO_append_filename GRPC_SHADOW_BIO_append_filename', - '#define BIO_get_fp GRPC_SHADOW_BIO_get_fp', - '#define BIO_new_file GRPC_SHADOW_BIO_new_file', - '#define BIO_new_fp GRPC_SHADOW_BIO_new_fp', - '#define BIO_read_filename GRPC_SHADOW_BIO_read_filename', - '#define BIO_rw_filename GRPC_SHADOW_BIO_rw_filename', - '#define BIO_s_file GRPC_SHADOW_BIO_s_file', - '#define BIO_set_fp GRPC_SHADOW_BIO_set_fp', - '#define BIO_write_filename GRPC_SHADOW_BIO_write_filename', - '#define BIO_hexdump GRPC_SHADOW_BIO_hexdump', - '#define BIO_ctrl_get_read_request GRPC_SHADOW_BIO_ctrl_get_read_request', - '#define BIO_ctrl_get_write_guarantee GRPC_SHADOW_BIO_ctrl_get_write_guarantee', - '#define BIO_new_bio_pair GRPC_SHADOW_BIO_new_bio_pair', - '#define BIO_shutdown_wr GRPC_SHADOW_BIO_shutdown_wr', - '#define BIO_printf GRPC_SHADOW_BIO_printf', - '#define BIO_new_socket GRPC_SHADOW_BIO_new_socket', - '#define BIO_s_socket GRPC_SHADOW_BIO_s_socket', - '#define bio_clear_socket_error GRPC_SHADOW_bio_clear_socket_error', - '#define bio_ip_and_port_to_socket_and_addr GRPC_SHADOW_bio_ip_and_port_to_socket_and_addr', - '#define bio_sock_error GRPC_SHADOW_bio_sock_error', - '#define bio_socket_nbio GRPC_SHADOW_bio_socket_nbio', - '#define RAND_enable_fork_unsafe_buffering GRPC_SHADOW_RAND_enable_fork_unsafe_buffering', - '#define rand_fork_unsafe_buffering_enabled GRPC_SHADOW_rand_fork_unsafe_buffering_enabled', - '#define RAND_SSLeay GRPC_SHADOW_RAND_SSLeay', - '#define RAND_add GRPC_SHADOW_RAND_add', - '#define RAND_cleanup GRPC_SHADOW_RAND_cleanup', - '#define RAND_egd GRPC_SHADOW_RAND_egd', - '#define RAND_file_name GRPC_SHADOW_RAND_file_name', - '#define RAND_get_rand_method GRPC_SHADOW_RAND_get_rand_method', - '#define RAND_load_file GRPC_SHADOW_RAND_load_file', - '#define RAND_poll GRPC_SHADOW_RAND_poll', - '#define RAND_seed GRPC_SHADOW_RAND_seed', - '#define RAND_set_rand_method GRPC_SHADOW_RAND_set_rand_method', - '#define RAND_status GRPC_SHADOW_RAND_status', - '#define OBJ_cbs2nid GRPC_SHADOW_OBJ_cbs2nid', - '#define OBJ_cmp GRPC_SHADOW_OBJ_cmp', - '#define OBJ_create GRPC_SHADOW_OBJ_create', - '#define OBJ_dup GRPC_SHADOW_OBJ_dup', - '#define OBJ_get0_data GRPC_SHADOW_OBJ_get0_data', - '#define OBJ_length GRPC_SHADOW_OBJ_length', - '#define OBJ_ln2nid GRPC_SHADOW_OBJ_ln2nid', - '#define OBJ_nid2cbb GRPC_SHADOW_OBJ_nid2cbb', - '#define OBJ_nid2ln GRPC_SHADOW_OBJ_nid2ln', - '#define OBJ_nid2obj GRPC_SHADOW_OBJ_nid2obj', - '#define OBJ_nid2sn GRPC_SHADOW_OBJ_nid2sn', - '#define OBJ_obj2nid GRPC_SHADOW_OBJ_obj2nid', - '#define OBJ_obj2txt GRPC_SHADOW_OBJ_obj2txt', - '#define OBJ_sn2nid GRPC_SHADOW_OBJ_sn2nid', - '#define OBJ_txt2nid GRPC_SHADOW_OBJ_txt2nid', - '#define OBJ_txt2obj GRPC_SHADOW_OBJ_txt2obj', - '#define OBJ_find_sigid_algs GRPC_SHADOW_OBJ_find_sigid_algs', - '#define OBJ_find_sigid_by_algs GRPC_SHADOW_OBJ_find_sigid_by_algs', - '#define ASN1_BIT_STRING_check GRPC_SHADOW_ASN1_BIT_STRING_check', - '#define ASN1_BIT_STRING_get_bit GRPC_SHADOW_ASN1_BIT_STRING_get_bit', - '#define ASN1_BIT_STRING_set GRPC_SHADOW_ASN1_BIT_STRING_set', - '#define ASN1_BIT_STRING_set_bit GRPC_SHADOW_ASN1_BIT_STRING_set_bit', - '#define c2i_ASN1_BIT_STRING GRPC_SHADOW_c2i_ASN1_BIT_STRING', - '#define i2c_ASN1_BIT_STRING GRPC_SHADOW_i2c_ASN1_BIT_STRING', - '#define d2i_ASN1_BOOLEAN GRPC_SHADOW_d2i_ASN1_BOOLEAN', - '#define i2d_ASN1_BOOLEAN GRPC_SHADOW_i2d_ASN1_BOOLEAN', - '#define ASN1_d2i_bio GRPC_SHADOW_ASN1_d2i_bio', - '#define ASN1_d2i_fp GRPC_SHADOW_ASN1_d2i_fp', - '#define ASN1_item_d2i_bio GRPC_SHADOW_ASN1_item_d2i_bio', - '#define ASN1_item_d2i_fp GRPC_SHADOW_ASN1_item_d2i_fp', - '#define ASN1_dup GRPC_SHADOW_ASN1_dup', - '#define ASN1_item_dup GRPC_SHADOW_ASN1_item_dup', - '#define ASN1_ENUMERATED_get GRPC_SHADOW_ASN1_ENUMERATED_get', - '#define ASN1_ENUMERATED_set GRPC_SHADOW_ASN1_ENUMERATED_set', - '#define ASN1_ENUMERATED_to_BN GRPC_SHADOW_ASN1_ENUMERATED_to_BN', - '#define BN_to_ASN1_ENUMERATED GRPC_SHADOW_BN_to_ASN1_ENUMERATED', - '#define ASN1_GENERALIZEDTIME_adj GRPC_SHADOW_ASN1_GENERALIZEDTIME_adj', - '#define ASN1_GENERALIZEDTIME_check GRPC_SHADOW_ASN1_GENERALIZEDTIME_check', - '#define ASN1_GENERALIZEDTIME_set GRPC_SHADOW_ASN1_GENERALIZEDTIME_set', - '#define ASN1_GENERALIZEDTIME_set_string GRPC_SHADOW_ASN1_GENERALIZEDTIME_set_string', - '#define asn1_generalizedtime_to_tm GRPC_SHADOW_asn1_generalizedtime_to_tm', - '#define ASN1_i2d_bio GRPC_SHADOW_ASN1_i2d_bio', - '#define ASN1_i2d_fp GRPC_SHADOW_ASN1_i2d_fp', - '#define ASN1_item_i2d_bio GRPC_SHADOW_ASN1_item_i2d_bio', - '#define ASN1_item_i2d_fp GRPC_SHADOW_ASN1_item_i2d_fp', - '#define ASN1_INTEGER_cmp GRPC_SHADOW_ASN1_INTEGER_cmp', - '#define ASN1_INTEGER_dup GRPC_SHADOW_ASN1_INTEGER_dup', - '#define ASN1_INTEGER_get GRPC_SHADOW_ASN1_INTEGER_get', - '#define ASN1_INTEGER_set GRPC_SHADOW_ASN1_INTEGER_set', - '#define ASN1_INTEGER_set_uint64 GRPC_SHADOW_ASN1_INTEGER_set_uint64', - '#define ASN1_INTEGER_to_BN GRPC_SHADOW_ASN1_INTEGER_to_BN', - '#define BN_to_ASN1_INTEGER GRPC_SHADOW_BN_to_ASN1_INTEGER', - '#define c2i_ASN1_INTEGER GRPC_SHADOW_c2i_ASN1_INTEGER', - '#define d2i_ASN1_UINTEGER GRPC_SHADOW_d2i_ASN1_UINTEGER', - '#define i2c_ASN1_INTEGER GRPC_SHADOW_i2c_ASN1_INTEGER', - '#define ASN1_mbstring_copy GRPC_SHADOW_ASN1_mbstring_copy', - '#define ASN1_mbstring_ncopy GRPC_SHADOW_ASN1_mbstring_ncopy', - '#define ASN1_OBJECT_create GRPC_SHADOW_ASN1_OBJECT_create', - '#define ASN1_OBJECT_free GRPC_SHADOW_ASN1_OBJECT_free', - '#define ASN1_OBJECT_new GRPC_SHADOW_ASN1_OBJECT_new', - '#define c2i_ASN1_OBJECT GRPC_SHADOW_c2i_ASN1_OBJECT', - '#define d2i_ASN1_OBJECT GRPC_SHADOW_d2i_ASN1_OBJECT', - '#define i2a_ASN1_OBJECT GRPC_SHADOW_i2a_ASN1_OBJECT', - '#define i2d_ASN1_OBJECT GRPC_SHADOW_i2d_ASN1_OBJECT', - '#define i2t_ASN1_OBJECT GRPC_SHADOW_i2t_ASN1_OBJECT', - '#define ASN1_OCTET_STRING_cmp GRPC_SHADOW_ASN1_OCTET_STRING_cmp', - '#define ASN1_OCTET_STRING_dup GRPC_SHADOW_ASN1_OCTET_STRING_dup', - '#define ASN1_OCTET_STRING_set GRPC_SHADOW_ASN1_OCTET_STRING_set', - '#define ASN1_PRINTABLE_type GRPC_SHADOW_ASN1_PRINTABLE_type', - '#define ASN1_STRING_TABLE_add GRPC_SHADOW_ASN1_STRING_TABLE_add', - '#define ASN1_STRING_TABLE_cleanup GRPC_SHADOW_ASN1_STRING_TABLE_cleanup', - '#define ASN1_STRING_TABLE_get GRPC_SHADOW_ASN1_STRING_TABLE_get', - '#define ASN1_STRING_get_default_mask GRPC_SHADOW_ASN1_STRING_get_default_mask', - '#define ASN1_STRING_set_by_NID GRPC_SHADOW_ASN1_STRING_set_by_NID', - '#define ASN1_STRING_set_default_mask GRPC_SHADOW_ASN1_STRING_set_default_mask', - '#define ASN1_STRING_set_default_mask_asc GRPC_SHADOW_ASN1_STRING_set_default_mask_asc', - '#define ASN1_TIME_adj GRPC_SHADOW_ASN1_TIME_adj', - '#define ASN1_TIME_check GRPC_SHADOW_ASN1_TIME_check', - '#define ASN1_TIME_diff GRPC_SHADOW_ASN1_TIME_diff', - '#define ASN1_TIME_free GRPC_SHADOW_ASN1_TIME_free', - '#define ASN1_TIME_it GRPC_SHADOW_ASN1_TIME_it', - '#define ASN1_TIME_new GRPC_SHADOW_ASN1_TIME_new', - '#define ASN1_TIME_set GRPC_SHADOW_ASN1_TIME_set', - '#define ASN1_TIME_set_string GRPC_SHADOW_ASN1_TIME_set_string', - '#define ASN1_TIME_to_generalizedtime GRPC_SHADOW_ASN1_TIME_to_generalizedtime', - '#define d2i_ASN1_TIME GRPC_SHADOW_d2i_ASN1_TIME', - '#define i2d_ASN1_TIME GRPC_SHADOW_i2d_ASN1_TIME', - '#define ASN1_TYPE_cmp GRPC_SHADOW_ASN1_TYPE_cmp', - '#define ASN1_TYPE_get GRPC_SHADOW_ASN1_TYPE_get', - '#define ASN1_TYPE_set GRPC_SHADOW_ASN1_TYPE_set', - '#define ASN1_TYPE_set1 GRPC_SHADOW_ASN1_TYPE_set1', - '#define ASN1_UTCTIME_adj GRPC_SHADOW_ASN1_UTCTIME_adj', - '#define ASN1_UTCTIME_check GRPC_SHADOW_ASN1_UTCTIME_check', - '#define ASN1_UTCTIME_cmp_time_t GRPC_SHADOW_ASN1_UTCTIME_cmp_time_t', - '#define ASN1_UTCTIME_set GRPC_SHADOW_ASN1_UTCTIME_set', - '#define ASN1_UTCTIME_set_string GRPC_SHADOW_ASN1_UTCTIME_set_string', - '#define asn1_utctime_to_tm GRPC_SHADOW_asn1_utctime_to_tm', - '#define UTF8_getc GRPC_SHADOW_UTF8_getc', - '#define UTF8_putc GRPC_SHADOW_UTF8_putc', - '#define ASN1_STRING_cmp GRPC_SHADOW_ASN1_STRING_cmp', - '#define ASN1_STRING_copy GRPC_SHADOW_ASN1_STRING_copy', - '#define ASN1_STRING_data GRPC_SHADOW_ASN1_STRING_data', - '#define ASN1_STRING_dup GRPC_SHADOW_ASN1_STRING_dup', - '#define ASN1_STRING_free GRPC_SHADOW_ASN1_STRING_free', - '#define ASN1_STRING_get0_data GRPC_SHADOW_ASN1_STRING_get0_data', - '#define ASN1_STRING_length GRPC_SHADOW_ASN1_STRING_length', - '#define ASN1_STRING_length_set GRPC_SHADOW_ASN1_STRING_length_set', - '#define ASN1_STRING_new GRPC_SHADOW_ASN1_STRING_new', - '#define ASN1_STRING_set GRPC_SHADOW_ASN1_STRING_set', - '#define ASN1_STRING_set0 GRPC_SHADOW_ASN1_STRING_set0', - '#define ASN1_STRING_type GRPC_SHADOW_ASN1_STRING_type', - '#define ASN1_STRING_type_new GRPC_SHADOW_ASN1_STRING_type_new', - '#define ASN1_get_object GRPC_SHADOW_ASN1_get_object', - '#define ASN1_object_size GRPC_SHADOW_ASN1_object_size', - '#define ASN1_put_eoc GRPC_SHADOW_ASN1_put_eoc', - '#define ASN1_put_object GRPC_SHADOW_ASN1_put_object', - '#define ASN1_tag2str GRPC_SHADOW_ASN1_tag2str', - '#define ASN1_item_pack GRPC_SHADOW_ASN1_item_pack', - '#define ASN1_item_unpack GRPC_SHADOW_ASN1_item_unpack', - '#define i2a_ASN1_ENUMERATED GRPC_SHADOW_i2a_ASN1_ENUMERATED', - '#define i2a_ASN1_INTEGER GRPC_SHADOW_i2a_ASN1_INTEGER', - '#define i2a_ASN1_STRING GRPC_SHADOW_i2a_ASN1_STRING', - '#define ASN1_item_d2i GRPC_SHADOW_ASN1_item_d2i', - '#define ASN1_item_ex_d2i GRPC_SHADOW_ASN1_item_ex_d2i', - '#define ASN1_tag2bit GRPC_SHADOW_ASN1_tag2bit', - '#define asn1_ex_c2i GRPC_SHADOW_asn1_ex_c2i', - '#define ASN1_item_ex_i2d GRPC_SHADOW_ASN1_item_ex_i2d', - '#define ASN1_item_i2d GRPC_SHADOW_ASN1_item_i2d', - '#define ASN1_item_ndef_i2d GRPC_SHADOW_ASN1_item_ndef_i2d', - '#define asn1_ex_i2c GRPC_SHADOW_asn1_ex_i2c', - '#define ASN1_item_ex_free GRPC_SHADOW_ASN1_item_ex_free', - '#define ASN1_item_free GRPC_SHADOW_ASN1_item_free', - '#define ASN1_primitive_free GRPC_SHADOW_ASN1_primitive_free', - '#define ASN1_template_free GRPC_SHADOW_ASN1_template_free', - '#define asn1_item_combine_free GRPC_SHADOW_asn1_item_combine_free', - '#define ASN1_item_ex_new GRPC_SHADOW_ASN1_item_ex_new', - '#define ASN1_item_new GRPC_SHADOW_ASN1_item_new', - '#define ASN1_primitive_new GRPC_SHADOW_ASN1_primitive_new', - '#define ASN1_template_new GRPC_SHADOW_ASN1_template_new', - '#define ASN1_ANY_it GRPC_SHADOW_ASN1_ANY_it', - '#define ASN1_BIT_STRING_free GRPC_SHADOW_ASN1_BIT_STRING_free', - '#define ASN1_BIT_STRING_it GRPC_SHADOW_ASN1_BIT_STRING_it', - '#define ASN1_BIT_STRING_new GRPC_SHADOW_ASN1_BIT_STRING_new', - '#define ASN1_BMPSTRING_free GRPC_SHADOW_ASN1_BMPSTRING_free', - '#define ASN1_BMPSTRING_it GRPC_SHADOW_ASN1_BMPSTRING_it', - '#define ASN1_BMPSTRING_new GRPC_SHADOW_ASN1_BMPSTRING_new', - '#define ASN1_BOOLEAN_it GRPC_SHADOW_ASN1_BOOLEAN_it', - '#define ASN1_ENUMERATED_free GRPC_SHADOW_ASN1_ENUMERATED_free', - '#define ASN1_ENUMERATED_it GRPC_SHADOW_ASN1_ENUMERATED_it', - '#define ASN1_ENUMERATED_new GRPC_SHADOW_ASN1_ENUMERATED_new', - '#define ASN1_FBOOLEAN_it GRPC_SHADOW_ASN1_FBOOLEAN_it', - '#define ASN1_GENERALIZEDTIME_free GRPC_SHADOW_ASN1_GENERALIZEDTIME_free', - '#define ASN1_GENERALIZEDTIME_it GRPC_SHADOW_ASN1_GENERALIZEDTIME_it', - '#define ASN1_GENERALIZEDTIME_new GRPC_SHADOW_ASN1_GENERALIZEDTIME_new', - '#define ASN1_GENERALSTRING_free GRPC_SHADOW_ASN1_GENERALSTRING_free', - '#define ASN1_GENERALSTRING_it GRPC_SHADOW_ASN1_GENERALSTRING_it', - '#define ASN1_GENERALSTRING_new GRPC_SHADOW_ASN1_GENERALSTRING_new', - '#define ASN1_IA5STRING_free GRPC_SHADOW_ASN1_IA5STRING_free', - '#define ASN1_IA5STRING_it GRPC_SHADOW_ASN1_IA5STRING_it', - '#define ASN1_IA5STRING_new GRPC_SHADOW_ASN1_IA5STRING_new', - '#define ASN1_INTEGER_free GRPC_SHADOW_ASN1_INTEGER_free', - '#define ASN1_INTEGER_it GRPC_SHADOW_ASN1_INTEGER_it', - '#define ASN1_INTEGER_new GRPC_SHADOW_ASN1_INTEGER_new', - '#define ASN1_NULL_free GRPC_SHADOW_ASN1_NULL_free', - '#define ASN1_NULL_it GRPC_SHADOW_ASN1_NULL_it', - '#define ASN1_NULL_new GRPC_SHADOW_ASN1_NULL_new', - '#define ASN1_OBJECT_it GRPC_SHADOW_ASN1_OBJECT_it', - '#define ASN1_OCTET_STRING_NDEF_it GRPC_SHADOW_ASN1_OCTET_STRING_NDEF_it', - '#define ASN1_OCTET_STRING_free GRPC_SHADOW_ASN1_OCTET_STRING_free', - '#define ASN1_OCTET_STRING_it GRPC_SHADOW_ASN1_OCTET_STRING_it', - '#define ASN1_OCTET_STRING_new GRPC_SHADOW_ASN1_OCTET_STRING_new', - '#define ASN1_PRINTABLESTRING_free GRPC_SHADOW_ASN1_PRINTABLESTRING_free', - '#define ASN1_PRINTABLESTRING_it GRPC_SHADOW_ASN1_PRINTABLESTRING_it', - '#define ASN1_PRINTABLESTRING_new GRPC_SHADOW_ASN1_PRINTABLESTRING_new', - '#define ASN1_PRINTABLE_free GRPC_SHADOW_ASN1_PRINTABLE_free', - '#define ASN1_PRINTABLE_it GRPC_SHADOW_ASN1_PRINTABLE_it', - '#define ASN1_PRINTABLE_new GRPC_SHADOW_ASN1_PRINTABLE_new', - '#define ASN1_SEQUENCE_ANY_it GRPC_SHADOW_ASN1_SEQUENCE_ANY_it', - '#define ASN1_SEQUENCE_it GRPC_SHADOW_ASN1_SEQUENCE_it', - '#define ASN1_SET_ANY_it GRPC_SHADOW_ASN1_SET_ANY_it', - '#define ASN1_T61STRING_free GRPC_SHADOW_ASN1_T61STRING_free', - '#define ASN1_T61STRING_it GRPC_SHADOW_ASN1_T61STRING_it', - '#define ASN1_T61STRING_new GRPC_SHADOW_ASN1_T61STRING_new', - '#define ASN1_TBOOLEAN_it GRPC_SHADOW_ASN1_TBOOLEAN_it', - '#define ASN1_TYPE_free GRPC_SHADOW_ASN1_TYPE_free', - '#define ASN1_TYPE_new GRPC_SHADOW_ASN1_TYPE_new', - '#define ASN1_UNIVERSALSTRING_free GRPC_SHADOW_ASN1_UNIVERSALSTRING_free', - '#define ASN1_UNIVERSALSTRING_it GRPC_SHADOW_ASN1_UNIVERSALSTRING_it', - '#define ASN1_UNIVERSALSTRING_new GRPC_SHADOW_ASN1_UNIVERSALSTRING_new', - '#define ASN1_UTCTIME_free GRPC_SHADOW_ASN1_UTCTIME_free', - '#define ASN1_UTCTIME_it GRPC_SHADOW_ASN1_UTCTIME_it', - '#define ASN1_UTCTIME_new GRPC_SHADOW_ASN1_UTCTIME_new', - '#define ASN1_UTF8STRING_free GRPC_SHADOW_ASN1_UTF8STRING_free', - '#define ASN1_UTF8STRING_it GRPC_SHADOW_ASN1_UTF8STRING_it', - '#define ASN1_UTF8STRING_new GRPC_SHADOW_ASN1_UTF8STRING_new', - '#define ASN1_VISIBLESTRING_free GRPC_SHADOW_ASN1_VISIBLESTRING_free', - '#define ASN1_VISIBLESTRING_it GRPC_SHADOW_ASN1_VISIBLESTRING_it', - '#define ASN1_VISIBLESTRING_new GRPC_SHADOW_ASN1_VISIBLESTRING_new', - '#define DIRECTORYSTRING_free GRPC_SHADOW_DIRECTORYSTRING_free', - '#define DIRECTORYSTRING_it GRPC_SHADOW_DIRECTORYSTRING_it', - '#define DIRECTORYSTRING_new GRPC_SHADOW_DIRECTORYSTRING_new', - '#define DISPLAYTEXT_free GRPC_SHADOW_DISPLAYTEXT_free', - '#define DISPLAYTEXT_it GRPC_SHADOW_DISPLAYTEXT_it', - '#define DISPLAYTEXT_new GRPC_SHADOW_DISPLAYTEXT_new', - '#define d2i_ASN1_BIT_STRING GRPC_SHADOW_d2i_ASN1_BIT_STRING', - '#define d2i_ASN1_BMPSTRING GRPC_SHADOW_d2i_ASN1_BMPSTRING', - '#define d2i_ASN1_ENUMERATED GRPC_SHADOW_d2i_ASN1_ENUMERATED', - '#define d2i_ASN1_GENERALIZEDTIME GRPC_SHADOW_d2i_ASN1_GENERALIZEDTIME', - '#define d2i_ASN1_GENERALSTRING GRPC_SHADOW_d2i_ASN1_GENERALSTRING', - '#define d2i_ASN1_IA5STRING GRPC_SHADOW_d2i_ASN1_IA5STRING', - '#define d2i_ASN1_INTEGER GRPC_SHADOW_d2i_ASN1_INTEGER', - '#define d2i_ASN1_NULL GRPC_SHADOW_d2i_ASN1_NULL', - '#define d2i_ASN1_OCTET_STRING GRPC_SHADOW_d2i_ASN1_OCTET_STRING', - '#define d2i_ASN1_PRINTABLE GRPC_SHADOW_d2i_ASN1_PRINTABLE', - '#define d2i_ASN1_PRINTABLESTRING GRPC_SHADOW_d2i_ASN1_PRINTABLESTRING', - '#define d2i_ASN1_SEQUENCE_ANY GRPC_SHADOW_d2i_ASN1_SEQUENCE_ANY', - '#define d2i_ASN1_SET_ANY GRPC_SHADOW_d2i_ASN1_SET_ANY', - '#define d2i_ASN1_T61STRING GRPC_SHADOW_d2i_ASN1_T61STRING', - '#define d2i_ASN1_TYPE GRPC_SHADOW_d2i_ASN1_TYPE', - '#define d2i_ASN1_UNIVERSALSTRING GRPC_SHADOW_d2i_ASN1_UNIVERSALSTRING', - '#define d2i_ASN1_UTCTIME GRPC_SHADOW_d2i_ASN1_UTCTIME', - '#define d2i_ASN1_UTF8STRING GRPC_SHADOW_d2i_ASN1_UTF8STRING', - '#define d2i_ASN1_VISIBLESTRING GRPC_SHADOW_d2i_ASN1_VISIBLESTRING', - '#define d2i_DIRECTORYSTRING GRPC_SHADOW_d2i_DIRECTORYSTRING', - '#define d2i_DISPLAYTEXT GRPC_SHADOW_d2i_DISPLAYTEXT', - '#define i2d_ASN1_BIT_STRING GRPC_SHADOW_i2d_ASN1_BIT_STRING', - '#define i2d_ASN1_BMPSTRING GRPC_SHADOW_i2d_ASN1_BMPSTRING', - '#define i2d_ASN1_ENUMERATED GRPC_SHADOW_i2d_ASN1_ENUMERATED', - '#define i2d_ASN1_GENERALIZEDTIME GRPC_SHADOW_i2d_ASN1_GENERALIZEDTIME', - '#define i2d_ASN1_GENERALSTRING GRPC_SHADOW_i2d_ASN1_GENERALSTRING', - '#define i2d_ASN1_IA5STRING GRPC_SHADOW_i2d_ASN1_IA5STRING', - '#define i2d_ASN1_INTEGER GRPC_SHADOW_i2d_ASN1_INTEGER', - '#define i2d_ASN1_NULL GRPC_SHADOW_i2d_ASN1_NULL', - '#define i2d_ASN1_OCTET_STRING GRPC_SHADOW_i2d_ASN1_OCTET_STRING', - '#define i2d_ASN1_PRINTABLE GRPC_SHADOW_i2d_ASN1_PRINTABLE', - '#define i2d_ASN1_PRINTABLESTRING GRPC_SHADOW_i2d_ASN1_PRINTABLESTRING', - '#define i2d_ASN1_SEQUENCE_ANY GRPC_SHADOW_i2d_ASN1_SEQUENCE_ANY', - '#define i2d_ASN1_SET_ANY GRPC_SHADOW_i2d_ASN1_SET_ANY', - '#define i2d_ASN1_T61STRING GRPC_SHADOW_i2d_ASN1_T61STRING', - '#define i2d_ASN1_TYPE GRPC_SHADOW_i2d_ASN1_TYPE', - '#define i2d_ASN1_UNIVERSALSTRING GRPC_SHADOW_i2d_ASN1_UNIVERSALSTRING', - '#define i2d_ASN1_UTCTIME GRPC_SHADOW_i2d_ASN1_UTCTIME', - '#define i2d_ASN1_UTF8STRING GRPC_SHADOW_i2d_ASN1_UTF8STRING', - '#define i2d_ASN1_VISIBLESTRING GRPC_SHADOW_i2d_ASN1_VISIBLESTRING', - '#define i2d_DIRECTORYSTRING GRPC_SHADOW_i2d_DIRECTORYSTRING', - '#define i2d_DISPLAYTEXT GRPC_SHADOW_i2d_DISPLAYTEXT', - '#define asn1_do_adb GRPC_SHADOW_asn1_do_adb', - '#define asn1_enc_free GRPC_SHADOW_asn1_enc_free', - '#define asn1_enc_init GRPC_SHADOW_asn1_enc_init', - '#define asn1_enc_restore GRPC_SHADOW_asn1_enc_restore', - '#define asn1_enc_save GRPC_SHADOW_asn1_enc_save', - '#define asn1_get_choice_selector GRPC_SHADOW_asn1_get_choice_selector', - '#define asn1_get_field_ptr GRPC_SHADOW_asn1_get_field_ptr', - '#define asn1_refcount_dec_and_test_zero GRPC_SHADOW_asn1_refcount_dec_and_test_zero', - '#define asn1_refcount_set_one GRPC_SHADOW_asn1_refcount_set_one', - '#define asn1_set_choice_selector GRPC_SHADOW_asn1_set_choice_selector', - '#define OPENSSL_gmtime GRPC_SHADOW_OPENSSL_gmtime', - '#define OPENSSL_gmtime_adj GRPC_SHADOW_OPENSSL_gmtime_adj', - '#define OPENSSL_gmtime_diff GRPC_SHADOW_OPENSSL_gmtime_diff', - '#define ENGINE_free GRPC_SHADOW_ENGINE_free', - '#define ENGINE_get_ECDSA_method GRPC_SHADOW_ENGINE_get_ECDSA_method', - '#define ENGINE_get_RSA_method GRPC_SHADOW_ENGINE_get_RSA_method', - '#define ENGINE_new GRPC_SHADOW_ENGINE_new', - '#define ENGINE_set_ECDSA_method GRPC_SHADOW_ENGINE_set_ECDSA_method', - '#define ENGINE_set_RSA_method GRPC_SHADOW_ENGINE_set_RSA_method', - '#define METHOD_ref GRPC_SHADOW_METHOD_ref', - '#define METHOD_unref GRPC_SHADOW_METHOD_unref', - '#define DH_compute_key GRPC_SHADOW_DH_compute_key', - '#define DH_free GRPC_SHADOW_DH_free', - '#define DH_generate_key GRPC_SHADOW_DH_generate_key', - '#define DH_generate_parameters_ex GRPC_SHADOW_DH_generate_parameters_ex', - '#define DH_get0_key GRPC_SHADOW_DH_get0_key', - '#define DH_get0_pqg GRPC_SHADOW_DH_get0_pqg', - '#define DH_get_ex_data GRPC_SHADOW_DH_get_ex_data', - '#define DH_get_ex_new_index GRPC_SHADOW_DH_get_ex_new_index', - '#define DH_new GRPC_SHADOW_DH_new', - '#define DH_num_bits GRPC_SHADOW_DH_num_bits', - '#define DH_set0_key GRPC_SHADOW_DH_set0_key', - '#define DH_set0_pqg GRPC_SHADOW_DH_set0_pqg', - '#define DH_set_ex_data GRPC_SHADOW_DH_set_ex_data', - '#define DH_size GRPC_SHADOW_DH_size', - '#define DH_up_ref GRPC_SHADOW_DH_up_ref', - '#define DHparams_dup GRPC_SHADOW_DHparams_dup', - '#define BN_get_rfc3526_prime_1536 GRPC_SHADOW_BN_get_rfc3526_prime_1536', - '#define DH_check GRPC_SHADOW_DH_check', - '#define DH_check_pub_key GRPC_SHADOW_DH_check_pub_key', - '#define DH_marshal_parameters GRPC_SHADOW_DH_marshal_parameters', - '#define DH_parse_parameters GRPC_SHADOW_DH_parse_parameters', - '#define d2i_DHparams GRPC_SHADOW_d2i_DHparams', - '#define i2d_DHparams GRPC_SHADOW_i2d_DHparams', - '#define DSA_SIG_free GRPC_SHADOW_DSA_SIG_free', - '#define DSA_SIG_new GRPC_SHADOW_DSA_SIG_new', - '#define DSA_check_signature GRPC_SHADOW_DSA_check_signature', - '#define DSA_do_check_signature GRPC_SHADOW_DSA_do_check_signature', - '#define DSA_do_sign GRPC_SHADOW_DSA_do_sign', - '#define DSA_do_verify GRPC_SHADOW_DSA_do_verify', - '#define DSA_dup_DH GRPC_SHADOW_DSA_dup_DH', - '#define DSA_free GRPC_SHADOW_DSA_free', - '#define DSA_generate_key GRPC_SHADOW_DSA_generate_key', - '#define DSA_generate_parameters_ex GRPC_SHADOW_DSA_generate_parameters_ex', - '#define DSA_get0_key GRPC_SHADOW_DSA_get0_key', - '#define DSA_get0_pqg GRPC_SHADOW_DSA_get0_pqg', - '#define DSA_get_ex_data GRPC_SHADOW_DSA_get_ex_data', - '#define DSA_get_ex_new_index GRPC_SHADOW_DSA_get_ex_new_index', - '#define DSA_new GRPC_SHADOW_DSA_new', - '#define DSA_set0_key GRPC_SHADOW_DSA_set0_key', - '#define DSA_set0_pqg GRPC_SHADOW_DSA_set0_pqg', - '#define DSA_set_ex_data GRPC_SHADOW_DSA_set_ex_data', - '#define DSA_sign GRPC_SHADOW_DSA_sign', - '#define DSA_size GRPC_SHADOW_DSA_size', - '#define DSA_up_ref GRPC_SHADOW_DSA_up_ref', - '#define DSA_verify GRPC_SHADOW_DSA_verify', - '#define DSAparams_dup GRPC_SHADOW_DSAparams_dup', - '#define DSA_SIG_marshal GRPC_SHADOW_DSA_SIG_marshal', - '#define DSA_SIG_parse GRPC_SHADOW_DSA_SIG_parse', - '#define DSA_marshal_parameters GRPC_SHADOW_DSA_marshal_parameters', - '#define DSA_marshal_private_key GRPC_SHADOW_DSA_marshal_private_key', - '#define DSA_marshal_public_key GRPC_SHADOW_DSA_marshal_public_key', - '#define DSA_parse_parameters GRPC_SHADOW_DSA_parse_parameters', - '#define DSA_parse_private_key GRPC_SHADOW_DSA_parse_private_key', - '#define DSA_parse_public_key GRPC_SHADOW_DSA_parse_public_key', - '#define d2i_DSAPrivateKey GRPC_SHADOW_d2i_DSAPrivateKey', - '#define d2i_DSAPublicKey GRPC_SHADOW_d2i_DSAPublicKey', - '#define d2i_DSA_SIG GRPC_SHADOW_d2i_DSA_SIG', - '#define d2i_DSAparams GRPC_SHADOW_d2i_DSAparams', - '#define i2d_DSAPrivateKey GRPC_SHADOW_i2d_DSAPrivateKey', - '#define i2d_DSAPublicKey GRPC_SHADOW_i2d_DSAPublicKey', - '#define i2d_DSA_SIG GRPC_SHADOW_i2d_DSA_SIG', - '#define i2d_DSAparams GRPC_SHADOW_i2d_DSAparams', - '#define RSAPrivateKey_dup GRPC_SHADOW_RSAPrivateKey_dup', - '#define RSAPublicKey_dup GRPC_SHADOW_RSAPublicKey_dup', - '#define RSA_marshal_private_key GRPC_SHADOW_RSA_marshal_private_key', - '#define RSA_marshal_public_key GRPC_SHADOW_RSA_marshal_public_key', - '#define RSA_parse_private_key GRPC_SHADOW_RSA_parse_private_key', - '#define RSA_parse_public_key GRPC_SHADOW_RSA_parse_public_key', - '#define RSA_private_key_from_bytes GRPC_SHADOW_RSA_private_key_from_bytes', - '#define RSA_private_key_to_bytes GRPC_SHADOW_RSA_private_key_to_bytes', - '#define RSA_public_key_from_bytes GRPC_SHADOW_RSA_public_key_from_bytes', - '#define RSA_public_key_to_bytes GRPC_SHADOW_RSA_public_key_to_bytes', - '#define d2i_RSAPrivateKey GRPC_SHADOW_d2i_RSAPrivateKey', - '#define d2i_RSAPublicKey GRPC_SHADOW_d2i_RSAPublicKey', - '#define i2d_RSAPrivateKey GRPC_SHADOW_i2d_RSAPrivateKey', - '#define i2d_RSAPublicKey GRPC_SHADOW_i2d_RSAPublicKey', - '#define EC_KEY_marshal_curve_name GRPC_SHADOW_EC_KEY_marshal_curve_name', - '#define EC_KEY_marshal_private_key GRPC_SHADOW_EC_KEY_marshal_private_key', - '#define EC_KEY_parse_curve_name GRPC_SHADOW_EC_KEY_parse_curve_name', - '#define EC_KEY_parse_parameters GRPC_SHADOW_EC_KEY_parse_parameters', - '#define EC_KEY_parse_private_key GRPC_SHADOW_EC_KEY_parse_private_key', - '#define EC_POINT_point2cbb GRPC_SHADOW_EC_POINT_point2cbb', - '#define d2i_ECParameters GRPC_SHADOW_d2i_ECParameters', - '#define d2i_ECPrivateKey GRPC_SHADOW_d2i_ECPrivateKey', - '#define i2d_ECParameters GRPC_SHADOW_i2d_ECParameters', - '#define i2d_ECPrivateKey GRPC_SHADOW_i2d_ECPrivateKey', - '#define i2o_ECPublicKey GRPC_SHADOW_i2o_ECPublicKey', - '#define o2i_ECPublicKey GRPC_SHADOW_o2i_ECPublicKey', - '#define ECDH_compute_key GRPC_SHADOW_ECDH_compute_key', - '#define ECDSA_SIG_from_bytes GRPC_SHADOW_ECDSA_SIG_from_bytes', - '#define ECDSA_SIG_marshal GRPC_SHADOW_ECDSA_SIG_marshal', - '#define ECDSA_SIG_max_len GRPC_SHADOW_ECDSA_SIG_max_len', - '#define ECDSA_SIG_parse GRPC_SHADOW_ECDSA_SIG_parse', - '#define ECDSA_SIG_to_bytes GRPC_SHADOW_ECDSA_SIG_to_bytes', - '#define ECDSA_sign GRPC_SHADOW_ECDSA_sign', - '#define ECDSA_size GRPC_SHADOW_ECDSA_size', - '#define ECDSA_verify GRPC_SHADOW_ECDSA_verify', - '#define d2i_ECDSA_SIG GRPC_SHADOW_d2i_ECDSA_SIG', - '#define i2d_ECDSA_SIG GRPC_SHADOW_i2d_ECDSA_SIG', - '#define AES_CMAC GRPC_SHADOW_AES_CMAC', - '#define CMAC_CTX_free GRPC_SHADOW_CMAC_CTX_free', - '#define CMAC_CTX_new GRPC_SHADOW_CMAC_CTX_new', - '#define CMAC_Final GRPC_SHADOW_CMAC_Final', - '#define CMAC_Init GRPC_SHADOW_CMAC_Init', - '#define CMAC_Reset GRPC_SHADOW_CMAC_Reset', - '#define CMAC_Update GRPC_SHADOW_CMAC_Update', - '#define EVP_DigestSign GRPC_SHADOW_EVP_DigestSign', - '#define EVP_DigestSignFinal GRPC_SHADOW_EVP_DigestSignFinal', - '#define EVP_DigestSignInit GRPC_SHADOW_EVP_DigestSignInit', - '#define EVP_DigestSignUpdate GRPC_SHADOW_EVP_DigestSignUpdate', - '#define EVP_DigestVerify GRPC_SHADOW_EVP_DigestVerify', - '#define EVP_DigestVerifyFinal GRPC_SHADOW_EVP_DigestVerifyFinal', - '#define EVP_DigestVerifyInit GRPC_SHADOW_EVP_DigestVerifyInit', - '#define EVP_DigestVerifyUpdate GRPC_SHADOW_EVP_DigestVerifyUpdate', - '#define EVP_PKEY_CTX_get_signature_md GRPC_SHADOW_EVP_PKEY_CTX_get_signature_md', - '#define EVP_PKEY_CTX_set_signature_md GRPC_SHADOW_EVP_PKEY_CTX_set_signature_md', - '#define EVP_PKEY_assign GRPC_SHADOW_EVP_PKEY_assign', - '#define EVP_PKEY_assign_DSA GRPC_SHADOW_EVP_PKEY_assign_DSA', - '#define EVP_PKEY_assign_EC_KEY GRPC_SHADOW_EVP_PKEY_assign_EC_KEY', - '#define EVP_PKEY_assign_RSA GRPC_SHADOW_EVP_PKEY_assign_RSA', - '#define EVP_PKEY_bits GRPC_SHADOW_EVP_PKEY_bits', - '#define EVP_PKEY_cmp GRPC_SHADOW_EVP_PKEY_cmp', - '#define EVP_PKEY_cmp_parameters GRPC_SHADOW_EVP_PKEY_cmp_parameters', - '#define EVP_PKEY_copy_parameters GRPC_SHADOW_EVP_PKEY_copy_parameters', - '#define EVP_PKEY_free GRPC_SHADOW_EVP_PKEY_free', - '#define EVP_PKEY_get0_DH GRPC_SHADOW_EVP_PKEY_get0_DH', - '#define EVP_PKEY_get0_DSA GRPC_SHADOW_EVP_PKEY_get0_DSA', - '#define EVP_PKEY_get0_EC_KEY GRPC_SHADOW_EVP_PKEY_get0_EC_KEY', - '#define EVP_PKEY_get0_RSA GRPC_SHADOW_EVP_PKEY_get0_RSA', - '#define EVP_PKEY_get1_DSA GRPC_SHADOW_EVP_PKEY_get1_DSA', - '#define EVP_PKEY_get1_EC_KEY GRPC_SHADOW_EVP_PKEY_get1_EC_KEY', - '#define EVP_PKEY_get1_RSA GRPC_SHADOW_EVP_PKEY_get1_RSA', - '#define EVP_PKEY_id GRPC_SHADOW_EVP_PKEY_id', - '#define EVP_PKEY_is_opaque GRPC_SHADOW_EVP_PKEY_is_opaque', - '#define EVP_PKEY_missing_parameters GRPC_SHADOW_EVP_PKEY_missing_parameters', - '#define EVP_PKEY_new GRPC_SHADOW_EVP_PKEY_new', - '#define EVP_PKEY_set1_DSA GRPC_SHADOW_EVP_PKEY_set1_DSA', - '#define EVP_PKEY_set1_EC_KEY GRPC_SHADOW_EVP_PKEY_set1_EC_KEY', - '#define EVP_PKEY_set1_RSA GRPC_SHADOW_EVP_PKEY_set1_RSA', - '#define EVP_PKEY_set_type GRPC_SHADOW_EVP_PKEY_set_type', - '#define EVP_PKEY_size GRPC_SHADOW_EVP_PKEY_size', - '#define EVP_PKEY_type GRPC_SHADOW_EVP_PKEY_type', - '#define EVP_PKEY_up_ref GRPC_SHADOW_EVP_PKEY_up_ref', - '#define EVP_cleanup GRPC_SHADOW_EVP_cleanup', - '#define OPENSSL_add_all_algorithms_conf GRPC_SHADOW_OPENSSL_add_all_algorithms_conf', - '#define OpenSSL_add_all_algorithms GRPC_SHADOW_OpenSSL_add_all_algorithms', - '#define OpenSSL_add_all_ciphers GRPC_SHADOW_OpenSSL_add_all_ciphers', - '#define OpenSSL_add_all_digests GRPC_SHADOW_OpenSSL_add_all_digests', - '#define EVP_marshal_private_key GRPC_SHADOW_EVP_marshal_private_key', - '#define EVP_marshal_public_key GRPC_SHADOW_EVP_marshal_public_key', - '#define EVP_parse_private_key GRPC_SHADOW_EVP_parse_private_key', - '#define EVP_parse_public_key GRPC_SHADOW_EVP_parse_public_key', - '#define d2i_AutoPrivateKey GRPC_SHADOW_d2i_AutoPrivateKey', - '#define d2i_PrivateKey GRPC_SHADOW_d2i_PrivateKey', - '#define i2d_PublicKey GRPC_SHADOW_i2d_PublicKey', - '#define EVP_PKEY_CTX_ctrl GRPC_SHADOW_EVP_PKEY_CTX_ctrl', - '#define EVP_PKEY_CTX_dup GRPC_SHADOW_EVP_PKEY_CTX_dup', - '#define EVP_PKEY_CTX_free GRPC_SHADOW_EVP_PKEY_CTX_free', - '#define EVP_PKEY_CTX_get0_pkey GRPC_SHADOW_EVP_PKEY_CTX_get0_pkey', - '#define EVP_PKEY_CTX_new GRPC_SHADOW_EVP_PKEY_CTX_new', - '#define EVP_PKEY_CTX_new_id GRPC_SHADOW_EVP_PKEY_CTX_new_id', - '#define EVP_PKEY_decrypt GRPC_SHADOW_EVP_PKEY_decrypt', - '#define EVP_PKEY_decrypt_init GRPC_SHADOW_EVP_PKEY_decrypt_init', - '#define EVP_PKEY_derive GRPC_SHADOW_EVP_PKEY_derive', - '#define EVP_PKEY_derive_init GRPC_SHADOW_EVP_PKEY_derive_init', - '#define EVP_PKEY_derive_set_peer GRPC_SHADOW_EVP_PKEY_derive_set_peer', - '#define EVP_PKEY_encrypt GRPC_SHADOW_EVP_PKEY_encrypt', - '#define EVP_PKEY_encrypt_init GRPC_SHADOW_EVP_PKEY_encrypt_init', - '#define EVP_PKEY_keygen GRPC_SHADOW_EVP_PKEY_keygen', - '#define EVP_PKEY_keygen_init GRPC_SHADOW_EVP_PKEY_keygen_init', - '#define EVP_PKEY_sign GRPC_SHADOW_EVP_PKEY_sign', - '#define EVP_PKEY_sign_init GRPC_SHADOW_EVP_PKEY_sign_init', - '#define EVP_PKEY_verify GRPC_SHADOW_EVP_PKEY_verify', - '#define EVP_PKEY_verify_init GRPC_SHADOW_EVP_PKEY_verify_init', - '#define EVP_PKEY_verify_recover GRPC_SHADOW_EVP_PKEY_verify_recover', - '#define EVP_PKEY_verify_recover_init GRPC_SHADOW_EVP_PKEY_verify_recover_init', - '#define dsa_asn1_meth GRPC_SHADOW_dsa_asn1_meth', - '#define ec_pkey_meth GRPC_SHADOW_ec_pkey_meth', - '#define ec_asn1_meth GRPC_SHADOW_ec_asn1_meth', - '#define ed25519_pkey_meth GRPC_SHADOW_ed25519_pkey_meth', - '#define EVP_PKEY_new_ed25519_private GRPC_SHADOW_EVP_PKEY_new_ed25519_private', - '#define EVP_PKEY_new_ed25519_public GRPC_SHADOW_EVP_PKEY_new_ed25519_public', - '#define ed25519_asn1_meth GRPC_SHADOW_ed25519_asn1_meth', - '#define EVP_PKEY_CTX_get0_rsa_oaep_label GRPC_SHADOW_EVP_PKEY_CTX_get0_rsa_oaep_label', - '#define EVP_PKEY_CTX_get_rsa_mgf1_md GRPC_SHADOW_EVP_PKEY_CTX_get_rsa_mgf1_md', - '#define EVP_PKEY_CTX_get_rsa_oaep_md GRPC_SHADOW_EVP_PKEY_CTX_get_rsa_oaep_md', - '#define EVP_PKEY_CTX_get_rsa_padding GRPC_SHADOW_EVP_PKEY_CTX_get_rsa_padding', - '#define EVP_PKEY_CTX_get_rsa_pss_saltlen GRPC_SHADOW_EVP_PKEY_CTX_get_rsa_pss_saltlen', - '#define EVP_PKEY_CTX_set0_rsa_oaep_label GRPC_SHADOW_EVP_PKEY_CTX_set0_rsa_oaep_label', - '#define EVP_PKEY_CTX_set_rsa_keygen_bits GRPC_SHADOW_EVP_PKEY_CTX_set_rsa_keygen_bits', - '#define EVP_PKEY_CTX_set_rsa_keygen_pubexp GRPC_SHADOW_EVP_PKEY_CTX_set_rsa_keygen_pubexp', - '#define EVP_PKEY_CTX_set_rsa_mgf1_md GRPC_SHADOW_EVP_PKEY_CTX_set_rsa_mgf1_md', - '#define EVP_PKEY_CTX_set_rsa_oaep_md GRPC_SHADOW_EVP_PKEY_CTX_set_rsa_oaep_md', - '#define EVP_PKEY_CTX_set_rsa_padding GRPC_SHADOW_EVP_PKEY_CTX_set_rsa_padding', - '#define EVP_PKEY_CTX_set_rsa_pss_saltlen GRPC_SHADOW_EVP_PKEY_CTX_set_rsa_pss_saltlen', - '#define rsa_pkey_meth GRPC_SHADOW_rsa_pkey_meth', - '#define rsa_asn1_meth GRPC_SHADOW_rsa_asn1_meth', - '#define PKCS5_PBKDF2_HMAC GRPC_SHADOW_PKCS5_PBKDF2_HMAC', - '#define PKCS5_PBKDF2_HMAC_SHA1 GRPC_SHADOW_PKCS5_PBKDF2_HMAC_SHA1', - '#define EVP_PKEY_print_params GRPC_SHADOW_EVP_PKEY_print_params', - '#define EVP_PKEY_print_private GRPC_SHADOW_EVP_PKEY_print_private', - '#define EVP_PKEY_print_public GRPC_SHADOW_EVP_PKEY_print_public', - '#define EVP_PBE_scrypt GRPC_SHADOW_EVP_PBE_scrypt', - '#define EVP_SignFinal GRPC_SHADOW_EVP_SignFinal', - '#define EVP_SignInit GRPC_SHADOW_EVP_SignInit', - '#define EVP_SignInit_ex GRPC_SHADOW_EVP_SignInit_ex', - '#define EVP_SignUpdate GRPC_SHADOW_EVP_SignUpdate', - '#define EVP_VerifyFinal GRPC_SHADOW_EVP_VerifyFinal', - '#define EVP_VerifyInit GRPC_SHADOW_EVP_VerifyInit', - '#define EVP_VerifyInit_ex GRPC_SHADOW_EVP_VerifyInit_ex', - '#define EVP_VerifyUpdate GRPC_SHADOW_EVP_VerifyUpdate', - '#define HKDF GRPC_SHADOW_HKDF', - '#define HKDF_expand GRPC_SHADOW_HKDF_expand', - '#define HKDF_extract GRPC_SHADOW_HKDF_extract', - '#define PEM_read_DSAPrivateKey GRPC_SHADOW_PEM_read_DSAPrivateKey', - '#define PEM_read_DSA_PUBKEY GRPC_SHADOW_PEM_read_DSA_PUBKEY', - '#define PEM_read_DSAparams GRPC_SHADOW_PEM_read_DSAparams', - '#define PEM_read_ECPrivateKey GRPC_SHADOW_PEM_read_ECPrivateKey', - '#define PEM_read_EC_PUBKEY GRPC_SHADOW_PEM_read_EC_PUBKEY', - '#define PEM_read_PUBKEY GRPC_SHADOW_PEM_read_PUBKEY', - '#define PEM_read_RSAPrivateKey GRPC_SHADOW_PEM_read_RSAPrivateKey', - '#define PEM_read_RSAPublicKey GRPC_SHADOW_PEM_read_RSAPublicKey', - '#define PEM_read_RSA_PUBKEY GRPC_SHADOW_PEM_read_RSA_PUBKEY', - '#define PEM_read_X509_CRL GRPC_SHADOW_PEM_read_X509_CRL', - '#define PEM_read_X509_REQ GRPC_SHADOW_PEM_read_X509_REQ', - '#define PEM_read_bio_DSAPrivateKey GRPC_SHADOW_PEM_read_bio_DSAPrivateKey', - '#define PEM_read_bio_DSA_PUBKEY GRPC_SHADOW_PEM_read_bio_DSA_PUBKEY', - '#define PEM_read_bio_DSAparams GRPC_SHADOW_PEM_read_bio_DSAparams', - '#define PEM_read_bio_ECPrivateKey GRPC_SHADOW_PEM_read_bio_ECPrivateKey', - '#define PEM_read_bio_EC_PUBKEY GRPC_SHADOW_PEM_read_bio_EC_PUBKEY', - '#define PEM_read_bio_PUBKEY GRPC_SHADOW_PEM_read_bio_PUBKEY', - '#define PEM_read_bio_RSAPrivateKey GRPC_SHADOW_PEM_read_bio_RSAPrivateKey', - '#define PEM_read_bio_RSAPublicKey GRPC_SHADOW_PEM_read_bio_RSAPublicKey', - '#define PEM_read_bio_RSA_PUBKEY GRPC_SHADOW_PEM_read_bio_RSA_PUBKEY', - '#define PEM_read_bio_X509_CRL GRPC_SHADOW_PEM_read_bio_X509_CRL', - '#define PEM_read_bio_X509_REQ GRPC_SHADOW_PEM_read_bio_X509_REQ', - '#define PEM_write_DHparams GRPC_SHADOW_PEM_write_DHparams', - '#define PEM_write_DSAPrivateKey GRPC_SHADOW_PEM_write_DSAPrivateKey', - '#define PEM_write_DSA_PUBKEY GRPC_SHADOW_PEM_write_DSA_PUBKEY', - '#define PEM_write_DSAparams GRPC_SHADOW_PEM_write_DSAparams', - '#define PEM_write_ECPrivateKey GRPC_SHADOW_PEM_write_ECPrivateKey', - '#define PEM_write_EC_PUBKEY GRPC_SHADOW_PEM_write_EC_PUBKEY', - '#define PEM_write_PUBKEY GRPC_SHADOW_PEM_write_PUBKEY', - '#define PEM_write_RSAPrivateKey GRPC_SHADOW_PEM_write_RSAPrivateKey', - '#define PEM_write_RSAPublicKey GRPC_SHADOW_PEM_write_RSAPublicKey', - '#define PEM_write_RSA_PUBKEY GRPC_SHADOW_PEM_write_RSA_PUBKEY', - '#define PEM_write_X509_CRL GRPC_SHADOW_PEM_write_X509_CRL', - '#define PEM_write_X509_REQ GRPC_SHADOW_PEM_write_X509_REQ', - '#define PEM_write_X509_REQ_NEW GRPC_SHADOW_PEM_write_X509_REQ_NEW', - '#define PEM_write_bio_DHparams GRPC_SHADOW_PEM_write_bio_DHparams', - '#define PEM_write_bio_DSAPrivateKey GRPC_SHADOW_PEM_write_bio_DSAPrivateKey', - '#define PEM_write_bio_DSA_PUBKEY GRPC_SHADOW_PEM_write_bio_DSA_PUBKEY', - '#define PEM_write_bio_DSAparams GRPC_SHADOW_PEM_write_bio_DSAparams', - '#define PEM_write_bio_ECPrivateKey GRPC_SHADOW_PEM_write_bio_ECPrivateKey', - '#define PEM_write_bio_EC_PUBKEY GRPC_SHADOW_PEM_write_bio_EC_PUBKEY', - '#define PEM_write_bio_PUBKEY GRPC_SHADOW_PEM_write_bio_PUBKEY', - '#define PEM_write_bio_RSAPrivateKey GRPC_SHADOW_PEM_write_bio_RSAPrivateKey', - '#define PEM_write_bio_RSAPublicKey GRPC_SHADOW_PEM_write_bio_RSAPublicKey', - '#define PEM_write_bio_RSA_PUBKEY GRPC_SHADOW_PEM_write_bio_RSA_PUBKEY', - '#define PEM_write_bio_X509_CRL GRPC_SHADOW_PEM_write_bio_X509_CRL', - '#define PEM_write_bio_X509_REQ GRPC_SHADOW_PEM_write_bio_X509_REQ', - '#define PEM_write_bio_X509_REQ_NEW GRPC_SHADOW_PEM_write_bio_X509_REQ_NEW', - '#define PEM_X509_INFO_read GRPC_SHADOW_PEM_X509_INFO_read', - '#define PEM_X509_INFO_read_bio GRPC_SHADOW_PEM_X509_INFO_read_bio', - '#define PEM_X509_INFO_write_bio GRPC_SHADOW_PEM_X509_INFO_write_bio', - '#define PEM_ASN1_read GRPC_SHADOW_PEM_ASN1_read', - '#define PEM_ASN1_write GRPC_SHADOW_PEM_ASN1_write', - '#define PEM_ASN1_write_bio GRPC_SHADOW_PEM_ASN1_write_bio', - '#define PEM_bytes_read_bio GRPC_SHADOW_PEM_bytes_read_bio', - '#define PEM_def_callback GRPC_SHADOW_PEM_def_callback', - '#define PEM_dek_info GRPC_SHADOW_PEM_dek_info', - '#define PEM_do_header GRPC_SHADOW_PEM_do_header', - '#define PEM_get_EVP_CIPHER_INFO GRPC_SHADOW_PEM_get_EVP_CIPHER_INFO', - '#define PEM_proc_type GRPC_SHADOW_PEM_proc_type', - '#define PEM_read GRPC_SHADOW_PEM_read', - '#define PEM_read_bio GRPC_SHADOW_PEM_read_bio', - '#define PEM_write GRPC_SHADOW_PEM_write', - '#define PEM_write_bio GRPC_SHADOW_PEM_write_bio', - '#define PEM_ASN1_read_bio GRPC_SHADOW_PEM_ASN1_read_bio', - '#define PEM_read_PKCS8 GRPC_SHADOW_PEM_read_PKCS8', - '#define PEM_read_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_PEM_read_PKCS8_PRIV_KEY_INFO', - '#define PEM_read_bio_PKCS8 GRPC_SHADOW_PEM_read_bio_PKCS8', - '#define PEM_read_bio_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_PEM_read_bio_PKCS8_PRIV_KEY_INFO', - '#define PEM_write_PKCS8 GRPC_SHADOW_PEM_write_PKCS8', - '#define PEM_write_PKCS8PrivateKey GRPC_SHADOW_PEM_write_PKCS8PrivateKey', - '#define PEM_write_PKCS8PrivateKey_nid GRPC_SHADOW_PEM_write_PKCS8PrivateKey_nid', - '#define PEM_write_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_PEM_write_PKCS8_PRIV_KEY_INFO', - '#define PEM_write_bio_PKCS8 GRPC_SHADOW_PEM_write_bio_PKCS8', - '#define PEM_write_bio_PKCS8PrivateKey GRPC_SHADOW_PEM_write_bio_PKCS8PrivateKey', - '#define PEM_write_bio_PKCS8PrivateKey_nid GRPC_SHADOW_PEM_write_bio_PKCS8PrivateKey_nid', - '#define PEM_write_bio_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_PEM_write_bio_PKCS8_PRIV_KEY_INFO', - '#define d2i_PKCS8PrivateKey_bio GRPC_SHADOW_d2i_PKCS8PrivateKey_bio', - '#define d2i_PKCS8PrivateKey_fp GRPC_SHADOW_d2i_PKCS8PrivateKey_fp', - '#define i2d_PKCS8PrivateKey_bio GRPC_SHADOW_i2d_PKCS8PrivateKey_bio', - '#define i2d_PKCS8PrivateKey_fp GRPC_SHADOW_i2d_PKCS8PrivateKey_fp', - '#define i2d_PKCS8PrivateKey_nid_bio GRPC_SHADOW_i2d_PKCS8PrivateKey_nid_bio', - '#define i2d_PKCS8PrivateKey_nid_fp GRPC_SHADOW_i2d_PKCS8PrivateKey_nid_fp', - '#define PEM_read_DHparams GRPC_SHADOW_PEM_read_DHparams', - '#define PEM_read_PrivateKey GRPC_SHADOW_PEM_read_PrivateKey', - '#define PEM_read_bio_DHparams GRPC_SHADOW_PEM_read_bio_DHparams', - '#define PEM_read_bio_PrivateKey GRPC_SHADOW_PEM_read_bio_PrivateKey', - '#define PEM_write_PrivateKey GRPC_SHADOW_PEM_write_PrivateKey', - '#define PEM_write_bio_PrivateKey GRPC_SHADOW_PEM_write_bio_PrivateKey', - '#define PEM_read_X509 GRPC_SHADOW_PEM_read_X509', - '#define PEM_read_bio_X509 GRPC_SHADOW_PEM_read_bio_X509', - '#define PEM_write_X509 GRPC_SHADOW_PEM_write_X509', - '#define PEM_write_bio_X509 GRPC_SHADOW_PEM_write_bio_X509', - '#define PEM_read_X509_AUX GRPC_SHADOW_PEM_read_X509_AUX', - '#define PEM_read_bio_X509_AUX GRPC_SHADOW_PEM_read_bio_X509_AUX', - '#define PEM_write_X509_AUX GRPC_SHADOW_PEM_write_X509_AUX', - '#define PEM_write_bio_X509_AUX GRPC_SHADOW_PEM_write_bio_X509_AUX', - '#define ASN1_digest GRPC_SHADOW_ASN1_digest', - '#define ASN1_item_digest GRPC_SHADOW_ASN1_item_digest', - '#define ASN1_item_sign GRPC_SHADOW_ASN1_item_sign', - '#define ASN1_item_sign_ctx GRPC_SHADOW_ASN1_item_sign_ctx', - '#define ASN1_STRING_print_ex GRPC_SHADOW_ASN1_STRING_print_ex', - '#define ASN1_STRING_print_ex_fp GRPC_SHADOW_ASN1_STRING_print_ex_fp', - '#define ASN1_STRING_to_UTF8 GRPC_SHADOW_ASN1_STRING_to_UTF8', - '#define X509_NAME_print_ex GRPC_SHADOW_X509_NAME_print_ex', - '#define X509_NAME_print_ex_fp GRPC_SHADOW_X509_NAME_print_ex_fp', - '#define ASN1_item_verify GRPC_SHADOW_ASN1_item_verify', - '#define x509_digest_sign_algorithm GRPC_SHADOW_x509_digest_sign_algorithm', - '#define x509_digest_verify_init GRPC_SHADOW_x509_digest_verify_init', - '#define ASN1_generate_nconf GRPC_SHADOW_ASN1_generate_nconf', - '#define ASN1_generate_v3 GRPC_SHADOW_ASN1_generate_v3', - '#define X509_LOOKUP_hash_dir GRPC_SHADOW_X509_LOOKUP_hash_dir', - '#define X509_LOOKUP_file GRPC_SHADOW_X509_LOOKUP_file', - '#define X509_load_cert_crl_file GRPC_SHADOW_X509_load_cert_crl_file', - '#define X509_load_cert_file GRPC_SHADOW_X509_load_cert_file', - '#define X509_load_crl_file GRPC_SHADOW_X509_load_crl_file', - '#define i2d_PrivateKey GRPC_SHADOW_i2d_PrivateKey', - '#define RSA_PSS_PARAMS_free GRPC_SHADOW_RSA_PSS_PARAMS_free', - '#define RSA_PSS_PARAMS_it GRPC_SHADOW_RSA_PSS_PARAMS_it', - '#define RSA_PSS_PARAMS_new GRPC_SHADOW_RSA_PSS_PARAMS_new', - '#define d2i_RSA_PSS_PARAMS GRPC_SHADOW_d2i_RSA_PSS_PARAMS', - '#define i2d_RSA_PSS_PARAMS GRPC_SHADOW_i2d_RSA_PSS_PARAMS', - '#define x509_print_rsa_pss_params GRPC_SHADOW_x509_print_rsa_pss_params', - '#define x509_rsa_ctx_to_pss GRPC_SHADOW_x509_rsa_ctx_to_pss', - '#define x509_rsa_pss_to_ctx GRPC_SHADOW_x509_rsa_pss_to_ctx', - '#define X509_CRL_print GRPC_SHADOW_X509_CRL_print', - '#define X509_CRL_print_fp GRPC_SHADOW_X509_CRL_print_fp', - '#define X509_REQ_print GRPC_SHADOW_X509_REQ_print', - '#define X509_REQ_print_ex GRPC_SHADOW_X509_REQ_print_ex', - '#define X509_REQ_print_fp GRPC_SHADOW_X509_REQ_print_fp', - '#define ASN1_GENERALIZEDTIME_print GRPC_SHADOW_ASN1_GENERALIZEDTIME_print', - '#define ASN1_STRING_print GRPC_SHADOW_ASN1_STRING_print', - '#define ASN1_TIME_print GRPC_SHADOW_ASN1_TIME_print', - '#define ASN1_UTCTIME_print GRPC_SHADOW_ASN1_UTCTIME_print', - '#define X509_NAME_print GRPC_SHADOW_X509_NAME_print', - '#define X509_ocspid_print GRPC_SHADOW_X509_ocspid_print', - '#define X509_print GRPC_SHADOW_X509_print', - '#define X509_print_ex GRPC_SHADOW_X509_print_ex', - '#define X509_print_ex_fp GRPC_SHADOW_X509_print_ex_fp', - '#define X509_print_fp GRPC_SHADOW_X509_print_fp', - '#define X509_signature_print GRPC_SHADOW_X509_signature_print', - '#define X509_CERT_AUX_print GRPC_SHADOW_X509_CERT_AUX_print', - '#define PKCS8_pkey_get0 GRPC_SHADOW_PKCS8_pkey_get0', - '#define PKCS8_pkey_set0 GRPC_SHADOW_PKCS8_pkey_set0', - '#define X509_signature_dump GRPC_SHADOW_X509_signature_dump', - '#define X509_ATTRIBUTE_count GRPC_SHADOW_X509_ATTRIBUTE_count', - '#define X509_ATTRIBUTE_create_by_NID GRPC_SHADOW_X509_ATTRIBUTE_create_by_NID', - '#define X509_ATTRIBUTE_create_by_OBJ GRPC_SHADOW_X509_ATTRIBUTE_create_by_OBJ', - '#define X509_ATTRIBUTE_create_by_txt GRPC_SHADOW_X509_ATTRIBUTE_create_by_txt', - '#define X509_ATTRIBUTE_get0_data GRPC_SHADOW_X509_ATTRIBUTE_get0_data', - '#define X509_ATTRIBUTE_get0_object GRPC_SHADOW_X509_ATTRIBUTE_get0_object', - '#define X509_ATTRIBUTE_get0_type GRPC_SHADOW_X509_ATTRIBUTE_get0_type', - '#define X509_ATTRIBUTE_set1_data GRPC_SHADOW_X509_ATTRIBUTE_set1_data', - '#define X509_ATTRIBUTE_set1_object GRPC_SHADOW_X509_ATTRIBUTE_set1_object', - '#define X509at_add1_attr GRPC_SHADOW_X509at_add1_attr', - '#define X509at_add1_attr_by_NID GRPC_SHADOW_X509at_add1_attr_by_NID', - '#define X509at_add1_attr_by_OBJ GRPC_SHADOW_X509at_add1_attr_by_OBJ', - '#define X509at_add1_attr_by_txt GRPC_SHADOW_X509at_add1_attr_by_txt', - '#define X509at_delete_attr GRPC_SHADOW_X509at_delete_attr', - '#define X509at_get0_data_by_OBJ GRPC_SHADOW_X509at_get0_data_by_OBJ', - '#define X509at_get_attr GRPC_SHADOW_X509at_get_attr', - '#define X509at_get_attr_by_NID GRPC_SHADOW_X509at_get_attr_by_NID', - '#define X509at_get_attr_by_OBJ GRPC_SHADOW_X509at_get_attr_by_OBJ', - '#define X509at_get_attr_count GRPC_SHADOW_X509at_get_attr_count', - '#define X509_CRL_check_suiteb GRPC_SHADOW_X509_CRL_check_suiteb', - '#define X509_CRL_cmp GRPC_SHADOW_X509_CRL_cmp', - '#define X509_CRL_match GRPC_SHADOW_X509_CRL_match', - '#define X509_NAME_cmp GRPC_SHADOW_X509_NAME_cmp', - '#define X509_NAME_hash GRPC_SHADOW_X509_NAME_hash', - '#define X509_NAME_hash_old GRPC_SHADOW_X509_NAME_hash_old', - '#define X509_chain_check_suiteb GRPC_SHADOW_X509_chain_check_suiteb', - '#define X509_chain_up_ref GRPC_SHADOW_X509_chain_up_ref', - '#define X509_check_private_key GRPC_SHADOW_X509_check_private_key', - '#define X509_cmp GRPC_SHADOW_X509_cmp', - '#define X509_find_by_issuer_and_serial GRPC_SHADOW_X509_find_by_issuer_and_serial', - '#define X509_find_by_subject GRPC_SHADOW_X509_find_by_subject', - '#define X509_get0_pubkey_bitstr GRPC_SHADOW_X509_get0_pubkey_bitstr', - '#define X509_get_issuer_name GRPC_SHADOW_X509_get_issuer_name', - '#define X509_get_pubkey GRPC_SHADOW_X509_get_pubkey', - '#define X509_get_serialNumber GRPC_SHADOW_X509_get_serialNumber', - '#define X509_get_subject_name GRPC_SHADOW_X509_get_subject_name', - '#define X509_issuer_and_serial_cmp GRPC_SHADOW_X509_issuer_and_serial_cmp', - '#define X509_issuer_and_serial_hash GRPC_SHADOW_X509_issuer_and_serial_hash', - '#define X509_issuer_name_cmp GRPC_SHADOW_X509_issuer_name_cmp', - '#define X509_issuer_name_hash GRPC_SHADOW_X509_issuer_name_hash', - '#define X509_issuer_name_hash_old GRPC_SHADOW_X509_issuer_name_hash_old', - '#define X509_subject_name_cmp GRPC_SHADOW_X509_subject_name_cmp', - '#define X509_subject_name_hash GRPC_SHADOW_X509_subject_name_hash', - '#define X509_subject_name_hash_old GRPC_SHADOW_X509_subject_name_hash_old', - '#define X509_STORE_load_locations GRPC_SHADOW_X509_STORE_load_locations', - '#define X509_STORE_set_default_paths GRPC_SHADOW_X509_STORE_set_default_paths', - '#define X509_get_default_cert_area GRPC_SHADOW_X509_get_default_cert_area', - '#define X509_get_default_cert_dir GRPC_SHADOW_X509_get_default_cert_dir', - '#define X509_get_default_cert_dir_env GRPC_SHADOW_X509_get_default_cert_dir_env', - '#define X509_get_default_cert_file GRPC_SHADOW_X509_get_default_cert_file', - '#define X509_get_default_cert_file_env GRPC_SHADOW_X509_get_default_cert_file_env', - '#define X509_get_default_private_dir GRPC_SHADOW_X509_get_default_private_dir', - '#define X509_CRL_add1_ext_i2d GRPC_SHADOW_X509_CRL_add1_ext_i2d', - '#define X509_CRL_add_ext GRPC_SHADOW_X509_CRL_add_ext', - '#define X509_CRL_delete_ext GRPC_SHADOW_X509_CRL_delete_ext', - '#define X509_CRL_get_ext GRPC_SHADOW_X509_CRL_get_ext', - '#define X509_CRL_get_ext_by_NID GRPC_SHADOW_X509_CRL_get_ext_by_NID', - '#define X509_CRL_get_ext_by_OBJ GRPC_SHADOW_X509_CRL_get_ext_by_OBJ', - '#define X509_CRL_get_ext_by_critical GRPC_SHADOW_X509_CRL_get_ext_by_critical', - '#define X509_CRL_get_ext_count GRPC_SHADOW_X509_CRL_get_ext_count', - '#define X509_CRL_get_ext_d2i GRPC_SHADOW_X509_CRL_get_ext_d2i', - '#define X509_REVOKED_add1_ext_i2d GRPC_SHADOW_X509_REVOKED_add1_ext_i2d', - '#define X509_REVOKED_add_ext GRPC_SHADOW_X509_REVOKED_add_ext', - '#define X509_REVOKED_delete_ext GRPC_SHADOW_X509_REVOKED_delete_ext', - '#define X509_REVOKED_get_ext GRPC_SHADOW_X509_REVOKED_get_ext', - '#define X509_REVOKED_get_ext_by_NID GRPC_SHADOW_X509_REVOKED_get_ext_by_NID', - '#define X509_REVOKED_get_ext_by_OBJ GRPC_SHADOW_X509_REVOKED_get_ext_by_OBJ', - '#define X509_REVOKED_get_ext_by_critical GRPC_SHADOW_X509_REVOKED_get_ext_by_critical', - '#define X509_REVOKED_get_ext_count GRPC_SHADOW_X509_REVOKED_get_ext_count', - '#define X509_REVOKED_get_ext_d2i GRPC_SHADOW_X509_REVOKED_get_ext_d2i', - '#define X509_add1_ext_i2d GRPC_SHADOW_X509_add1_ext_i2d', - '#define X509_add_ext GRPC_SHADOW_X509_add_ext', - '#define X509_delete_ext GRPC_SHADOW_X509_delete_ext', - '#define X509_get_ext GRPC_SHADOW_X509_get_ext', - '#define X509_get_ext_by_NID GRPC_SHADOW_X509_get_ext_by_NID', - '#define X509_get_ext_by_OBJ GRPC_SHADOW_X509_get_ext_by_OBJ', - '#define X509_get_ext_by_critical GRPC_SHADOW_X509_get_ext_by_critical', - '#define X509_get_ext_count GRPC_SHADOW_X509_get_ext_count', - '#define X509_get_ext_d2i GRPC_SHADOW_X509_get_ext_d2i', - '#define X509_LOOKUP_by_alias GRPC_SHADOW_X509_LOOKUP_by_alias', - '#define X509_LOOKUP_by_fingerprint GRPC_SHADOW_X509_LOOKUP_by_fingerprint', - '#define X509_LOOKUP_by_issuer_serial GRPC_SHADOW_X509_LOOKUP_by_issuer_serial', - '#define X509_LOOKUP_by_subject GRPC_SHADOW_X509_LOOKUP_by_subject', - '#define X509_LOOKUP_ctrl GRPC_SHADOW_X509_LOOKUP_ctrl', - '#define X509_LOOKUP_free GRPC_SHADOW_X509_LOOKUP_free', - '#define X509_LOOKUP_init GRPC_SHADOW_X509_LOOKUP_init', - '#define X509_LOOKUP_new GRPC_SHADOW_X509_LOOKUP_new', - '#define X509_LOOKUP_shutdown GRPC_SHADOW_X509_LOOKUP_shutdown', - '#define X509_OBJECT_free_contents GRPC_SHADOW_X509_OBJECT_free_contents', - '#define X509_OBJECT_get0_X509 GRPC_SHADOW_X509_OBJECT_get0_X509', - '#define X509_OBJECT_get_type GRPC_SHADOW_X509_OBJECT_get_type', - '#define X509_OBJECT_idx_by_subject GRPC_SHADOW_X509_OBJECT_idx_by_subject', - '#define X509_OBJECT_retrieve_by_subject GRPC_SHADOW_X509_OBJECT_retrieve_by_subject', - '#define X509_OBJECT_retrieve_match GRPC_SHADOW_X509_OBJECT_retrieve_match', - '#define X509_OBJECT_up_ref_count GRPC_SHADOW_X509_OBJECT_up_ref_count', - '#define X509_STORE_CTX_get0_store GRPC_SHADOW_X509_STORE_CTX_get0_store', - '#define X509_STORE_CTX_get1_issuer GRPC_SHADOW_X509_STORE_CTX_get1_issuer', - '#define X509_STORE_add_cert GRPC_SHADOW_X509_STORE_add_cert', - '#define X509_STORE_add_crl GRPC_SHADOW_X509_STORE_add_crl', - '#define X509_STORE_add_lookup GRPC_SHADOW_X509_STORE_add_lookup', - '#define X509_STORE_free GRPC_SHADOW_X509_STORE_free', - '#define X509_STORE_get0_objects GRPC_SHADOW_X509_STORE_get0_objects', - '#define X509_STORE_get0_param GRPC_SHADOW_X509_STORE_get0_param', - '#define X509_STORE_get1_certs GRPC_SHADOW_X509_STORE_get1_certs', - '#define X509_STORE_get1_crls GRPC_SHADOW_X509_STORE_get1_crls', - '#define X509_STORE_get_by_subject GRPC_SHADOW_X509_STORE_get_by_subject', - '#define X509_STORE_new GRPC_SHADOW_X509_STORE_new', - '#define X509_STORE_set0_additional_untrusted GRPC_SHADOW_X509_STORE_set0_additional_untrusted', - '#define X509_STORE_set1_param GRPC_SHADOW_X509_STORE_set1_param', - '#define X509_STORE_set_depth GRPC_SHADOW_X509_STORE_set_depth', - '#define X509_STORE_set_flags GRPC_SHADOW_X509_STORE_set_flags', - '#define X509_STORE_set_lookup_crls_cb GRPC_SHADOW_X509_STORE_set_lookup_crls_cb', - '#define X509_STORE_set_purpose GRPC_SHADOW_X509_STORE_set_purpose', - '#define X509_STORE_set_trust GRPC_SHADOW_X509_STORE_set_trust', - '#define X509_STORE_set_verify_cb GRPC_SHADOW_X509_STORE_set_verify_cb', - '#define X509_STORE_up_ref GRPC_SHADOW_X509_STORE_up_ref', - '#define X509_NAME_oneline GRPC_SHADOW_X509_NAME_oneline', - '#define X509_REQ_to_X509 GRPC_SHADOW_X509_REQ_to_X509', - '#define X509_REQ_add1_attr GRPC_SHADOW_X509_REQ_add1_attr', - '#define X509_REQ_add1_attr_by_NID GRPC_SHADOW_X509_REQ_add1_attr_by_NID', - '#define X509_REQ_add1_attr_by_OBJ GRPC_SHADOW_X509_REQ_add1_attr_by_OBJ', - '#define X509_REQ_add1_attr_by_txt GRPC_SHADOW_X509_REQ_add1_attr_by_txt', - '#define X509_REQ_add_extensions GRPC_SHADOW_X509_REQ_add_extensions', - '#define X509_REQ_add_extensions_nid GRPC_SHADOW_X509_REQ_add_extensions_nid', - '#define X509_REQ_check_private_key GRPC_SHADOW_X509_REQ_check_private_key', - '#define X509_REQ_delete_attr GRPC_SHADOW_X509_REQ_delete_attr', - '#define X509_REQ_extension_nid GRPC_SHADOW_X509_REQ_extension_nid', - '#define X509_REQ_get_attr GRPC_SHADOW_X509_REQ_get_attr', - '#define X509_REQ_get_attr_by_NID GRPC_SHADOW_X509_REQ_get_attr_by_NID', - '#define X509_REQ_get_attr_by_OBJ GRPC_SHADOW_X509_REQ_get_attr_by_OBJ', - '#define X509_REQ_get_attr_count GRPC_SHADOW_X509_REQ_get_attr_count', - '#define X509_REQ_get_extension_nids GRPC_SHADOW_X509_REQ_get_extension_nids', - '#define X509_REQ_get_extensions GRPC_SHADOW_X509_REQ_get_extensions', - '#define X509_REQ_get_pubkey GRPC_SHADOW_X509_REQ_get_pubkey', - '#define X509_REQ_set_extension_nids GRPC_SHADOW_X509_REQ_set_extension_nids', - '#define X509_to_X509_REQ GRPC_SHADOW_X509_to_X509_REQ', - '#define X509_get0_extensions GRPC_SHADOW_X509_get0_extensions', - '#define X509_get0_notAfter GRPC_SHADOW_X509_get0_notAfter', - '#define X509_get0_notBefore GRPC_SHADOW_X509_get0_notBefore', - '#define X509_set_issuer_name GRPC_SHADOW_X509_set_issuer_name', - '#define X509_set_notAfter GRPC_SHADOW_X509_set_notAfter', - '#define X509_set_notBefore GRPC_SHADOW_X509_set_notBefore', - '#define X509_set_pubkey GRPC_SHADOW_X509_set_pubkey', - '#define X509_set_serialNumber GRPC_SHADOW_X509_set_serialNumber', - '#define X509_set_subject_name GRPC_SHADOW_X509_set_subject_name', - '#define X509_set_version GRPC_SHADOW_X509_set_version', - '#define X509_TRUST_add GRPC_SHADOW_X509_TRUST_add', - '#define X509_TRUST_cleanup GRPC_SHADOW_X509_TRUST_cleanup', - '#define X509_TRUST_get0 GRPC_SHADOW_X509_TRUST_get0', - '#define X509_TRUST_get0_name GRPC_SHADOW_X509_TRUST_get0_name', - '#define X509_TRUST_get_by_id GRPC_SHADOW_X509_TRUST_get_by_id', - '#define X509_TRUST_get_count GRPC_SHADOW_X509_TRUST_get_count', - '#define X509_TRUST_get_flags GRPC_SHADOW_X509_TRUST_get_flags', - '#define X509_TRUST_get_trust GRPC_SHADOW_X509_TRUST_get_trust', - '#define X509_TRUST_set GRPC_SHADOW_X509_TRUST_set', - '#define X509_TRUST_set_default GRPC_SHADOW_X509_TRUST_set_default', - '#define X509_check_trust GRPC_SHADOW_X509_check_trust', - '#define X509_verify_cert_error_string GRPC_SHADOW_X509_verify_cert_error_string', - '#define X509_EXTENSION_create_by_NID GRPC_SHADOW_X509_EXTENSION_create_by_NID', - '#define X509_EXTENSION_create_by_OBJ GRPC_SHADOW_X509_EXTENSION_create_by_OBJ', - '#define X509_EXTENSION_get_critical GRPC_SHADOW_X509_EXTENSION_get_critical', - '#define X509_EXTENSION_get_data GRPC_SHADOW_X509_EXTENSION_get_data', - '#define X509_EXTENSION_get_object GRPC_SHADOW_X509_EXTENSION_get_object', - '#define X509_EXTENSION_set_critical GRPC_SHADOW_X509_EXTENSION_set_critical', - '#define X509_EXTENSION_set_data GRPC_SHADOW_X509_EXTENSION_set_data', - '#define X509_EXTENSION_set_object GRPC_SHADOW_X509_EXTENSION_set_object', - '#define X509v3_add_ext GRPC_SHADOW_X509v3_add_ext', - '#define X509v3_delete_ext GRPC_SHADOW_X509v3_delete_ext', - '#define X509v3_get_ext GRPC_SHADOW_X509v3_get_ext', - '#define X509v3_get_ext_by_NID GRPC_SHADOW_X509v3_get_ext_by_NID', - '#define X509v3_get_ext_by_OBJ GRPC_SHADOW_X509v3_get_ext_by_OBJ', - '#define X509v3_get_ext_by_critical GRPC_SHADOW_X509v3_get_ext_by_critical', - '#define X509v3_get_ext_count GRPC_SHADOW_X509v3_get_ext_count', - '#define X509_CRL_diff GRPC_SHADOW_X509_CRL_diff', - '#define X509_STORE_CTX_cleanup GRPC_SHADOW_X509_STORE_CTX_cleanup', - '#define X509_STORE_CTX_free GRPC_SHADOW_X509_STORE_CTX_free', - '#define X509_STORE_CTX_get0_current_crl GRPC_SHADOW_X509_STORE_CTX_get0_current_crl', - '#define X509_STORE_CTX_get0_current_issuer GRPC_SHADOW_X509_STORE_CTX_get0_current_issuer', - '#define X509_STORE_CTX_get0_param GRPC_SHADOW_X509_STORE_CTX_get0_param', - '#define X509_STORE_CTX_get0_parent_ctx GRPC_SHADOW_X509_STORE_CTX_get0_parent_ctx', - '#define X509_STORE_CTX_get0_policy_tree GRPC_SHADOW_X509_STORE_CTX_get0_policy_tree', - '#define X509_STORE_CTX_get0_untrusted GRPC_SHADOW_X509_STORE_CTX_get0_untrusted', - '#define X509_STORE_CTX_get1_chain GRPC_SHADOW_X509_STORE_CTX_get1_chain', - '#define X509_STORE_CTX_get_chain GRPC_SHADOW_X509_STORE_CTX_get_chain', - '#define X509_STORE_CTX_get_current_cert GRPC_SHADOW_X509_STORE_CTX_get_current_cert', - '#define X509_STORE_CTX_get_error GRPC_SHADOW_X509_STORE_CTX_get_error', - '#define X509_STORE_CTX_get_error_depth GRPC_SHADOW_X509_STORE_CTX_get_error_depth', - '#define X509_STORE_CTX_get_ex_data GRPC_SHADOW_X509_STORE_CTX_get_ex_data', - '#define X509_STORE_CTX_get_ex_new_index GRPC_SHADOW_X509_STORE_CTX_get_ex_new_index', - '#define X509_STORE_CTX_get_explicit_policy GRPC_SHADOW_X509_STORE_CTX_get_explicit_policy', - '#define X509_STORE_CTX_init GRPC_SHADOW_X509_STORE_CTX_init', - '#define X509_STORE_CTX_new GRPC_SHADOW_X509_STORE_CTX_new', - '#define X509_STORE_CTX_purpose_inherit GRPC_SHADOW_X509_STORE_CTX_purpose_inherit', - '#define X509_STORE_CTX_set0_crls GRPC_SHADOW_X509_STORE_CTX_set0_crls', - '#define X509_STORE_CTX_set0_param GRPC_SHADOW_X509_STORE_CTX_set0_param', - '#define X509_STORE_CTX_set_cert GRPC_SHADOW_X509_STORE_CTX_set_cert', - '#define X509_STORE_CTX_set_chain GRPC_SHADOW_X509_STORE_CTX_set_chain', - '#define X509_STORE_CTX_set_default GRPC_SHADOW_X509_STORE_CTX_set_default', - '#define X509_STORE_CTX_set_depth GRPC_SHADOW_X509_STORE_CTX_set_depth', - '#define X509_STORE_CTX_set_error GRPC_SHADOW_X509_STORE_CTX_set_error', - '#define X509_STORE_CTX_set_ex_data GRPC_SHADOW_X509_STORE_CTX_set_ex_data', - '#define X509_STORE_CTX_set_flags GRPC_SHADOW_X509_STORE_CTX_set_flags', - '#define X509_STORE_CTX_set_purpose GRPC_SHADOW_X509_STORE_CTX_set_purpose', - '#define X509_STORE_CTX_set_time GRPC_SHADOW_X509_STORE_CTX_set_time', - '#define X509_STORE_CTX_set_trust GRPC_SHADOW_X509_STORE_CTX_set_trust', - '#define X509_STORE_CTX_set_verify_cb GRPC_SHADOW_X509_STORE_CTX_set_verify_cb', - '#define X509_STORE_CTX_trusted_stack GRPC_SHADOW_X509_STORE_CTX_trusted_stack', - '#define X509_STORE_CTX_zero GRPC_SHADOW_X509_STORE_CTX_zero', - '#define X509_cmp_current_time GRPC_SHADOW_X509_cmp_current_time', - '#define X509_cmp_time GRPC_SHADOW_X509_cmp_time', - '#define X509_gmtime_adj GRPC_SHADOW_X509_gmtime_adj', - '#define X509_time_adj GRPC_SHADOW_X509_time_adj', - '#define X509_time_adj_ex GRPC_SHADOW_X509_time_adj_ex', - '#define X509_verify_cert GRPC_SHADOW_X509_verify_cert', - '#define X509_VERIFY_PARAM_add0_policy GRPC_SHADOW_X509_VERIFY_PARAM_add0_policy', - '#define X509_VERIFY_PARAM_add0_table GRPC_SHADOW_X509_VERIFY_PARAM_add0_table', - '#define X509_VERIFY_PARAM_add1_host GRPC_SHADOW_X509_VERIFY_PARAM_add1_host', - '#define X509_VERIFY_PARAM_clear_flags GRPC_SHADOW_X509_VERIFY_PARAM_clear_flags', - '#define X509_VERIFY_PARAM_free GRPC_SHADOW_X509_VERIFY_PARAM_free', - '#define X509_VERIFY_PARAM_get0 GRPC_SHADOW_X509_VERIFY_PARAM_get0', - '#define X509_VERIFY_PARAM_get0_name GRPC_SHADOW_X509_VERIFY_PARAM_get0_name', - '#define X509_VERIFY_PARAM_get0_peername GRPC_SHADOW_X509_VERIFY_PARAM_get0_peername', - '#define X509_VERIFY_PARAM_get_count GRPC_SHADOW_X509_VERIFY_PARAM_get_count', - '#define X509_VERIFY_PARAM_get_depth GRPC_SHADOW_X509_VERIFY_PARAM_get_depth', - '#define X509_VERIFY_PARAM_get_flags GRPC_SHADOW_X509_VERIFY_PARAM_get_flags', - '#define X509_VERIFY_PARAM_inherit GRPC_SHADOW_X509_VERIFY_PARAM_inherit', - '#define X509_VERIFY_PARAM_lookup GRPC_SHADOW_X509_VERIFY_PARAM_lookup', - '#define X509_VERIFY_PARAM_new GRPC_SHADOW_X509_VERIFY_PARAM_new', - '#define X509_VERIFY_PARAM_set1 GRPC_SHADOW_X509_VERIFY_PARAM_set1', - '#define X509_VERIFY_PARAM_set1_email GRPC_SHADOW_X509_VERIFY_PARAM_set1_email', - '#define X509_VERIFY_PARAM_set1_host GRPC_SHADOW_X509_VERIFY_PARAM_set1_host', - '#define X509_VERIFY_PARAM_set1_ip GRPC_SHADOW_X509_VERIFY_PARAM_set1_ip', - '#define X509_VERIFY_PARAM_set1_ip_asc GRPC_SHADOW_X509_VERIFY_PARAM_set1_ip_asc', - '#define X509_VERIFY_PARAM_set1_name GRPC_SHADOW_X509_VERIFY_PARAM_set1_name', - '#define X509_VERIFY_PARAM_set1_policies GRPC_SHADOW_X509_VERIFY_PARAM_set1_policies', - '#define X509_VERIFY_PARAM_set_depth GRPC_SHADOW_X509_VERIFY_PARAM_set_depth', - '#define X509_VERIFY_PARAM_set_flags GRPC_SHADOW_X509_VERIFY_PARAM_set_flags', - '#define X509_VERIFY_PARAM_set_hostflags GRPC_SHADOW_X509_VERIFY_PARAM_set_hostflags', - '#define X509_VERIFY_PARAM_set_purpose GRPC_SHADOW_X509_VERIFY_PARAM_set_purpose', - '#define X509_VERIFY_PARAM_set_time GRPC_SHADOW_X509_VERIFY_PARAM_set_time', - '#define X509_VERIFY_PARAM_set_trust GRPC_SHADOW_X509_VERIFY_PARAM_set_trust', - '#define X509_VERIFY_PARAM_table_cleanup GRPC_SHADOW_X509_VERIFY_PARAM_table_cleanup', - '#define X509_CRL_set_issuer_name GRPC_SHADOW_X509_CRL_set_issuer_name', - '#define X509_CRL_set_lastUpdate GRPC_SHADOW_X509_CRL_set_lastUpdate', - '#define X509_CRL_set_nextUpdate GRPC_SHADOW_X509_CRL_set_nextUpdate', - '#define X509_CRL_set_version GRPC_SHADOW_X509_CRL_set_version', - '#define X509_CRL_sort GRPC_SHADOW_X509_CRL_sort', - '#define X509_CRL_up_ref GRPC_SHADOW_X509_CRL_up_ref', - '#define X509_REVOKED_set_revocationDate GRPC_SHADOW_X509_REVOKED_set_revocationDate', - '#define X509_REVOKED_set_serialNumber GRPC_SHADOW_X509_REVOKED_set_serialNumber', - '#define X509_NAME_ENTRY_create_by_NID GRPC_SHADOW_X509_NAME_ENTRY_create_by_NID', - '#define X509_NAME_ENTRY_create_by_OBJ GRPC_SHADOW_X509_NAME_ENTRY_create_by_OBJ', - '#define X509_NAME_ENTRY_create_by_txt GRPC_SHADOW_X509_NAME_ENTRY_create_by_txt', - '#define X509_NAME_ENTRY_get_data GRPC_SHADOW_X509_NAME_ENTRY_get_data', - '#define X509_NAME_ENTRY_get_object GRPC_SHADOW_X509_NAME_ENTRY_get_object', - '#define X509_NAME_ENTRY_set_data GRPC_SHADOW_X509_NAME_ENTRY_set_data', - '#define X509_NAME_ENTRY_set_object GRPC_SHADOW_X509_NAME_ENTRY_set_object', - '#define X509_NAME_add_entry GRPC_SHADOW_X509_NAME_add_entry', - '#define X509_NAME_add_entry_by_NID GRPC_SHADOW_X509_NAME_add_entry_by_NID', - '#define X509_NAME_add_entry_by_OBJ GRPC_SHADOW_X509_NAME_add_entry_by_OBJ', - '#define X509_NAME_add_entry_by_txt GRPC_SHADOW_X509_NAME_add_entry_by_txt', - '#define X509_NAME_delete_entry GRPC_SHADOW_X509_NAME_delete_entry', - '#define X509_NAME_entry_count GRPC_SHADOW_X509_NAME_entry_count', - '#define X509_NAME_get_entry GRPC_SHADOW_X509_NAME_get_entry', - '#define X509_NAME_get_index_by_NID GRPC_SHADOW_X509_NAME_get_index_by_NID', - '#define X509_NAME_get_index_by_OBJ GRPC_SHADOW_X509_NAME_get_index_by_OBJ', - '#define X509_NAME_get_text_by_NID GRPC_SHADOW_X509_NAME_get_text_by_NID', - '#define X509_NAME_get_text_by_OBJ GRPC_SHADOW_X509_NAME_get_text_by_OBJ', - '#define X509_REQ_set_pubkey GRPC_SHADOW_X509_REQ_set_pubkey', - '#define X509_REQ_set_subject_name GRPC_SHADOW_X509_REQ_set_subject_name', - '#define X509_REQ_set_version GRPC_SHADOW_X509_REQ_set_version', - '#define NETSCAPE_SPKI_b64_decode GRPC_SHADOW_NETSCAPE_SPKI_b64_decode', - '#define NETSCAPE_SPKI_b64_encode GRPC_SHADOW_NETSCAPE_SPKI_b64_encode', - '#define NETSCAPE_SPKI_get_pubkey GRPC_SHADOW_NETSCAPE_SPKI_get_pubkey', - '#define NETSCAPE_SPKI_set_pubkey GRPC_SHADOW_NETSCAPE_SPKI_set_pubkey', - '#define X509_ALGORS_it GRPC_SHADOW_X509_ALGORS_it', - '#define X509_ALGOR_cmp GRPC_SHADOW_X509_ALGOR_cmp', - '#define X509_ALGOR_dup GRPC_SHADOW_X509_ALGOR_dup', - '#define X509_ALGOR_free GRPC_SHADOW_X509_ALGOR_free', - '#define X509_ALGOR_get0 GRPC_SHADOW_X509_ALGOR_get0', - '#define X509_ALGOR_it GRPC_SHADOW_X509_ALGOR_it', - '#define X509_ALGOR_new GRPC_SHADOW_X509_ALGOR_new', - '#define X509_ALGOR_set0 GRPC_SHADOW_X509_ALGOR_set0', - '#define X509_ALGOR_set_md GRPC_SHADOW_X509_ALGOR_set_md', - '#define d2i_X509_ALGOR GRPC_SHADOW_d2i_X509_ALGOR', - '#define d2i_X509_ALGORS GRPC_SHADOW_d2i_X509_ALGORS', - '#define i2d_X509_ALGOR GRPC_SHADOW_i2d_X509_ALGOR', - '#define i2d_X509_ALGORS GRPC_SHADOW_i2d_X509_ALGORS', - '#define NETSCAPE_SPKI_sign GRPC_SHADOW_NETSCAPE_SPKI_sign', - '#define NETSCAPE_SPKI_verify GRPC_SHADOW_NETSCAPE_SPKI_verify', - '#define X509_CRL_digest GRPC_SHADOW_X509_CRL_digest', - '#define X509_CRL_sign GRPC_SHADOW_X509_CRL_sign', - '#define X509_CRL_sign_ctx GRPC_SHADOW_X509_CRL_sign_ctx', - '#define X509_NAME_digest GRPC_SHADOW_X509_NAME_digest', - '#define X509_REQ_digest GRPC_SHADOW_X509_REQ_digest', - '#define X509_REQ_sign GRPC_SHADOW_X509_REQ_sign', - '#define X509_REQ_sign_ctx GRPC_SHADOW_X509_REQ_sign_ctx', - '#define X509_REQ_verify GRPC_SHADOW_X509_REQ_verify', - '#define X509_digest GRPC_SHADOW_X509_digest', - '#define X509_pubkey_digest GRPC_SHADOW_X509_pubkey_digest', - '#define X509_sign GRPC_SHADOW_X509_sign', - '#define X509_sign_ctx GRPC_SHADOW_X509_sign_ctx', - '#define X509_verify GRPC_SHADOW_X509_verify', - '#define d2i_DSAPrivateKey_bio GRPC_SHADOW_d2i_DSAPrivateKey_bio', - '#define d2i_DSAPrivateKey_fp GRPC_SHADOW_d2i_DSAPrivateKey_fp', - '#define d2i_DSA_PUBKEY_bio GRPC_SHADOW_d2i_DSA_PUBKEY_bio', - '#define d2i_DSA_PUBKEY_fp GRPC_SHADOW_d2i_DSA_PUBKEY_fp', - '#define d2i_ECPrivateKey_bio GRPC_SHADOW_d2i_ECPrivateKey_bio', - '#define d2i_ECPrivateKey_fp GRPC_SHADOW_d2i_ECPrivateKey_fp', - '#define d2i_EC_PUBKEY_bio GRPC_SHADOW_d2i_EC_PUBKEY_bio', - '#define d2i_EC_PUBKEY_fp GRPC_SHADOW_d2i_EC_PUBKEY_fp', - '#define d2i_PKCS8_PRIV_KEY_INFO_bio GRPC_SHADOW_d2i_PKCS8_PRIV_KEY_INFO_bio', - '#define d2i_PKCS8_PRIV_KEY_INFO_fp GRPC_SHADOW_d2i_PKCS8_PRIV_KEY_INFO_fp', - '#define d2i_PKCS8_bio GRPC_SHADOW_d2i_PKCS8_bio', - '#define d2i_PKCS8_fp GRPC_SHADOW_d2i_PKCS8_fp', - '#define d2i_PUBKEY_bio GRPC_SHADOW_d2i_PUBKEY_bio', - '#define d2i_PUBKEY_fp GRPC_SHADOW_d2i_PUBKEY_fp', - '#define d2i_PrivateKey_bio GRPC_SHADOW_d2i_PrivateKey_bio', - '#define d2i_PrivateKey_fp GRPC_SHADOW_d2i_PrivateKey_fp', - '#define d2i_RSAPrivateKey_bio GRPC_SHADOW_d2i_RSAPrivateKey_bio', - '#define d2i_RSAPrivateKey_fp GRPC_SHADOW_d2i_RSAPrivateKey_fp', - '#define d2i_RSAPublicKey_bio GRPC_SHADOW_d2i_RSAPublicKey_bio', - '#define d2i_RSAPublicKey_fp GRPC_SHADOW_d2i_RSAPublicKey_fp', - '#define d2i_RSA_PUBKEY_bio GRPC_SHADOW_d2i_RSA_PUBKEY_bio', - '#define d2i_RSA_PUBKEY_fp GRPC_SHADOW_d2i_RSA_PUBKEY_fp', - '#define d2i_X509_CRL_bio GRPC_SHADOW_d2i_X509_CRL_bio', - '#define d2i_X509_CRL_fp GRPC_SHADOW_d2i_X509_CRL_fp', - '#define d2i_X509_REQ_bio GRPC_SHADOW_d2i_X509_REQ_bio', - '#define d2i_X509_REQ_fp GRPC_SHADOW_d2i_X509_REQ_fp', - '#define d2i_X509_bio GRPC_SHADOW_d2i_X509_bio', - '#define d2i_X509_fp GRPC_SHADOW_d2i_X509_fp', - '#define i2d_DSAPrivateKey_bio GRPC_SHADOW_i2d_DSAPrivateKey_bio', - '#define i2d_DSAPrivateKey_fp GRPC_SHADOW_i2d_DSAPrivateKey_fp', - '#define i2d_DSA_PUBKEY_bio GRPC_SHADOW_i2d_DSA_PUBKEY_bio', - '#define i2d_DSA_PUBKEY_fp GRPC_SHADOW_i2d_DSA_PUBKEY_fp', - '#define i2d_ECPrivateKey_bio GRPC_SHADOW_i2d_ECPrivateKey_bio', - '#define i2d_ECPrivateKey_fp GRPC_SHADOW_i2d_ECPrivateKey_fp', - '#define i2d_EC_PUBKEY_bio GRPC_SHADOW_i2d_EC_PUBKEY_bio', - '#define i2d_EC_PUBKEY_fp GRPC_SHADOW_i2d_EC_PUBKEY_fp', - '#define i2d_PKCS8PrivateKeyInfo_bio GRPC_SHADOW_i2d_PKCS8PrivateKeyInfo_bio', - '#define i2d_PKCS8PrivateKeyInfo_fp GRPC_SHADOW_i2d_PKCS8PrivateKeyInfo_fp', - '#define i2d_PKCS8_PRIV_KEY_INFO_bio GRPC_SHADOW_i2d_PKCS8_PRIV_KEY_INFO_bio', - '#define i2d_PKCS8_PRIV_KEY_INFO_fp GRPC_SHADOW_i2d_PKCS8_PRIV_KEY_INFO_fp', - '#define i2d_PKCS8_bio GRPC_SHADOW_i2d_PKCS8_bio', - '#define i2d_PKCS8_fp GRPC_SHADOW_i2d_PKCS8_fp', - '#define i2d_PUBKEY_bio GRPC_SHADOW_i2d_PUBKEY_bio', - '#define i2d_PUBKEY_fp GRPC_SHADOW_i2d_PUBKEY_fp', - '#define i2d_PrivateKey_bio GRPC_SHADOW_i2d_PrivateKey_bio', - '#define i2d_PrivateKey_fp GRPC_SHADOW_i2d_PrivateKey_fp', - '#define i2d_RSAPrivateKey_bio GRPC_SHADOW_i2d_RSAPrivateKey_bio', - '#define i2d_RSAPrivateKey_fp GRPC_SHADOW_i2d_RSAPrivateKey_fp', - '#define i2d_RSAPublicKey_bio GRPC_SHADOW_i2d_RSAPublicKey_bio', - '#define i2d_RSAPublicKey_fp GRPC_SHADOW_i2d_RSAPublicKey_fp', - '#define i2d_RSA_PUBKEY_bio GRPC_SHADOW_i2d_RSA_PUBKEY_bio', - '#define i2d_RSA_PUBKEY_fp GRPC_SHADOW_i2d_RSA_PUBKEY_fp', - '#define i2d_X509_CRL_bio GRPC_SHADOW_i2d_X509_CRL_bio', - '#define i2d_X509_CRL_fp GRPC_SHADOW_i2d_X509_CRL_fp', - '#define i2d_X509_REQ_bio GRPC_SHADOW_i2d_X509_REQ_bio', - '#define i2d_X509_REQ_fp GRPC_SHADOW_i2d_X509_REQ_fp', - '#define i2d_X509_bio GRPC_SHADOW_i2d_X509_bio', - '#define i2d_X509_fp GRPC_SHADOW_i2d_X509_fp', - '#define X509_ATTRIBUTE_SET_it GRPC_SHADOW_X509_ATTRIBUTE_SET_it', - '#define X509_ATTRIBUTE_create GRPC_SHADOW_X509_ATTRIBUTE_create', - '#define X509_ATTRIBUTE_dup GRPC_SHADOW_X509_ATTRIBUTE_dup', - '#define X509_ATTRIBUTE_free GRPC_SHADOW_X509_ATTRIBUTE_free', - '#define X509_ATTRIBUTE_it GRPC_SHADOW_X509_ATTRIBUTE_it', - '#define X509_ATTRIBUTE_new GRPC_SHADOW_X509_ATTRIBUTE_new', - '#define d2i_X509_ATTRIBUTE GRPC_SHADOW_d2i_X509_ATTRIBUTE', - '#define i2d_X509_ATTRIBUTE GRPC_SHADOW_i2d_X509_ATTRIBUTE', - '#define X509_CRL_INFO_free GRPC_SHADOW_X509_CRL_INFO_free', - '#define X509_CRL_INFO_it GRPC_SHADOW_X509_CRL_INFO_it', - '#define X509_CRL_INFO_new GRPC_SHADOW_X509_CRL_INFO_new', - '#define X509_CRL_METHOD_free GRPC_SHADOW_X509_CRL_METHOD_free', - '#define X509_CRL_METHOD_new GRPC_SHADOW_X509_CRL_METHOD_new', - '#define X509_CRL_add0_revoked GRPC_SHADOW_X509_CRL_add0_revoked', - '#define X509_CRL_dup GRPC_SHADOW_X509_CRL_dup', - '#define X509_CRL_free GRPC_SHADOW_X509_CRL_free', - '#define X509_CRL_get0_by_cert GRPC_SHADOW_X509_CRL_get0_by_cert', - '#define X509_CRL_get0_by_serial GRPC_SHADOW_X509_CRL_get0_by_serial', - '#define X509_CRL_get_meth_data GRPC_SHADOW_X509_CRL_get_meth_data', - '#define X509_CRL_it GRPC_SHADOW_X509_CRL_it', - '#define X509_CRL_new GRPC_SHADOW_X509_CRL_new', - '#define X509_CRL_set_default_method GRPC_SHADOW_X509_CRL_set_default_method', - '#define X509_CRL_set_meth_data GRPC_SHADOW_X509_CRL_set_meth_data', - '#define X509_CRL_verify GRPC_SHADOW_X509_CRL_verify', - '#define X509_REVOKED_dup GRPC_SHADOW_X509_REVOKED_dup', - '#define X509_REVOKED_free GRPC_SHADOW_X509_REVOKED_free', - '#define X509_REVOKED_it GRPC_SHADOW_X509_REVOKED_it', - '#define X509_REVOKED_new GRPC_SHADOW_X509_REVOKED_new', - '#define d2i_X509_CRL GRPC_SHADOW_d2i_X509_CRL', - '#define d2i_X509_CRL_INFO GRPC_SHADOW_d2i_X509_CRL_INFO', - '#define d2i_X509_REVOKED GRPC_SHADOW_d2i_X509_REVOKED', - '#define i2d_X509_CRL GRPC_SHADOW_i2d_X509_CRL', - '#define i2d_X509_CRL_INFO GRPC_SHADOW_i2d_X509_CRL_INFO', - '#define i2d_X509_REVOKED GRPC_SHADOW_i2d_X509_REVOKED', - '#define X509_EXTENSIONS_it GRPC_SHADOW_X509_EXTENSIONS_it', - '#define X509_EXTENSION_dup GRPC_SHADOW_X509_EXTENSION_dup', - '#define X509_EXTENSION_free GRPC_SHADOW_X509_EXTENSION_free', - '#define X509_EXTENSION_it GRPC_SHADOW_X509_EXTENSION_it', - '#define X509_EXTENSION_new GRPC_SHADOW_X509_EXTENSION_new', - '#define d2i_X509_EXTENSION GRPC_SHADOW_d2i_X509_EXTENSION', - '#define d2i_X509_EXTENSIONS GRPC_SHADOW_d2i_X509_EXTENSIONS', - '#define i2d_X509_EXTENSION GRPC_SHADOW_i2d_X509_EXTENSION', - '#define i2d_X509_EXTENSIONS GRPC_SHADOW_i2d_X509_EXTENSIONS', - '#define X509_INFO_free GRPC_SHADOW_X509_INFO_free', - '#define X509_INFO_new GRPC_SHADOW_X509_INFO_new', - '#define X509_NAME_ENTRIES_it GRPC_SHADOW_X509_NAME_ENTRIES_it', - '#define X509_NAME_ENTRY_dup GRPC_SHADOW_X509_NAME_ENTRY_dup', - '#define X509_NAME_ENTRY_free GRPC_SHADOW_X509_NAME_ENTRY_free', - '#define X509_NAME_ENTRY_it GRPC_SHADOW_X509_NAME_ENTRY_it', - '#define X509_NAME_ENTRY_new GRPC_SHADOW_X509_NAME_ENTRY_new', - '#define X509_NAME_ENTRY_set GRPC_SHADOW_X509_NAME_ENTRY_set', - '#define X509_NAME_INTERNAL_it GRPC_SHADOW_X509_NAME_INTERNAL_it', - '#define X509_NAME_dup GRPC_SHADOW_X509_NAME_dup', - '#define X509_NAME_free GRPC_SHADOW_X509_NAME_free', - '#define X509_NAME_get0_der GRPC_SHADOW_X509_NAME_get0_der', - '#define X509_NAME_it GRPC_SHADOW_X509_NAME_it', - '#define X509_NAME_new GRPC_SHADOW_X509_NAME_new', - '#define X509_NAME_set GRPC_SHADOW_X509_NAME_set', - '#define d2i_X509_NAME GRPC_SHADOW_d2i_X509_NAME', - '#define d2i_X509_NAME_ENTRY GRPC_SHADOW_d2i_X509_NAME_ENTRY', - '#define i2d_X509_NAME GRPC_SHADOW_i2d_X509_NAME', - '#define i2d_X509_NAME_ENTRY GRPC_SHADOW_i2d_X509_NAME_ENTRY', - '#define X509_PKEY_free GRPC_SHADOW_X509_PKEY_free', - '#define X509_PKEY_new GRPC_SHADOW_X509_PKEY_new', - '#define X509_PUBKEY_free GRPC_SHADOW_X509_PUBKEY_free', - '#define X509_PUBKEY_get GRPC_SHADOW_X509_PUBKEY_get', - '#define X509_PUBKEY_get0_param GRPC_SHADOW_X509_PUBKEY_get0_param', - '#define X509_PUBKEY_it GRPC_SHADOW_X509_PUBKEY_it', - '#define X509_PUBKEY_new GRPC_SHADOW_X509_PUBKEY_new', - '#define X509_PUBKEY_set GRPC_SHADOW_X509_PUBKEY_set', - '#define X509_PUBKEY_set0_param GRPC_SHADOW_X509_PUBKEY_set0_param', - '#define d2i_DSA_PUBKEY GRPC_SHADOW_d2i_DSA_PUBKEY', - '#define d2i_EC_PUBKEY GRPC_SHADOW_d2i_EC_PUBKEY', - '#define d2i_PUBKEY GRPC_SHADOW_d2i_PUBKEY', - '#define d2i_RSA_PUBKEY GRPC_SHADOW_d2i_RSA_PUBKEY', - '#define d2i_X509_PUBKEY GRPC_SHADOW_d2i_X509_PUBKEY', - '#define i2d_DSA_PUBKEY GRPC_SHADOW_i2d_DSA_PUBKEY', - '#define i2d_EC_PUBKEY GRPC_SHADOW_i2d_EC_PUBKEY', - '#define i2d_PUBKEY GRPC_SHADOW_i2d_PUBKEY', - '#define i2d_RSA_PUBKEY GRPC_SHADOW_i2d_RSA_PUBKEY', - '#define i2d_X509_PUBKEY GRPC_SHADOW_i2d_X509_PUBKEY', - '#define X509_REQ_INFO_free GRPC_SHADOW_X509_REQ_INFO_free', - '#define X509_REQ_INFO_it GRPC_SHADOW_X509_REQ_INFO_it', - '#define X509_REQ_INFO_new GRPC_SHADOW_X509_REQ_INFO_new', - '#define X509_REQ_dup GRPC_SHADOW_X509_REQ_dup', - '#define X509_REQ_free GRPC_SHADOW_X509_REQ_free', - '#define X509_REQ_it GRPC_SHADOW_X509_REQ_it', - '#define X509_REQ_new GRPC_SHADOW_X509_REQ_new', - '#define d2i_X509_REQ GRPC_SHADOW_d2i_X509_REQ', - '#define d2i_X509_REQ_INFO GRPC_SHADOW_d2i_X509_REQ_INFO', - '#define i2d_X509_REQ GRPC_SHADOW_i2d_X509_REQ', - '#define i2d_X509_REQ_INFO GRPC_SHADOW_i2d_X509_REQ_INFO', - '#define X509_SIG_free GRPC_SHADOW_X509_SIG_free', - '#define X509_SIG_it GRPC_SHADOW_X509_SIG_it', - '#define X509_SIG_new GRPC_SHADOW_X509_SIG_new', - '#define d2i_X509_SIG GRPC_SHADOW_d2i_X509_SIG', - '#define i2d_X509_SIG GRPC_SHADOW_i2d_X509_SIG', - '#define NETSCAPE_SPKAC_free GRPC_SHADOW_NETSCAPE_SPKAC_free', - '#define NETSCAPE_SPKAC_it GRPC_SHADOW_NETSCAPE_SPKAC_it', - '#define NETSCAPE_SPKAC_new GRPC_SHADOW_NETSCAPE_SPKAC_new', - '#define NETSCAPE_SPKI_free GRPC_SHADOW_NETSCAPE_SPKI_free', - '#define NETSCAPE_SPKI_it GRPC_SHADOW_NETSCAPE_SPKI_it', - '#define NETSCAPE_SPKI_new GRPC_SHADOW_NETSCAPE_SPKI_new', - '#define d2i_NETSCAPE_SPKAC GRPC_SHADOW_d2i_NETSCAPE_SPKAC', - '#define d2i_NETSCAPE_SPKI GRPC_SHADOW_d2i_NETSCAPE_SPKI', - '#define i2d_NETSCAPE_SPKAC GRPC_SHADOW_i2d_NETSCAPE_SPKAC', - '#define i2d_NETSCAPE_SPKI GRPC_SHADOW_i2d_NETSCAPE_SPKI', - '#define X509_VAL_free GRPC_SHADOW_X509_VAL_free', - '#define X509_VAL_it GRPC_SHADOW_X509_VAL_it', - '#define X509_VAL_new GRPC_SHADOW_X509_VAL_new', - '#define d2i_X509_VAL GRPC_SHADOW_d2i_X509_VAL', - '#define i2d_X509_VAL GRPC_SHADOW_i2d_X509_VAL', - '#define X509_CINF_free GRPC_SHADOW_X509_CINF_free', - '#define X509_CINF_it GRPC_SHADOW_X509_CINF_it', - '#define X509_CINF_new GRPC_SHADOW_X509_CINF_new', - '#define X509_dup GRPC_SHADOW_X509_dup', - '#define X509_free GRPC_SHADOW_X509_free', - '#define X509_get0_signature GRPC_SHADOW_X509_get0_signature', - '#define X509_get_ex_data GRPC_SHADOW_X509_get_ex_data', - '#define X509_get_ex_new_index GRPC_SHADOW_X509_get_ex_new_index', - '#define X509_get_signature_nid GRPC_SHADOW_X509_get_signature_nid', - '#define X509_it GRPC_SHADOW_X509_it', - '#define X509_new GRPC_SHADOW_X509_new', - '#define X509_parse_from_buffer GRPC_SHADOW_X509_parse_from_buffer', - '#define X509_set_ex_data GRPC_SHADOW_X509_set_ex_data', - '#define X509_up_ref GRPC_SHADOW_X509_up_ref', - '#define d2i_X509 GRPC_SHADOW_d2i_X509', - '#define d2i_X509_AUX GRPC_SHADOW_d2i_X509_AUX', - '#define d2i_X509_CINF GRPC_SHADOW_d2i_X509_CINF', - '#define i2d_X509 GRPC_SHADOW_i2d_X509', - '#define i2d_X509_AUX GRPC_SHADOW_i2d_X509_AUX', - '#define i2d_X509_CINF GRPC_SHADOW_i2d_X509_CINF', - '#define X509_CERT_AUX_free GRPC_SHADOW_X509_CERT_AUX_free', - '#define X509_CERT_AUX_it GRPC_SHADOW_X509_CERT_AUX_it', - '#define X509_CERT_AUX_new GRPC_SHADOW_X509_CERT_AUX_new', - '#define X509_add1_reject_object GRPC_SHADOW_X509_add1_reject_object', - '#define X509_add1_trust_object GRPC_SHADOW_X509_add1_trust_object', - '#define X509_alias_get0 GRPC_SHADOW_X509_alias_get0', - '#define X509_alias_set1 GRPC_SHADOW_X509_alias_set1', - '#define X509_keyid_get0 GRPC_SHADOW_X509_keyid_get0', - '#define X509_keyid_set1 GRPC_SHADOW_X509_keyid_set1', - '#define X509_reject_clear GRPC_SHADOW_X509_reject_clear', - '#define X509_trust_clear GRPC_SHADOW_X509_trust_clear', - '#define d2i_X509_CERT_AUX GRPC_SHADOW_d2i_X509_CERT_AUX', - '#define i2d_X509_CERT_AUX GRPC_SHADOW_i2d_X509_CERT_AUX', - '#define policy_cache_find_data GRPC_SHADOW_policy_cache_find_data', - '#define policy_cache_free GRPC_SHADOW_policy_cache_free', - '#define policy_cache_set GRPC_SHADOW_policy_cache_set', - '#define policy_data_free GRPC_SHADOW_policy_data_free', - '#define policy_data_new GRPC_SHADOW_policy_data_new', - '#define X509_policy_level_get0_node GRPC_SHADOW_X509_policy_level_get0_node', - '#define X509_policy_level_node_count GRPC_SHADOW_X509_policy_level_node_count', - '#define X509_policy_node_get0_parent GRPC_SHADOW_X509_policy_node_get0_parent', - '#define X509_policy_node_get0_policy GRPC_SHADOW_X509_policy_node_get0_policy', - '#define X509_policy_node_get0_qualifiers GRPC_SHADOW_X509_policy_node_get0_qualifiers', - '#define X509_policy_tree_get0_level GRPC_SHADOW_X509_policy_tree_get0_level', - '#define X509_policy_tree_get0_policies GRPC_SHADOW_X509_policy_tree_get0_policies', - '#define X509_policy_tree_get0_user_policies GRPC_SHADOW_X509_policy_tree_get0_user_policies', - '#define X509_policy_tree_level_count GRPC_SHADOW_X509_policy_tree_level_count', - '#define policy_cache_set_mapping GRPC_SHADOW_policy_cache_set_mapping', - '#define level_add_node GRPC_SHADOW_level_add_node', - '#define level_find_node GRPC_SHADOW_level_find_node', - '#define policy_node_cmp_new GRPC_SHADOW_policy_node_cmp_new', - '#define policy_node_free GRPC_SHADOW_policy_node_free', - '#define policy_node_match GRPC_SHADOW_policy_node_match', - '#define tree_find_sk GRPC_SHADOW_tree_find_sk', - '#define X509_policy_check GRPC_SHADOW_X509_policy_check', - '#define X509_policy_tree_free GRPC_SHADOW_X509_policy_tree_free', - '#define v3_akey_id GRPC_SHADOW_v3_akey_id', - '#define AUTHORITY_KEYID_free GRPC_SHADOW_AUTHORITY_KEYID_free', - '#define AUTHORITY_KEYID_it GRPC_SHADOW_AUTHORITY_KEYID_it', - '#define AUTHORITY_KEYID_new GRPC_SHADOW_AUTHORITY_KEYID_new', - '#define d2i_AUTHORITY_KEYID GRPC_SHADOW_d2i_AUTHORITY_KEYID', - '#define i2d_AUTHORITY_KEYID GRPC_SHADOW_i2d_AUTHORITY_KEYID', - '#define GENERAL_NAME_print GRPC_SHADOW_GENERAL_NAME_print', - '#define a2i_GENERAL_NAME GRPC_SHADOW_a2i_GENERAL_NAME', - '#define i2v_GENERAL_NAME GRPC_SHADOW_i2v_GENERAL_NAME', - '#define i2v_GENERAL_NAMES GRPC_SHADOW_i2v_GENERAL_NAMES', - '#define v2i_GENERAL_NAME GRPC_SHADOW_v2i_GENERAL_NAME', - '#define v2i_GENERAL_NAMES GRPC_SHADOW_v2i_GENERAL_NAMES', - '#define v2i_GENERAL_NAME_ex GRPC_SHADOW_v2i_GENERAL_NAME_ex', - '#define v3_alt GRPC_SHADOW_v3_alt', - '#define BASIC_CONSTRAINTS_free GRPC_SHADOW_BASIC_CONSTRAINTS_free', - '#define BASIC_CONSTRAINTS_it GRPC_SHADOW_BASIC_CONSTRAINTS_it', - '#define BASIC_CONSTRAINTS_new GRPC_SHADOW_BASIC_CONSTRAINTS_new', - '#define d2i_BASIC_CONSTRAINTS GRPC_SHADOW_d2i_BASIC_CONSTRAINTS', - '#define i2d_BASIC_CONSTRAINTS GRPC_SHADOW_i2d_BASIC_CONSTRAINTS', - '#define v3_bcons GRPC_SHADOW_v3_bcons', - '#define i2v_ASN1_BIT_STRING GRPC_SHADOW_i2v_ASN1_BIT_STRING', - '#define v2i_ASN1_BIT_STRING GRPC_SHADOW_v2i_ASN1_BIT_STRING', - '#define v3_key_usage GRPC_SHADOW_v3_key_usage', - '#define v3_nscert GRPC_SHADOW_v3_nscert', - '#define X509V3_EXT_CRL_add_nconf GRPC_SHADOW_X509V3_EXT_CRL_add_nconf', - '#define X509V3_EXT_REQ_add_nconf GRPC_SHADOW_X509V3_EXT_REQ_add_nconf', - '#define X509V3_EXT_add_nconf GRPC_SHADOW_X509V3_EXT_add_nconf', - '#define X509V3_EXT_add_nconf_sk GRPC_SHADOW_X509V3_EXT_add_nconf_sk', - '#define X509V3_EXT_i2d GRPC_SHADOW_X509V3_EXT_i2d', - '#define X509V3_EXT_nconf GRPC_SHADOW_X509V3_EXT_nconf', - '#define X509V3_EXT_nconf_nid GRPC_SHADOW_X509V3_EXT_nconf_nid', - '#define X509V3_get_section GRPC_SHADOW_X509V3_get_section', - '#define X509V3_get_string GRPC_SHADOW_X509V3_get_string', - '#define X509V3_section_free GRPC_SHADOW_X509V3_section_free', - '#define X509V3_set_ctx GRPC_SHADOW_X509V3_set_ctx', - '#define X509V3_set_nconf GRPC_SHADOW_X509V3_set_nconf', - '#define X509V3_string_free GRPC_SHADOW_X509V3_string_free', - '#define CERTIFICATEPOLICIES_free GRPC_SHADOW_CERTIFICATEPOLICIES_free', - '#define CERTIFICATEPOLICIES_it GRPC_SHADOW_CERTIFICATEPOLICIES_it', - '#define CERTIFICATEPOLICIES_new GRPC_SHADOW_CERTIFICATEPOLICIES_new', - '#define NOTICEREF_free GRPC_SHADOW_NOTICEREF_free', - '#define NOTICEREF_it GRPC_SHADOW_NOTICEREF_it', - '#define NOTICEREF_new GRPC_SHADOW_NOTICEREF_new', - '#define POLICYINFO_free GRPC_SHADOW_POLICYINFO_free', - '#define POLICYINFO_it GRPC_SHADOW_POLICYINFO_it', - '#define POLICYINFO_new GRPC_SHADOW_POLICYINFO_new', - '#define POLICYQUALINFO_free GRPC_SHADOW_POLICYQUALINFO_free', - '#define POLICYQUALINFO_it GRPC_SHADOW_POLICYQUALINFO_it', - '#define POLICYQUALINFO_new GRPC_SHADOW_POLICYQUALINFO_new', - '#define USERNOTICE_free GRPC_SHADOW_USERNOTICE_free', - '#define USERNOTICE_it GRPC_SHADOW_USERNOTICE_it', - '#define USERNOTICE_new GRPC_SHADOW_USERNOTICE_new', - '#define X509_POLICY_NODE_print GRPC_SHADOW_X509_POLICY_NODE_print', - '#define d2i_CERTIFICATEPOLICIES GRPC_SHADOW_d2i_CERTIFICATEPOLICIES', - '#define d2i_NOTICEREF GRPC_SHADOW_d2i_NOTICEREF', - '#define d2i_POLICYINFO GRPC_SHADOW_d2i_POLICYINFO', - '#define d2i_POLICYQUALINFO GRPC_SHADOW_d2i_POLICYQUALINFO', - '#define d2i_USERNOTICE GRPC_SHADOW_d2i_USERNOTICE', - '#define i2d_CERTIFICATEPOLICIES GRPC_SHADOW_i2d_CERTIFICATEPOLICIES', - '#define i2d_NOTICEREF GRPC_SHADOW_i2d_NOTICEREF', - '#define i2d_POLICYINFO GRPC_SHADOW_i2d_POLICYINFO', - '#define i2d_POLICYQUALINFO GRPC_SHADOW_i2d_POLICYQUALINFO', - '#define i2d_USERNOTICE GRPC_SHADOW_i2d_USERNOTICE', - '#define v3_cpols GRPC_SHADOW_v3_cpols', - '#define CRL_DIST_POINTS_free GRPC_SHADOW_CRL_DIST_POINTS_free', - '#define CRL_DIST_POINTS_it GRPC_SHADOW_CRL_DIST_POINTS_it', - '#define CRL_DIST_POINTS_new GRPC_SHADOW_CRL_DIST_POINTS_new', - '#define DIST_POINT_NAME_free GRPC_SHADOW_DIST_POINT_NAME_free', - '#define DIST_POINT_NAME_it GRPC_SHADOW_DIST_POINT_NAME_it', - '#define DIST_POINT_NAME_new GRPC_SHADOW_DIST_POINT_NAME_new', - '#define DIST_POINT_free GRPC_SHADOW_DIST_POINT_free', - '#define DIST_POINT_it GRPC_SHADOW_DIST_POINT_it', - '#define DIST_POINT_new GRPC_SHADOW_DIST_POINT_new', - '#define DIST_POINT_set_dpname GRPC_SHADOW_DIST_POINT_set_dpname', - '#define ISSUING_DIST_POINT_free GRPC_SHADOW_ISSUING_DIST_POINT_free', - '#define ISSUING_DIST_POINT_it GRPC_SHADOW_ISSUING_DIST_POINT_it', - '#define ISSUING_DIST_POINT_new GRPC_SHADOW_ISSUING_DIST_POINT_new', - '#define d2i_CRL_DIST_POINTS GRPC_SHADOW_d2i_CRL_DIST_POINTS', - '#define d2i_DIST_POINT GRPC_SHADOW_d2i_DIST_POINT', - '#define d2i_DIST_POINT_NAME GRPC_SHADOW_d2i_DIST_POINT_NAME', - '#define d2i_ISSUING_DIST_POINT GRPC_SHADOW_d2i_ISSUING_DIST_POINT', - '#define i2d_CRL_DIST_POINTS GRPC_SHADOW_i2d_CRL_DIST_POINTS', - '#define i2d_DIST_POINT GRPC_SHADOW_i2d_DIST_POINT', - '#define i2d_DIST_POINT_NAME GRPC_SHADOW_i2d_DIST_POINT_NAME', - '#define i2d_ISSUING_DIST_POINT GRPC_SHADOW_i2d_ISSUING_DIST_POINT', - '#define v3_crld GRPC_SHADOW_v3_crld', - '#define v3_freshest_crl GRPC_SHADOW_v3_freshest_crl', - '#define v3_idp GRPC_SHADOW_v3_idp', - '#define i2s_ASN1_ENUMERATED_TABLE GRPC_SHADOW_i2s_ASN1_ENUMERATED_TABLE', - '#define v3_crl_reason GRPC_SHADOW_v3_crl_reason', - '#define EXTENDED_KEY_USAGE_free GRPC_SHADOW_EXTENDED_KEY_USAGE_free', - '#define EXTENDED_KEY_USAGE_it GRPC_SHADOW_EXTENDED_KEY_USAGE_it', - '#define EXTENDED_KEY_USAGE_new GRPC_SHADOW_EXTENDED_KEY_USAGE_new', - '#define d2i_EXTENDED_KEY_USAGE GRPC_SHADOW_d2i_EXTENDED_KEY_USAGE', - '#define i2d_EXTENDED_KEY_USAGE GRPC_SHADOW_i2d_EXTENDED_KEY_USAGE', - '#define v3_ext_ku GRPC_SHADOW_v3_ext_ku', - '#define v3_ocsp_accresp GRPC_SHADOW_v3_ocsp_accresp', - '#define EDIPARTYNAME_free GRPC_SHADOW_EDIPARTYNAME_free', - '#define EDIPARTYNAME_it GRPC_SHADOW_EDIPARTYNAME_it', - '#define EDIPARTYNAME_new GRPC_SHADOW_EDIPARTYNAME_new', - '#define GENERAL_NAMES_free GRPC_SHADOW_GENERAL_NAMES_free', - '#define GENERAL_NAMES_it GRPC_SHADOW_GENERAL_NAMES_it', - '#define GENERAL_NAMES_new GRPC_SHADOW_GENERAL_NAMES_new', - '#define GENERAL_NAME_cmp GRPC_SHADOW_GENERAL_NAME_cmp', - '#define GENERAL_NAME_dup GRPC_SHADOW_GENERAL_NAME_dup', - '#define GENERAL_NAME_free GRPC_SHADOW_GENERAL_NAME_free', - '#define GENERAL_NAME_get0_otherName GRPC_SHADOW_GENERAL_NAME_get0_otherName', - '#define GENERAL_NAME_get0_value GRPC_SHADOW_GENERAL_NAME_get0_value', - '#define GENERAL_NAME_it GRPC_SHADOW_GENERAL_NAME_it', - '#define GENERAL_NAME_new GRPC_SHADOW_GENERAL_NAME_new', - '#define GENERAL_NAME_set0_othername GRPC_SHADOW_GENERAL_NAME_set0_othername', - '#define GENERAL_NAME_set0_value GRPC_SHADOW_GENERAL_NAME_set0_value', - '#define OTHERNAME_cmp GRPC_SHADOW_OTHERNAME_cmp', - '#define OTHERNAME_free GRPC_SHADOW_OTHERNAME_free', - '#define OTHERNAME_it GRPC_SHADOW_OTHERNAME_it', - '#define OTHERNAME_new GRPC_SHADOW_OTHERNAME_new', - '#define d2i_EDIPARTYNAME GRPC_SHADOW_d2i_EDIPARTYNAME', - '#define d2i_GENERAL_NAME GRPC_SHADOW_d2i_GENERAL_NAME', - '#define d2i_GENERAL_NAMES GRPC_SHADOW_d2i_GENERAL_NAMES', - '#define d2i_OTHERNAME GRPC_SHADOW_d2i_OTHERNAME', - '#define i2d_EDIPARTYNAME GRPC_SHADOW_i2d_EDIPARTYNAME', - '#define i2d_GENERAL_NAME GRPC_SHADOW_i2d_GENERAL_NAME', - '#define i2d_GENERAL_NAMES GRPC_SHADOW_i2d_GENERAL_NAMES', - '#define i2d_OTHERNAME GRPC_SHADOW_i2d_OTHERNAME', - '#define v3_ns_ia5_list GRPC_SHADOW_v3_ns_ia5_list', - '#define ACCESS_DESCRIPTION_free GRPC_SHADOW_ACCESS_DESCRIPTION_free', - '#define ACCESS_DESCRIPTION_it GRPC_SHADOW_ACCESS_DESCRIPTION_it', - '#define ACCESS_DESCRIPTION_new GRPC_SHADOW_ACCESS_DESCRIPTION_new', - '#define AUTHORITY_INFO_ACCESS_free GRPC_SHADOW_AUTHORITY_INFO_ACCESS_free', - '#define AUTHORITY_INFO_ACCESS_it GRPC_SHADOW_AUTHORITY_INFO_ACCESS_it', - '#define AUTHORITY_INFO_ACCESS_new GRPC_SHADOW_AUTHORITY_INFO_ACCESS_new', - '#define d2i_ACCESS_DESCRIPTION GRPC_SHADOW_d2i_ACCESS_DESCRIPTION', - '#define d2i_AUTHORITY_INFO_ACCESS GRPC_SHADOW_d2i_AUTHORITY_INFO_ACCESS', - '#define i2a_ACCESS_DESCRIPTION GRPC_SHADOW_i2a_ACCESS_DESCRIPTION', - '#define i2d_ACCESS_DESCRIPTION GRPC_SHADOW_i2d_ACCESS_DESCRIPTION', - '#define i2d_AUTHORITY_INFO_ACCESS GRPC_SHADOW_i2d_AUTHORITY_INFO_ACCESS', - '#define v3_info GRPC_SHADOW_v3_info', - '#define v3_sinfo GRPC_SHADOW_v3_sinfo', - '#define v3_crl_num GRPC_SHADOW_v3_crl_num', - '#define v3_delta_crl GRPC_SHADOW_v3_delta_crl', - '#define v3_inhibit_anyp GRPC_SHADOW_v3_inhibit_anyp', - '#define X509V3_EXT_add GRPC_SHADOW_X509V3_EXT_add', - '#define X509V3_EXT_add_alias GRPC_SHADOW_X509V3_EXT_add_alias', - '#define X509V3_EXT_add_list GRPC_SHADOW_X509V3_EXT_add_list', - '#define X509V3_EXT_cleanup GRPC_SHADOW_X509V3_EXT_cleanup', - '#define X509V3_EXT_d2i GRPC_SHADOW_X509V3_EXT_d2i', - '#define X509V3_EXT_free GRPC_SHADOW_X509V3_EXT_free', - '#define X509V3_EXT_get GRPC_SHADOW_X509V3_EXT_get', - '#define X509V3_EXT_get_nid GRPC_SHADOW_X509V3_EXT_get_nid', - '#define X509V3_add1_i2d GRPC_SHADOW_X509V3_add1_i2d', - '#define X509V3_add_standard_extensions GRPC_SHADOW_X509V3_add_standard_extensions', - '#define X509V3_get_d2i GRPC_SHADOW_X509V3_get_d2i', - '#define GENERAL_SUBTREE_free GRPC_SHADOW_GENERAL_SUBTREE_free', - '#define GENERAL_SUBTREE_it GRPC_SHADOW_GENERAL_SUBTREE_it', - '#define GENERAL_SUBTREE_new GRPC_SHADOW_GENERAL_SUBTREE_new', - '#define NAME_CONSTRAINTS_check GRPC_SHADOW_NAME_CONSTRAINTS_check', - '#define NAME_CONSTRAINTS_free GRPC_SHADOW_NAME_CONSTRAINTS_free', - '#define NAME_CONSTRAINTS_it GRPC_SHADOW_NAME_CONSTRAINTS_it', - '#define NAME_CONSTRAINTS_new GRPC_SHADOW_NAME_CONSTRAINTS_new', - '#define v3_name_constraints GRPC_SHADOW_v3_name_constraints', - '#define v3_pci GRPC_SHADOW_v3_pci', - '#define PROXY_CERT_INFO_EXTENSION_free GRPC_SHADOW_PROXY_CERT_INFO_EXTENSION_free', - '#define PROXY_CERT_INFO_EXTENSION_it GRPC_SHADOW_PROXY_CERT_INFO_EXTENSION_it', - '#define PROXY_CERT_INFO_EXTENSION_new GRPC_SHADOW_PROXY_CERT_INFO_EXTENSION_new', - '#define PROXY_POLICY_free GRPC_SHADOW_PROXY_POLICY_free', - '#define PROXY_POLICY_it GRPC_SHADOW_PROXY_POLICY_it', - '#define PROXY_POLICY_new GRPC_SHADOW_PROXY_POLICY_new', - '#define d2i_PROXY_CERT_INFO_EXTENSION GRPC_SHADOW_d2i_PROXY_CERT_INFO_EXTENSION', - '#define d2i_PROXY_POLICY GRPC_SHADOW_d2i_PROXY_POLICY', - '#define i2d_PROXY_CERT_INFO_EXTENSION GRPC_SHADOW_i2d_PROXY_CERT_INFO_EXTENSION', - '#define i2d_PROXY_POLICY GRPC_SHADOW_i2d_PROXY_POLICY', - '#define POLICY_CONSTRAINTS_free GRPC_SHADOW_POLICY_CONSTRAINTS_free', - '#define POLICY_CONSTRAINTS_it GRPC_SHADOW_POLICY_CONSTRAINTS_it', - '#define POLICY_CONSTRAINTS_new GRPC_SHADOW_POLICY_CONSTRAINTS_new', - '#define v3_policy_constraints GRPC_SHADOW_v3_policy_constraints', - '#define PKEY_USAGE_PERIOD_free GRPC_SHADOW_PKEY_USAGE_PERIOD_free', - '#define PKEY_USAGE_PERIOD_it GRPC_SHADOW_PKEY_USAGE_PERIOD_it', - '#define PKEY_USAGE_PERIOD_new GRPC_SHADOW_PKEY_USAGE_PERIOD_new', - '#define d2i_PKEY_USAGE_PERIOD GRPC_SHADOW_d2i_PKEY_USAGE_PERIOD', - '#define i2d_PKEY_USAGE_PERIOD GRPC_SHADOW_i2d_PKEY_USAGE_PERIOD', - '#define v3_pkey_usage_period GRPC_SHADOW_v3_pkey_usage_period', - '#define POLICY_MAPPINGS_it GRPC_SHADOW_POLICY_MAPPINGS_it', - '#define POLICY_MAPPING_free GRPC_SHADOW_POLICY_MAPPING_free', - '#define POLICY_MAPPING_it GRPC_SHADOW_POLICY_MAPPING_it', - '#define POLICY_MAPPING_new GRPC_SHADOW_POLICY_MAPPING_new', - '#define v3_policy_mappings GRPC_SHADOW_v3_policy_mappings', - '#define X509V3_EXT_print GRPC_SHADOW_X509V3_EXT_print', - '#define X509V3_EXT_print_fp GRPC_SHADOW_X509V3_EXT_print_fp', - '#define X509V3_EXT_val_prn GRPC_SHADOW_X509V3_EXT_val_prn', - '#define X509V3_extensions_print GRPC_SHADOW_X509V3_extensions_print', - '#define X509_PURPOSE_add GRPC_SHADOW_X509_PURPOSE_add', - '#define X509_PURPOSE_cleanup GRPC_SHADOW_X509_PURPOSE_cleanup', - '#define X509_PURPOSE_get0 GRPC_SHADOW_X509_PURPOSE_get0', - '#define X509_PURPOSE_get0_name GRPC_SHADOW_X509_PURPOSE_get0_name', - '#define X509_PURPOSE_get0_sname GRPC_SHADOW_X509_PURPOSE_get0_sname', - '#define X509_PURPOSE_get_by_id GRPC_SHADOW_X509_PURPOSE_get_by_id', - '#define X509_PURPOSE_get_by_sname GRPC_SHADOW_X509_PURPOSE_get_by_sname', - '#define X509_PURPOSE_get_count GRPC_SHADOW_X509_PURPOSE_get_count', - '#define X509_PURPOSE_get_id GRPC_SHADOW_X509_PURPOSE_get_id', - '#define X509_PURPOSE_get_trust GRPC_SHADOW_X509_PURPOSE_get_trust', - '#define X509_PURPOSE_set GRPC_SHADOW_X509_PURPOSE_set', - '#define X509_check_akid GRPC_SHADOW_X509_check_akid', - '#define X509_check_ca GRPC_SHADOW_X509_check_ca', - '#define X509_check_issued GRPC_SHADOW_X509_check_issued', - '#define X509_check_purpose GRPC_SHADOW_X509_check_purpose', - '#define X509_supported_extension GRPC_SHADOW_X509_supported_extension', - '#define i2s_ASN1_OCTET_STRING GRPC_SHADOW_i2s_ASN1_OCTET_STRING', - '#define s2i_ASN1_OCTET_STRING GRPC_SHADOW_s2i_ASN1_OCTET_STRING', - '#define v3_skey_id GRPC_SHADOW_v3_skey_id', - '#define SXNETID_free GRPC_SHADOW_SXNETID_free', - '#define SXNETID_it GRPC_SHADOW_SXNETID_it', - '#define SXNETID_new GRPC_SHADOW_SXNETID_new', - '#define SXNET_add_id_INTEGER GRPC_SHADOW_SXNET_add_id_INTEGER', - '#define SXNET_add_id_asc GRPC_SHADOW_SXNET_add_id_asc', - '#define SXNET_add_id_ulong GRPC_SHADOW_SXNET_add_id_ulong', - '#define SXNET_free GRPC_SHADOW_SXNET_free', - '#define SXNET_get_id_INTEGER GRPC_SHADOW_SXNET_get_id_INTEGER', - '#define SXNET_get_id_asc GRPC_SHADOW_SXNET_get_id_asc', - '#define SXNET_get_id_ulong GRPC_SHADOW_SXNET_get_id_ulong', - '#define SXNET_it GRPC_SHADOW_SXNET_it', - '#define SXNET_new GRPC_SHADOW_SXNET_new', - '#define d2i_SXNET GRPC_SHADOW_d2i_SXNET', - '#define d2i_SXNETID GRPC_SHADOW_d2i_SXNETID', - '#define i2d_SXNET GRPC_SHADOW_i2d_SXNET', - '#define i2d_SXNETID GRPC_SHADOW_i2d_SXNETID', - '#define v3_sxnet GRPC_SHADOW_v3_sxnet', - '#define X509V3_NAME_from_section GRPC_SHADOW_X509V3_NAME_from_section', - '#define X509V3_add_value GRPC_SHADOW_X509V3_add_value', - '#define X509V3_add_value_bool GRPC_SHADOW_X509V3_add_value_bool', - '#define X509V3_add_value_bool_nf GRPC_SHADOW_X509V3_add_value_bool_nf', - '#define X509V3_add_value_int GRPC_SHADOW_X509V3_add_value_int', - '#define X509V3_add_value_uchar GRPC_SHADOW_X509V3_add_value_uchar', - '#define X509V3_conf_free GRPC_SHADOW_X509V3_conf_free', - '#define X509V3_get_value_bool GRPC_SHADOW_X509V3_get_value_bool', - '#define X509V3_get_value_int GRPC_SHADOW_X509V3_get_value_int', - '#define X509V3_parse_list GRPC_SHADOW_X509V3_parse_list', - '#define X509_REQ_get1_email GRPC_SHADOW_X509_REQ_get1_email', - '#define X509_check_email GRPC_SHADOW_X509_check_email', - '#define X509_check_host GRPC_SHADOW_X509_check_host', - '#define X509_check_ip GRPC_SHADOW_X509_check_ip', - '#define X509_check_ip_asc GRPC_SHADOW_X509_check_ip_asc', - '#define X509_email_free GRPC_SHADOW_X509_email_free', - '#define X509_get1_email GRPC_SHADOW_X509_get1_email', - '#define X509_get1_ocsp GRPC_SHADOW_X509_get1_ocsp', - '#define a2i_IPADDRESS GRPC_SHADOW_a2i_IPADDRESS', - '#define a2i_IPADDRESS_NC GRPC_SHADOW_a2i_IPADDRESS_NC', - '#define a2i_ipadd GRPC_SHADOW_a2i_ipadd', - '#define hex_to_string GRPC_SHADOW_hex_to_string', - '#define i2s_ASN1_ENUMERATED GRPC_SHADOW_i2s_ASN1_ENUMERATED', - '#define i2s_ASN1_INTEGER GRPC_SHADOW_i2s_ASN1_INTEGER', - '#define name_cmp GRPC_SHADOW_name_cmp', - '#define s2i_ASN1_INTEGER GRPC_SHADOW_s2i_ASN1_INTEGER', - '#define string_to_hex GRPC_SHADOW_string_to_hex', - '#define PKCS7_get_raw_certificates GRPC_SHADOW_PKCS7_get_raw_certificates', - '#define pkcs7_bundle GRPC_SHADOW_pkcs7_bundle', - '#define pkcs7_parse_header GRPC_SHADOW_pkcs7_parse_header', - '#define PKCS7_bundle_CRLs GRPC_SHADOW_PKCS7_bundle_CRLs', - '#define PKCS7_bundle_certificates GRPC_SHADOW_PKCS7_bundle_certificates', - '#define PKCS7_get_CRLs GRPC_SHADOW_PKCS7_get_CRLs', - '#define PKCS7_get_PEM_CRLs GRPC_SHADOW_PKCS7_get_PEM_CRLs', - '#define PKCS7_get_PEM_certificates GRPC_SHADOW_PKCS7_get_PEM_certificates', - '#define PKCS7_get_certificates GRPC_SHADOW_PKCS7_get_certificates', - '#define PKCS8_marshal_encrypted_private_key GRPC_SHADOW_PKCS8_marshal_encrypted_private_key', - '#define PKCS8_parse_encrypted_private_key GRPC_SHADOW_PKCS8_parse_encrypted_private_key', - '#define pkcs12_key_gen GRPC_SHADOW_pkcs12_key_gen', - '#define pkcs8_pbe_decrypt GRPC_SHADOW_pkcs8_pbe_decrypt', - '#define EVP_PKCS82PKEY GRPC_SHADOW_EVP_PKCS82PKEY', - '#define EVP_PKEY2PKCS8 GRPC_SHADOW_EVP_PKEY2PKCS8', - '#define PKCS12_PBE_add GRPC_SHADOW_PKCS12_PBE_add', - '#define PKCS12_free GRPC_SHADOW_PKCS12_free', - '#define PKCS12_get_key_and_certs GRPC_SHADOW_PKCS12_get_key_and_certs', - '#define PKCS12_parse GRPC_SHADOW_PKCS12_parse', - '#define PKCS12_verify_mac GRPC_SHADOW_PKCS12_verify_mac', - '#define PKCS8_PRIV_KEY_INFO_free GRPC_SHADOW_PKCS8_PRIV_KEY_INFO_free', - '#define PKCS8_PRIV_KEY_INFO_it GRPC_SHADOW_PKCS8_PRIV_KEY_INFO_it', - '#define PKCS8_PRIV_KEY_INFO_new GRPC_SHADOW_PKCS8_PRIV_KEY_INFO_new', - '#define PKCS8_decrypt GRPC_SHADOW_PKCS8_decrypt', - '#define PKCS8_encrypt GRPC_SHADOW_PKCS8_encrypt', - '#define d2i_PKCS12 GRPC_SHADOW_d2i_PKCS12', - '#define d2i_PKCS12_bio GRPC_SHADOW_d2i_PKCS12_bio', - '#define d2i_PKCS12_fp GRPC_SHADOW_d2i_PKCS12_fp', - '#define d2i_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_d2i_PKCS8_PRIV_KEY_INFO', - '#define i2d_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_i2d_PKCS8_PRIV_KEY_INFO', - '#define PKCS5_pbe2_decrypt_init GRPC_SHADOW_PKCS5_pbe2_decrypt_init', - '#define PKCS5_pbe2_encrypt_init GRPC_SHADOW_PKCS5_pbe2_encrypt_init' - end + ${expand_symbol_list(settings.grpc_shadow_boringssl_symbols)} + end \ No newline at end of file From 034bfe755255e7c01f3def256b3340c8b415f0d9 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 18 Jan 2019 10:05:37 -0800 Subject: [PATCH 021/218] generate_projects --- src/objective-c/BoringSSL-GRPC.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/BoringSSL-GRPC.podspec b/src/objective-c/BoringSSL-GRPC.podspec index 6ec3747faef..99bb5397aef 100644 --- a/src/objective-c/BoringSSL-GRPC.podspec +++ b/src/objective-c/BoringSSL-GRPC.podspec @@ -4527,4 +4527,4 @@ Pod::Spec.new do |s| '#define i2d_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_i2d_PKCS8_PRIV_KEY_INFO', '#define PKCS5_pbe2_decrypt_init GRPC_SHADOW_PKCS5_pbe2_decrypt_init', '#define PKCS5_pbe2_encrypt_init GRPC_SHADOW_PKCS5_pbe2_encrypt_init' -end +end \ No newline at end of file From d748d9c01d4e5de93c0290401cfd8429dc89ef99 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 18 Jan 2019 21:41:42 +0100 Subject: [PATCH 022/218] Refactor ContextPropagationToken --- src/csharp/Grpc.Core.Tests/CallOptionsTest.cs | 6 +- .../Grpc.Core.Tests/ContextPropagationTest.cs | 2 +- src/csharp/Grpc.Core/CallOptions.cs | 12 +- .../Grpc.Core/ContextPropagationOptions.cs | 59 +++++++++ .../Grpc.Core/ContextPropagationToken.cs | 124 +----------------- src/csharp/Grpc.Core/Internal/AsyncCall.cs | 5 +- .../Internal/ContextPropagationFlags.cs | 34 +++++ .../Internal/ContextPropagationTokenImpl.cs | 118 +++++++++++++++++ .../Internal/DefaultServerCallContext.cs | 2 +- 9 files changed, 228 insertions(+), 134 deletions(-) create mode 100644 src/csharp/Grpc.Core/ContextPropagationOptions.cs create mode 100644 src/csharp/Grpc.Core/Internal/ContextPropagationFlags.cs create mode 100644 src/csharp/Grpc.Core/Internal/ContextPropagationTokenImpl.cs diff --git a/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs b/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs index 8e5c411cadd..1fd48812b54 100644 --- a/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs +++ b/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs @@ -45,7 +45,7 @@ namespace Grpc.Core.Tests var writeOptions = new WriteOptions(); Assert.AreSame(writeOptions, options.WithWriteOptions(writeOptions).WriteOptions); - var propagationToken = new ContextPropagationToken(CallSafeHandle.NullInstance, DateTime.UtcNow, + var propagationToken = new ContextPropagationTokenImpl(CallSafeHandle.NullInstance, DateTime.UtcNow, CancellationToken.None, ContextPropagationOptions.Default); Assert.AreSame(propagationToken, options.WithPropagationToken(propagationToken).PropagationToken); @@ -72,13 +72,13 @@ namespace Grpc.Core.Tests Assert.AreEqual(DateTime.MaxValue, new CallOptions().Normalize().Deadline.Value); var deadline = DateTime.UtcNow; - var propagationToken1 = new ContextPropagationToken(CallSafeHandle.NullInstance, deadline, CancellationToken.None, + var propagationToken1 = new ContextPropagationTokenImpl(CallSafeHandle.NullInstance, deadline, CancellationToken.None, new ContextPropagationOptions(propagateDeadline: true, propagateCancellation: false)); Assert.AreEqual(deadline, new CallOptions(propagationToken: propagationToken1).Normalize().Deadline.Value); Assert.Throws(typeof(ArgumentException), () => new CallOptions(deadline: deadline, propagationToken: propagationToken1).Normalize()); var token = new CancellationTokenSource().Token; - var propagationToken2 = new ContextPropagationToken(CallSafeHandle.NullInstance, deadline, token, + var propagationToken2 = new ContextPropagationTokenImpl(CallSafeHandle.NullInstance, deadline, token, new ContextPropagationOptions(propagateDeadline: false, propagateCancellation: true)); Assert.AreEqual(token, new CallOptions(propagationToken: propagationToken2).Normalize().CancellationToken); Assert.Throws(typeof(ArgumentException), () => new CallOptions(cancellationToken: token, propagationToken: propagationToken2).Normalize()); diff --git a/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs b/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs index c8bc372202d..9a878bde436 100644 --- a/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs +++ b/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs @@ -72,7 +72,7 @@ namespace Grpc.Core.Tests helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => { var propagationToken = context.CreatePropagationToken(); - Assert.IsNotNull(propagationToken.ParentCall); + Assert.IsNotNull(propagationToken.AsImplOrNull().ParentCall); var callOptions = new CallOptions(propagationToken: propagationToken); try diff --git a/src/csharp/Grpc.Core/CallOptions.cs b/src/csharp/Grpc.Core/CallOptions.cs index 75d8906a691..89fd047a1ea 100644 --- a/src/csharp/Grpc.Core/CallOptions.cs +++ b/src/csharp/Grpc.Core/CallOptions.cs @@ -236,22 +236,24 @@ namespace Grpc.Core internal CallOptions Normalize() { var newOptions = this; + // silently ignore the context propagation token if it wasn't produced by "us" + var propagationTokenImpl = propagationToken.AsImplOrNull(); if (propagationToken != null) { - if (propagationToken.Options.IsPropagateDeadline) + if (propagationTokenImpl.Options.IsPropagateDeadline) { GrpcPreconditions.CheckArgument(!newOptions.deadline.HasValue, "Cannot propagate deadline from parent call. The deadline has already been set explicitly."); - newOptions.deadline = propagationToken.ParentDeadline; + newOptions.deadline = propagationTokenImpl.ParentDeadline; } - if (propagationToken.Options.IsPropagateCancellation) + if (propagationTokenImpl.Options.IsPropagateCancellation) { GrpcPreconditions.CheckArgument(!newOptions.cancellationToken.CanBeCanceled, "Cannot propagate cancellation token from parent call. The cancellation token has already been set to a non-default value."); - newOptions.cancellationToken = propagationToken.ParentCancellationToken; + newOptions.cancellationToken = propagationTokenImpl.ParentCancellationToken; } } - + newOptions.headers = newOptions.headers ?? Metadata.Empty; newOptions.deadline = newOptions.deadline ?? DateTime.MaxValue; return newOptions; diff --git a/src/csharp/Grpc.Core/ContextPropagationOptions.cs b/src/csharp/Grpc.Core/ContextPropagationOptions.cs new file mode 100644 index 00000000000..160d10dc82c --- /dev/null +++ b/src/csharp/Grpc.Core/ContextPropagationOptions.cs @@ -0,0 +1,59 @@ +#region Copyright notice and license + +// Copyright 2019 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. + +#endregion + +using System; + +namespace Grpc.Core +{ + /// + /// Options for . + /// + public class ContextPropagationOptions + { + /// + /// The context propagation options that will be used by default. + /// + public static readonly ContextPropagationOptions Default = new ContextPropagationOptions(); + + bool propagateDeadline; + bool propagateCancellation; + + /// + /// Creates new context propagation options. + /// + /// If set to true parent call's deadline will be propagated to the child call. + /// If set to true parent call's cancellation token will be propagated to the child call. + public ContextPropagationOptions(bool propagateDeadline = true, bool propagateCancellation = true) + { + this.propagateDeadline = propagateDeadline; + this.propagateCancellation = propagateCancellation; + } + + /// true if parent call's deadline should be propagated to the child call. + public bool IsPropagateDeadline + { + get { return this.propagateDeadline; } + } + + /// true if parent call's cancellation token should be propagated to the child call. + public bool IsPropagateCancellation + { + get { return this.propagateCancellation; } + } + } +} diff --git a/src/csharp/Grpc.Core/ContextPropagationToken.cs b/src/csharp/Grpc.Core/ContextPropagationToken.cs index fe5c8a5c99a..d0c3f0cd1d3 100644 --- a/src/csharp/Grpc.Core/ContextPropagationToken.cs +++ b/src/csharp/Grpc.Core/ContextPropagationToken.cs @@ -16,12 +16,6 @@ #endregion -using System; -using System.Threading; - -using Grpc.Core.Internal; -using Grpc.Core.Utils; - namespace Grpc.Core { /// @@ -32,124 +26,10 @@ namespace Grpc.Core /// The gRPC native layer provides some other contexts (like tracing context) that /// are not accessible to explicitly C# layer, but this token still allows propagating them. /// - public class ContextPropagationToken - { - /// - /// Default propagation mask used by C core. - /// - private const ContextPropagationFlags DefaultCoreMask = (ContextPropagationFlags)0xffff; - - /// - /// Default propagation mask used by C# - we want to propagate deadline - /// and cancellation token by our own means. - /// - internal const ContextPropagationFlags DefaultMask = DefaultCoreMask - & ~ContextPropagationFlags.Deadline & ~ContextPropagationFlags.Cancellation; - - readonly CallSafeHandle parentCall; - readonly DateTime deadline; - readonly CancellationToken cancellationToken; - readonly ContextPropagationOptions options; - - internal ContextPropagationToken(CallSafeHandle parentCall, DateTime deadline, CancellationToken cancellationToken, ContextPropagationOptions options) - { - this.parentCall = GrpcPreconditions.CheckNotNull(parentCall); - this.deadline = deadline; - this.cancellationToken = cancellationToken; - this.options = options ?? ContextPropagationOptions.Default; - } - - /// - /// Gets the native handle of the parent call. - /// - internal CallSafeHandle ParentCall - { - get - { - return this.parentCall; - } - } - - /// - /// Gets the parent call's deadline. - /// - internal DateTime ParentDeadline - { - get - { - return this.deadline; - } - } - - /// - /// Gets the parent call's cancellation token. - /// - internal CancellationToken ParentCancellationToken - { - get - { - return this.cancellationToken; - } - } - - /// - /// Get the context propagation options. - /// - internal ContextPropagationOptions Options - { - get - { - return this.options; - } - } - } - - /// - /// Options for . - /// - public class ContextPropagationOptions + public abstract class ContextPropagationToken { - /// - /// The context propagation options that will be used by default. - /// - public static readonly ContextPropagationOptions Default = new ContextPropagationOptions(); - - bool propagateDeadline; - bool propagateCancellation; - - /// - /// Creates new context propagation options. - /// - /// If set to true parent call's deadline will be propagated to the child call. - /// If set to true parent call's cancellation token will be propagated to the child call. - public ContextPropagationOptions(bool propagateDeadline = true, bool propagateCancellation = true) - { - this.propagateDeadline = propagateDeadline; - this.propagateCancellation = propagateCancellation; - } - - /// true if parent call's deadline should be propagated to the child call. - public bool IsPropagateDeadline + internal ContextPropagationToken() { - get { return this.propagateDeadline; } } - - /// true if parent call's cancellation token should be propagated to the child call. - public bool IsPropagateCancellation - { - get { return this.propagateCancellation; } - } - } - - /// - /// Context propagation flags from grpc/grpc.h. - /// - [Flags] - internal enum ContextPropagationFlags - { - Deadline = 1, - CensusStatsContext = 2, - CensusTracingContext = 4, - Cancellation = 8 } } diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs index b6d687f71e7..e2a018e871b 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs @@ -494,13 +494,14 @@ namespace Grpc.Core.Internal return injectedNativeCall; // allows injecting a mock INativeCall in tests. } - var parentCall = details.Options.PropagationToken != null ? details.Options.PropagationToken.ParentCall : CallSafeHandle.NullInstance; + var parentCall = details.Options.PropagationToken != null ? details.Options.PropagationToken.AsImplOrNull().ParentCall : CallSafeHandle.NullInstance; var credentials = details.Options.Credentials; using (var nativeCredentials = credentials != null ? credentials.ToNativeCredentials() : null) { + // TODO(jtattermusch): is the "DefaultMask" correct here?? var result = details.Channel.Handle.CreateCall( - parentCall, ContextPropagationToken.DefaultMask, cq, + parentCall, ContextPropagationTokenImpl.DefaultMask, cq, details.Method, details.Host, Timespec.FromDateTime(details.Options.Deadline.Value), nativeCredentials); return result; } diff --git a/src/csharp/Grpc.Core/Internal/ContextPropagationFlags.cs b/src/csharp/Grpc.Core/Internal/ContextPropagationFlags.cs new file mode 100644 index 00000000000..11a9c93a67d --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ContextPropagationFlags.cs @@ -0,0 +1,34 @@ +#region Copyright notice and license + +// Copyright 2019 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. + +#endregion + +using System; + +namespace Grpc.Core.Internal +{ + /// + /// Context propagation flags from grpc/grpc.h. + /// + [Flags] + internal enum ContextPropagationFlags + { + Deadline = 1, + CensusStatsContext = 2, + CensusTracingContext = 4, + Cancellation = 8 + } +} diff --git a/src/csharp/Grpc.Core/Internal/ContextPropagationTokenImpl.cs b/src/csharp/Grpc.Core/Internal/ContextPropagationTokenImpl.cs new file mode 100644 index 00000000000..1fd994e607c --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ContextPropagationTokenImpl.cs @@ -0,0 +1,118 @@ +#region Copyright notice and license + +// Copyright 2019 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. + +#endregion + +using System; +using System.Threading; + +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Implementation of ContextPropagationToken that carries + /// all fields needed for context propagation by C-core based implementation of gRPC. + /// Instances of ContextPropagationToken that are not of this + /// type will be recognized as "foreign" and will be silently ignored + /// (treated as if null). + /// + internal class ContextPropagationTokenImpl : ContextPropagationToken + { + /// + /// Default propagation mask used by C core. + /// + private const ContextPropagationFlags DefaultCoreMask = (ContextPropagationFlags)0xffff; + + /// + /// Default propagation mask used by C# - we want to propagate deadline + /// and cancellation token by our own means. + /// + internal const ContextPropagationFlags DefaultMask = DefaultCoreMask + & ~ContextPropagationFlags.Deadline & ~ContextPropagationFlags.Cancellation; + + readonly CallSafeHandle parentCall; + readonly DateTime deadline; + readonly CancellationToken cancellationToken; + readonly ContextPropagationOptions options; + + internal ContextPropagationTokenImpl(CallSafeHandle parentCall, DateTime deadline, CancellationToken cancellationToken, ContextPropagationOptions options) + { + this.parentCall = GrpcPreconditions.CheckNotNull(parentCall); + this.deadline = deadline; + this.cancellationToken = cancellationToken; + this.options = options ?? ContextPropagationOptions.Default; + } + + /// + /// Gets the native handle of the parent call. + /// + internal CallSafeHandle ParentCall + { + get + { + return this.parentCall; + } + } + + /// + /// Gets the parent call's deadline. + /// + internal DateTime ParentDeadline + { + get + { + return this.deadline; + } + } + + /// + /// Gets the parent call's cancellation token. + /// + internal CancellationToken ParentCancellationToken + { + get + { + return this.cancellationToken; + } + } + + /// + /// Get the context propagation options. + /// + internal ContextPropagationOptions Options + { + get + { + return this.options; + } + } + } + + internal static class ContextPropagationTokenExtensions + { + /// + /// Converts given ContextPropagationToken to ContextPropagationTokenImpl + /// if possible or returns null. + /// Being able to convert means that the context propagation token is recognized as + /// "ours" (was created by this implementation). + /// + public static ContextPropagationTokenImpl AsImplOrNull(this ContextPropagationToken instanceOrNull) + { + return instanceOrNull as ContextPropagationTokenImpl; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/DefaultServerCallContext.cs b/src/csharp/Grpc.Core/Internal/DefaultServerCallContext.cs index 8220e599f92..b33cb631e26 100644 --- a/src/csharp/Grpc.Core/Internal/DefaultServerCallContext.cs +++ b/src/csharp/Grpc.Core/Internal/DefaultServerCallContext.cs @@ -63,7 +63,7 @@ namespace Grpc.Core protected override ContextPropagationToken CreatePropagationTokenCore(ContextPropagationOptions options) { - return new ContextPropagationToken(callHandle, deadline, cancellationToken, options); + return new ContextPropagationTokenImpl(callHandle, deadline, cancellationToken, options); } protected override Task WriteResponseHeadersAsyncCore(Metadata responseHeaders) From f6924ff2d1e506a553f0a6590801a50fca34fa27 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 18 Jan 2019 13:57:39 -0800 Subject: [PATCH 023/218] fix newline EOF --- templates/src/objective-c/BoringSSL-GRPC.podspec.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/src/objective-c/BoringSSL-GRPC.podspec.template b/templates/src/objective-c/BoringSSL-GRPC.podspec.template index 6804f75f1b0..f2abe0d61dc 100644 --- a/templates/src/objective-c/BoringSSL-GRPC.podspec.template +++ b/templates/src/objective-c/BoringSSL-GRPC.podspec.template @@ -1561,4 +1561,4 @@ # This is the last part of this file. s.prefix_header_contents = ${expand_symbol_list(settings.grpc_shadow_boringssl_symbols)} - end \ No newline at end of file + end From 371d4cd519b8f838fd40e7a9c7fec1889b11dcfd Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 18 Jan 2019 15:51:31 -0800 Subject: [PATCH 024/218] Update pod versions --- gRPC-C++.podspec | 2 +- src/objective-c/BoringSSL-GRPC.podspec | 4 ++-- templates/gRPC-C++.podspec.template | 2 +- templates/src/objective-c/BoringSSL-GRPC.podspec.template | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 4c30e568a1b..08ca3da2650 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -24,7 +24,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 = '0.0.6-dev' + version = '0.0.8-dev' s.version = version s.summary = 'gRPC C++ library' s.homepage = 'https://grpc.io' diff --git a/src/objective-c/BoringSSL-GRPC.podspec b/src/objective-c/BoringSSL-GRPC.podspec index 99bb5397aef..528b96f32aa 100644 --- a/src/objective-c/BoringSSL-GRPC.podspec +++ b/src/objective-c/BoringSSL-GRPC.podspec @@ -39,7 +39,7 @@ Pod::Spec.new do |s| s.name = 'BoringSSL-GRPC' - version = '0.0.2' + version = '0.0.3' s.version = version s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.' # Adapted from the homepage: @@ -4527,4 +4527,4 @@ Pod::Spec.new do |s| '#define i2d_PKCS8_PRIV_KEY_INFO GRPC_SHADOW_i2d_PKCS8_PRIV_KEY_INFO', '#define PKCS5_pbe2_decrypt_init GRPC_SHADOW_PKCS5_pbe2_decrypt_init', '#define PKCS5_pbe2_encrypt_init GRPC_SHADOW_PKCS5_pbe2_encrypt_init' -end \ No newline at end of file +end diff --git a/templates/gRPC-C++.podspec.template b/templates/gRPC-C++.podspec.template index 371d25cd6ba..1ba4556ee10 100644 --- a/templates/gRPC-C++.podspec.template +++ b/templates/gRPC-C++.podspec.template @@ -140,7 +140,7 @@ s.name = 'gRPC-C++' # TODO (mxyan): use version that match gRPC version when pod is stabilized # version = '${settings.version}' - version = '${modify_podspec_version_string('0.0.6', settings.version)}' + version = '${modify_podspec_version_string('0.0.8', settings.version)}' s.version = version s.summary = 'gRPC C++ library' s.homepage = 'https://grpc.io' diff --git a/templates/src/objective-c/BoringSSL-GRPC.podspec.template b/templates/src/objective-c/BoringSSL-GRPC.podspec.template index f2abe0d61dc..d86aa0c6cb4 100644 --- a/templates/src/objective-c/BoringSSL-GRPC.podspec.template +++ b/templates/src/objective-c/BoringSSL-GRPC.podspec.template @@ -44,7 +44,7 @@ Pod::Spec.new do |s| s.name = 'BoringSSL-GRPC' - version = '0.0.2' + version = '0.0.3' s.version = version s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.' # Adapted from the homepage: From f019339cecd3b6b3972d6aa31d47e7f8d23ab89e Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 21 Jan 2019 14:42:23 +0100 Subject: [PATCH 025/218] improve ContextPropagationToken doc comment --- src/csharp/Grpc.Core/ContextPropagationToken.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/csharp/Grpc.Core/ContextPropagationToken.cs b/src/csharp/Grpc.Core/ContextPropagationToken.cs index d0c3f0cd1d3..60e407dc781 100644 --- a/src/csharp/Grpc.Core/ContextPropagationToken.cs +++ b/src/csharp/Grpc.Core/ContextPropagationToken.cs @@ -23,8 +23,8 @@ namespace Grpc.Core /// In situations when a backend is making calls to another backend, /// it makes sense to propagate properties like deadline and cancellation /// token of the server call to the child call. - /// The gRPC native layer provides some other contexts (like tracing context) that - /// are not accessible to explicitly C# layer, but this token still allows propagating them. + /// Underlying gRPC implementation may provide other "opaque" contexts (like tracing context) that + /// are not explicitly accesible via the public C# API, but this token still allows propagating them. /// public abstract class ContextPropagationToken { From 50854e952122176a241c708a28b412a3ceefc0f6 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 21 Jan 2019 14:51:30 +0100 Subject: [PATCH 026/218] remove unsubstantiated TODO --- src/csharp/Grpc.Core/Internal/AsyncCall.cs | 1 - src/csharp/Grpc.Core/Internal/ContextPropagationTokenImpl.cs | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs index e2a018e871b..f80ac4a2f9d 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs @@ -499,7 +499,6 @@ namespace Grpc.Core.Internal var credentials = details.Options.Credentials; using (var nativeCredentials = credentials != null ? credentials.ToNativeCredentials() : null) { - // TODO(jtattermusch): is the "DefaultMask" correct here?? var result = details.Channel.Handle.CreateCall( parentCall, ContextPropagationTokenImpl.DefaultMask, cq, details.Method, details.Host, Timespec.FromDateTime(details.Options.Deadline.Value), nativeCredentials); diff --git a/src/csharp/Grpc.Core/Internal/ContextPropagationTokenImpl.cs b/src/csharp/Grpc.Core/Internal/ContextPropagationTokenImpl.cs index 1fd994e607c..e2528e84cff 100644 --- a/src/csharp/Grpc.Core/Internal/ContextPropagationTokenImpl.cs +++ b/src/csharp/Grpc.Core/Internal/ContextPropagationTokenImpl.cs @@ -39,7 +39,8 @@ namespace Grpc.Core.Internal /// /// Default propagation mask used by C# - we want to propagate deadline - /// and cancellation token by our own means. + /// and cancellation token by our own means, everything else will be propagated + /// by C core automatically (according to DefaultCoreMask). /// internal const ContextPropagationFlags DefaultMask = DefaultCoreMask & ~ContextPropagationFlags.Deadline & ~ContextPropagationFlags.Cancellation; From b273ffb609908f5a7a2e3aa2feb2cd446a2fbdc6 Mon Sep 17 00:00:00 2001 From: Jerry Date: Mon, 21 Jan 2019 11:55:47 -0800 Subject: [PATCH 027/218] create a valgrind.include, and include it in php and php7 docker images --- .../dockerfile/test/php7_jessie_x64/Dockerfile.template | 1 + .../dockerfile/test/php_jessie_x64/Dockerfile.template | 1 + templates/tools/dockerfile/valgrind.include | 8 ++++++++ tools/dockerfile/test/php7_jessie_x64/Dockerfile | 8 ++++++++ tools/dockerfile/test/php_jessie_x64/Dockerfile | 8 ++++++++ 5 files changed, 26 insertions(+) create mode 100644 templates/tools/dockerfile/valgrind.include diff --git a/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template index e7b6c0d5f9c..f6f52805b8c 100644 --- a/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template @@ -19,6 +19,7 @@ <%include file="../../php7_deps.include"/> <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> + <%include file="../../valgrind.include"/> <%include file="../../run_tests_addons.include"/> # Define the default command. CMD ["bash"] diff --git a/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template index fdbad53c391..1a07522c011 100644 --- a/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template @@ -20,6 +20,7 @@ <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../php_deps.include"/> + <%include file="../../valgrind.include"/> <%include file="../../run_tests_addons.include"/> # Define the default command. CMD ["bash"] diff --git a/templates/tools/dockerfile/valgrind.include b/templates/tools/dockerfile/valgrind.include new file mode 100644 index 00000000000..d86cc7158bf --- /dev/null +++ b/templates/tools/dockerfile/valgrind.include @@ -0,0 +1,8 @@ +#================= +# PHP dependencies + +# Install dependencies + +RUN apt-get update && apt-get install -y ${'\\'} + valgrind + \ No newline at end of file diff --git a/tools/dockerfile/test/php7_jessie_x64/Dockerfile b/tools/dockerfile/test/php7_jessie_x64/Dockerfile index 0dff8399047..e4daf169285 100644 --- a/tools/dockerfile/test/php7_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/php7_jessie_x64/Dockerfile @@ -79,6 +79,14 @@ 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 +#================= +# PHP dependencies + +# Install dependencies + +RUN apt-get update && apt-get install -y \ + valgrind + RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/test/php_jessie_x64/Dockerfile b/tools/dockerfile/test/php_jessie_x64/Dockerfile index ed59e569956..8698deec835 100644 --- a/tools/dockerfile/test/php_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/php_jessie_x64/Dockerfile @@ -76,6 +76,14 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t RUN apt-get update && apt-get install -y \ git php5 php5-dev phpunit unzip +#================= +# PHP dependencies + +# Install dependencies + +RUN apt-get update && apt-get install -y \ + valgrind + RUN mkdir /var/local/jenkins From 412bba83548a7bf11d4822eb355c26f8b27a020f Mon Sep 17 00:00:00 2001 From: Jerry Date: Mon, 21 Jan 2019 11:59:39 -0800 Subject: [PATCH 028/218] changed comment in valgrind.include --- templates/tools/dockerfile/valgrind.include | 3 +-- tools/dockerfile/test/php7_jessie_x64/Dockerfile | 4 ++-- tools/dockerfile/test/php_jessie_x64/Dockerfile | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/templates/tools/dockerfile/valgrind.include b/templates/tools/dockerfile/valgrind.include index d86cc7158bf..f1f3b67d826 100644 --- a/templates/tools/dockerfile/valgrind.include +++ b/templates/tools/dockerfile/valgrind.include @@ -1,8 +1,7 @@ #================= -# PHP dependencies +# PHP Test dependencies # Install dependencies RUN apt-get update && apt-get install -y ${'\\'} valgrind - \ No newline at end of file diff --git a/tools/dockerfile/test/php7_jessie_x64/Dockerfile b/tools/dockerfile/test/php7_jessie_x64/Dockerfile index e4daf169285..529ebb9127b 100644 --- a/tools/dockerfile/test/php7_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/php7_jessie_x64/Dockerfile @@ -80,13 +80,13 @@ 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 #================= -# PHP dependencies +# PHP Test dependencies # Install dependencies RUN apt-get update && apt-get install -y \ valgrind - + RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/test/php_jessie_x64/Dockerfile b/tools/dockerfile/test/php_jessie_x64/Dockerfile index 8698deec835..f69f7e65a20 100644 --- a/tools/dockerfile/test/php_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/php_jessie_x64/Dockerfile @@ -77,13 +77,13 @@ RUN apt-get update && apt-get install -y \ git php5 php5-dev phpunit unzip #================= -# PHP dependencies +# PHP Test dependencies # Install dependencies RUN apt-get update && apt-get install -y \ valgrind - + RUN mkdir /var/local/jenkins From 958f4535c435796286432272d7a066a42c3c03a9 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 21 Jan 2019 19:15:35 -0800 Subject: [PATCH 029/218] Fix TSAN issue in filter_status_code test --- test/core/end2end/tests/filter_status_code.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/core/end2end/tests/filter_status_code.cc b/test/core/end2end/tests/filter_status_code.cc index 5ffc3d00a3f..6d85c1b0724 100644 --- a/test/core/end2end/tests/filter_status_code.cc +++ b/test/core/end2end/tests/filter_status_code.cc @@ -260,6 +260,7 @@ typedef struct final_status_data { static void server_start_transport_stream_op_batch( grpc_call_element* elem, grpc_transport_stream_op_batch* op) { auto* data = static_cast(elem->call_data); + gpr_mu_lock(&g_mu); if (data->call == g_server_call_stack) { if (op->send_initial_metadata) { auto* batch = op->payload->send_initial_metadata.send_initial_metadata; @@ -270,6 +271,7 @@ static void server_start_transport_stream_op_batch( } } } + gpr_mu_unlock(&g_mu); grpc_call_next_op(elem, op); } From bf8777dc307e2938a7d7e02ff761580b9917f529 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 21 Jan 2019 19:57:52 -0800 Subject: [PATCH 030/218] Add const qualifiers to member methods in Optional --- src/core/lib/gprpp/optional.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/lib/gprpp/optional.h b/src/core/lib/gprpp/optional.h index e517c6edccc..a8e3ce1505e 100644 --- a/src/core/lib/gprpp/optional.h +++ b/src/core/lib/gprpp/optional.h @@ -31,11 +31,11 @@ class Optional { set_ = true; } - bool has_value() { return set_; } + bool has_value() const { return set_; } void reset() { set_ = false; } - T value() { return value_; } + T value() const { return value_; } private: T value_; From 4f451c78a41e5c1a90d641754cdd2f4efc2e915d Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Tue, 22 Jan 2019 16:50:47 -0800 Subject: [PATCH 031/218] Add basic benchmark test for Python --- src/proto/grpc/core/BUILD | 18 +++- src/proto/grpc/testing/BUILD | 94 +++++++++++++--- src/python/grpcio_tests/tests/qps/BUILD | 89 ++++++++++++++++ src/python/grpcio_tests/tests/qps/README.md | 100 ++++++++++++++++++ .../tests/qps/basic_benchmark_test.sh | 45 ++++++++ .../grpcio_tests/tests/qps/scenarios.json | 96 +++++++++++++++++ test/cpp/qps/BUILD | 6 +- 7 files changed, 428 insertions(+), 20 deletions(-) create mode 100644 src/python/grpcio_tests/tests/qps/BUILD create mode 100644 src/python/grpcio_tests/tests/qps/README.md create mode 100755 src/python/grpcio_tests/tests/qps/basic_benchmark_test.sh create mode 100644 src/python/grpcio_tests/tests/qps/scenarios.json diff --git a/src/proto/grpc/core/BUILD b/src/proto/grpc/core/BUILD index 46de9fae187..2543027821c 100644 --- a/src/proto/grpc/core/BUILD +++ b/src/proto/grpc/core/BUILD @@ -14,11 +14,25 @@ licenses(["notice"]) # Apache v2 -load("//bazel:grpc_build_system.bzl", "grpc_proto_library", "grpc_package") +load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library") +load("@grpc_python_dependencies//:requirements.bzl", "requirement") +load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_library") -grpc_package(name = "core", visibility = "public") +grpc_package( + name = "core", + visibility = "public", +) grpc_proto_library( name = "stats_proto", srcs = ["stats.proto"], ) + +py_proto_library( + name = "py_stats_proto", + protos = ["stats.proto"], + with_grpc = True, + deps = [ + requirement("protobuf"), + ], +) diff --git a/src/proto/grpc/testing/BUILD b/src/proto/grpc/testing/BUILD index 9876d5160a1..0c658967942 100644 --- a/src/proto/grpc/testing/BUILD +++ b/src/proto/grpc/testing/BUILD @@ -14,11 +14,14 @@ licenses(["notice"]) # Apache v2 -load("//bazel:grpc_build_system.bzl", "grpc_proto_library", "grpc_package") +load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library") load("@grpc_python_dependencies//:requirements.bzl", "requirement") load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_library") -grpc_package(name = "testing", visibility = "public") +grpc_package( + name = "testing", + visibility = "public", +) exports_files([ "echo.proto", @@ -50,9 +53,11 @@ grpc_proto_library( grpc_proto_library( name = "echo_proto", srcs = ["echo.proto"], - deps = ["echo_messages_proto", - "simple_messages_proto"], generate_mocks = True, + deps = [ + "echo_messages_proto", + "simple_messages_proto", + ], ) grpc_proto_library( @@ -63,10 +68,10 @@ grpc_proto_library( py_proto_library( name = "py_empty_proto", - protos = ["empty.proto",], + protos = ["empty.proto"], with_grpc = True, deps = [ - requirement('protobuf'), + requirement("protobuf"), ], ) @@ -78,10 +83,10 @@ grpc_proto_library( py_proto_library( name = "py_messages_proto", - protos = ["messages.proto",], + protos = ["messages.proto"], with_grpc = True, deps = [ - requirement('protobuf'), + requirement("protobuf"), ], ) @@ -100,7 +105,7 @@ grpc_proto_library( name = "benchmark_service_proto", srcs = ["benchmark_service.proto"], deps = [ - "messages_proto", + "messages_proto", ], ) @@ -108,7 +113,7 @@ grpc_proto_library( name = "report_qps_scenario_service_proto", srcs = ["report_qps_scenario_service.proto"], deps = [ - "control_proto", + "control_proto", ], ) @@ -116,7 +121,7 @@ grpc_proto_library( name = "worker_service_proto", srcs = ["worker_service.proto"], deps = [ - "control_proto", + "control_proto", ], ) @@ -132,7 +137,7 @@ grpc_proto_library( has_services = False, deps = [ "//src/proto/grpc/core:stats_proto", - ] + ], ) grpc_proto_library( @@ -146,14 +151,71 @@ grpc_proto_library( py_proto_library( name = "py_test_proto", - protos = ["test.proto",], + proto_deps = [ + ":py_empty_proto", + ":py_messages_proto", + ], + protos = ["test.proto"], with_grpc = True, deps = [ - requirement('protobuf'), + requirement("protobuf"), ], +) + +py_proto_library( + name = "py_benchmark_service_proto", proto_deps = [ - ":py_empty_proto", ":py_messages_proto", - ] + ], + protos = ["benchmark_service.proto"], + with_grpc = True, + deps = [ + requirement("protobuf"), + ], +) + +py_proto_library( + name = "py_payloads_proto", + protos = ["payloads.proto"], + with_grpc = True, + deps = [ + requirement("protobuf"), + ], ) +py_proto_library( + name = "py_stats_proto", + proto_deps = [ + "//src/proto/grpc/core:py_stats_proto", + ], + protos = ["stats.proto"], + with_grpc = True, + deps = [ + requirement("protobuf"), + ], +) + +py_proto_library( + name = "py_control_proto", + proto_deps = [ + ":py_payloads_proto", + ":py_stats_proto", + ], + protos = ["control.proto"], + with_grpc = True, + deps = [ + requirement("protobuf"), + ], +) + +py_proto_library( + name = "py_worker_service_proto", + proto_deps = [ + ":py_control_proto", + ], + protos = ["worker_service.proto"], + with_grpc = True, + deps = [ + requirement("protobuf"), + ], +) diff --git a/src/python/grpcio_tests/tests/qps/BUILD b/src/python/grpcio_tests/tests/qps/BUILD new file mode 100644 index 00000000000..c1eb6b8e11a --- /dev/null +++ b/src/python/grpcio_tests/tests/qps/BUILD @@ -0,0 +1,89 @@ +package(default_visibility = ["//visibility:public"]) + +load("@grpc_python_dependencies//:requirements.bzl", "requirement") + +py_library( + name = "benchmark_client", + srcs = ["benchmark_client.py"], + imports = ["../../"], + deps = [ + requirement("six"), + "//src/proto/grpc/testing:py_benchmark_service_proto", + "//src/proto/grpc/testing:py_messages_proto", + "//src/python/grpcio/grpc:grpcio", + "//src/python/grpcio_tests/tests/unit:resources", + "//src/python/grpcio_tests/tests/unit:test_common", + ], +) + +py_library( + name = "benchmark_server", + srcs = ["benchmark_server.py"], + imports = ["../../"], + deps = [ + "//src/proto/grpc/testing:py_benchmark_service_proto", + "//src/proto/grpc/testing:py_messages_proto", + ], +) + +py_library( + name = "client_runner", + srcs = ["client_runner.py"], + imports = ["../../"], +) + +py_library( + name = "histogram", + srcs = ["histogram.py"], + imports = ["../../"], + deps = [ + "//src/proto/grpc/testing:py_stats_proto", + ], +) + +py_library( + name = "worker_server", + srcs = ["worker_server.py"], + imports = ["../../"], + deps = [ + ":benchmark_client", + ":benchmark_server", + ":client_runner", + ":histogram", + "//src/proto/grpc/testing:py_benchmark_service_proto", + "//src/proto/grpc/testing:py_control_proto", + "//src/proto/grpc/testing:py_stats_proto", + "//src/proto/grpc/testing:py_worker_service_proto", + "//src/python/grpcio/grpc:grpcio", + "//src/python/grpcio_tests/tests/unit:resources", + "//src/python/grpcio_tests/tests/unit:test_common", + ], +) + +py_binary( + name = "qps_worker", + srcs = ["qps_worker.py"], + imports = ["../../"], + main = "qps_worker.py", + deps = [ + ":worker_server", + "//src/proto/grpc/testing:py_worker_service_proto", + "//src/python/grpcio/grpc:grpcio", + "//src/python/grpcio_tests/tests/unit:test_common", + ], +) + +filegroup( + name = "scenarios", + srcs = ["scenarios.json"], +) + +sh_test( + name = "basic_benchmark_test", + srcs = ["basic_benchmark_test.sh"], + data = [ + ":qps_worker", + ":scenarios", + "//test/cpp/qps:qps_json_driver", + ], +) diff --git a/src/python/grpcio_tests/tests/qps/README.md b/src/python/grpcio_tests/tests/qps/README.md new file mode 100644 index 00000000000..504a2189f73 --- /dev/null +++ b/src/python/grpcio_tests/tests/qps/README.md @@ -0,0 +1,100 @@ +# Python Benchmark Tools + +## Scenarios + +In `src/proto/grpc/testing/control.proto`, it defines the fields of a scenario. +In `tools/run_tests/performance/scenario_config.py`, the script generates actual scenario content that usually in json format, or piped to another script. + +All Python related benchmark scenarios are: +* netperf +* python_generic_sync_streaming_ping_pong +* python_protobuf_sync_streaming_ping_pong +* python_protobuf_async_unary_ping_pong +* python_protobuf_sync_unary_ping_pong +* python_protobuf_sync_unary_qps_unconstrained +* python_protobuf_sync_streaming_qps_unconstrained +* python_protobuf_sync_unary_ping_pong_1MB + +Here I picked the top 2 most representative scenarios of them, and reduce their benchmark duration from 30 seconds to 10 seconds: +* python_protobuf_async_unary_ping_pong +* python_protobuf_sync_streaming_ping_pong + +## Why keep the scenario file if it can be generated? + +Well... The `tools/run_tests/performance/scenario_config.py` is 1274 lines long. The intention of building these benchmark tools is reducing the complexity of existing infrastructure code. Depending on something that is + +## How to run it? + +```shell +bazel test --test_output=streamed src/python/grpcio_tests/tests/qps:basic_benchmark_test +``` + +## How is the output look like? + +``` +RUNNING SCENARIO: python_protobuf_async_unary_ping_pong +I0123 00:26:04.746195000 140736237159296 driver.cc:288] Starting server on localhost:10086 (worker #0) +D0123 00:26:04.747190000 140736237159296 ev_posix.cc:170] Using polling engine: poll +D0123 00:26:04.747264000 140736237159296 dns_resolver_ares.cc:488] Using ares dns resolver +I0123 00:26:04.748445000 140736237159296 subchannel.cc:869] Connect failed: {"created":"@1548203164.748403000","description":"Failed to connect to remote host: Connection refused","errno":61,"file":"src/core/lib/iomgr/tcp_client_posix.cc","file_line":207,"os_error":"Connection refused","syscall":"connect","target_address":"ipv6:[::1]:10086"} +I0123 00:26:04.748585000 140736237159296 subchannel.cc:869] Connect failed: {"created":"@1548203164.748564000","description":"Failed to connect to remote host: Connection refused","errno":61,"file":"src/core/lib/iomgr/tcp_client_posix.cc","file_line":207,"os_error":"Connection refused","syscall":"connect","target_address":"ipv4:127.0.0.1:10086"} +I0123 00:26:04.748596000 140736237159296 subchannel.cc:751] Subchannel 0x7fca43c19360: Retry in 999 milliseconds +I0123 00:26:05.751251000 123145571299328 subchannel.cc:710] Failed to connect to channel, retrying +I0123 00:26:05.752209000 140736237159296 subchannel.cc:832] New connected subchannel at 0x7fca45000060 for subchannel 0x7fca43c19360 +I0123 00:26:05.772291000 140736237159296 driver.cc:349] Starting client on localhost:10087 (worker #1) +D0123 00:26:05.772384000 140736237159296 driver.cc:373] Client 0 gets 1 channels +I0123 00:26:05.773286000 140736237159296 subchannel.cc:832] New connected subchannel at 0x7fca45004a80 for subchannel 0x7fca451034b0 +I0123 00:26:05.789797000 140736237159296 driver.cc:394] Initiating +I0123 00:26:05.790858000 140736237159296 driver.cc:415] Warming up +I0123 00:26:07.791078000 140736237159296 driver.cc:421] Starting +I0123 00:26:07.791860000 140736237159296 driver.cc:448] Running +I0123 00:26:17.790915000 140736237159296 driver.cc:462] Finishing clients +I0123 00:26:17.791821000 140736237159296 driver.cc:476] Received final status from client 0 +I0123 00:26:17.792148000 140736237159296 driver.cc:508] Finishing servers +I0123 00:26:17.792493000 140736237159296 driver.cc:522] Received final status from server 0 +I0123 00:26:17.795786000 140736237159296 report.cc:82] QPS: 2066.6 +I0123 00:26:17.795799000 140736237159296 report.cc:122] QPS: 2066.6 (258.3/server core) +I0123 00:26:17.795805000 140736237159296 report.cc:127] Latencies (50/90/95/99/99.9%-ile): 467.9/504.8/539.0/653.3/890.4 us +I0123 00:26:17.795811000 140736237159296 report.cc:137] Server system time: 100.00% +I0123 00:26:17.795815000 140736237159296 report.cc:139] Server user time: 100.00% +I0123 00:26:17.795818000 140736237159296 report.cc:141] Client system time: 100.00% +I0123 00:26:17.795821000 140736237159296 report.cc:143] Client user time: 100.00% +I0123 00:26:17.795825000 140736237159296 report.cc:148] Server CPU usage: 0.00% +I0123 00:26:17.795828000 140736237159296 report.cc:153] Client Polls per Request: 0.00 +I0123 00:26:17.795831000 140736237159296 report.cc:155] Server Polls per Request: 0.00 +I0123 00:26:17.795834000 140736237159296 report.cc:160] Server Queries/CPU-sec: 1033.19 +I0123 00:26:17.795837000 140736237159296 report.cc:162] Client Queries/CPU-sec: 1033.32 +RUNNING SCENARIO: python_protobuf_sync_streaming_ping_pong +I0123 00:26:17.795888000 140736237159296 driver.cc:288] Starting server on localhost:10086 (worker #0) +D0123 00:26:17.795964000 140736237159296 ev_posix.cc:170] Using polling engine: poll +D0123 00:26:17.795978000 140736237159296 dns_resolver_ares.cc:488] Using ares dns resolver +I0123 00:26:17.796613000 140736237159296 subchannel.cc:832] New connected subchannel at 0x7fca43c15820 for subchannel 0x7fca43d12140 +I0123 00:26:17.810911000 140736237159296 driver.cc:349] Starting client on localhost:10087 (worker #1) +D0123 00:26:17.811037000 140736237159296 driver.cc:373] Client 0 gets 1 channels +I0123 00:26:17.811892000 140736237159296 subchannel.cc:832] New connected subchannel at 0x7fca43d18f40 for subchannel 0x7fca43d16b80 +I0123 00:26:17.818902000 140736237159296 driver.cc:394] Initiating +I0123 00:26:17.820776000 140736237159296 driver.cc:415] Warming up +I0123 00:26:19.824685000 140736237159296 driver.cc:421] Starting +I0123 00:26:19.825970000 140736237159296 driver.cc:448] Running +I0123 00:26:29.821866000 140736237159296 driver.cc:462] Finishing clients +I0123 00:26:29.823259000 140736237159296 driver.cc:476] Received final status from client 0 +I0123 00:26:29.827195000 140736237159296 driver.cc:508] Finishing servers +I0123 00:26:29.827599000 140736237159296 driver.cc:522] Received final status from server 0 +I0123 00:26:29.828739000 140736237159296 report.cc:82] QPS: 619.5 +I0123 00:26:29.828752000 140736237159296 report.cc:122] QPS: 619.5 (77.4/server core) +I0123 00:26:29.828760000 140736237159296 report.cc:127] Latencies (50/90/95/99/99.9%-ile): 1589.8/1854.3/1920.4/2015.8/2204.8 us +I0123 00:26:29.828765000 140736237159296 report.cc:137] Server system time: 100.00% +I0123 00:26:29.828769000 140736237159296 report.cc:139] Server user time: 100.00% +I0123 00:26:29.828772000 140736237159296 report.cc:141] Client system time: 100.00% +I0123 00:26:29.828776000 140736237159296 report.cc:143] Client user time: 100.00% +I0123 00:26:29.828780000 140736237159296 report.cc:148] Server CPU usage: 0.00% +I0123 00:26:29.828784000 140736237159296 report.cc:153] Client Polls per Request: 0.00 +I0123 00:26:29.828788000 140736237159296 report.cc:155] Server Polls per Request: 0.00 +I0123 00:26:29.828792000 140736237159296 report.cc:160] Server Queries/CPU-sec: 309.58 +I0123 00:26:29.828795000 140736237159296 report.cc:162] Client Queries/CPU-sec: 309.75 +``` + +## Future Works (TODOs) + +1. Generate a target for each scenario. +2. Simplify the main entrance of our benchmark related code, or make it depends on Bazel. diff --git a/src/python/grpcio_tests/tests/qps/basic_benchmark_test.sh b/src/python/grpcio_tests/tests/qps/basic_benchmark_test.sh new file mode 100755 index 00000000000..6011a7e01c2 --- /dev/null +++ b/src/python/grpcio_tests/tests/qps/basic_benchmark_test.sh @@ -0,0 +1,45 @@ +#! /bin/bash +# Copyright 2019 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. + +# This test benchmarks Python client/server. +set -ex + +declare -a DRIVER_PORTS=("10086" "10087") +SCENARIOS_FILE=src/python/grpcio_tests/tests/qps/scenarios.json + +function join { local IFS="$1"; shift; echo "$*"; } + +if [[ -e "${SCENARIOS_FILE}" ]]; then + echo "Running against scenarios.json:" + cat "${SCENARIOS_FILE}" +else + echo "Failed to find scenarios.json!" + exit 1 +fi + +echo "Starting Python qps workers..." +qps_workers=() +for DRIVER_PORT in "${DRIVER_PORTS[@]}" +do + echo -e "\tRunning Python qps worker listening at localhost:${DRIVER_PORT}..." + src/python/grpcio_tests/tests/qps/qps_worker \ + --driver_port="${DRIVER_PORT}" & + qps_workers+=("localhost:${DRIVER_PORT}") +done + +echo "Running qps json driver..." +QPS_WORKERS=$(join , ${qps_workers[@]}) +export QPS_WORKERS +test/cpp/qps/qps_json_driver --scenarios_file="${SCENARIOS_FILE}" diff --git a/src/python/grpcio_tests/tests/qps/scenarios.json b/src/python/grpcio_tests/tests/qps/scenarios.json new file mode 100644 index 00000000000..03c91be1e71 --- /dev/null +++ b/src/python/grpcio_tests/tests/qps/scenarios.json @@ -0,0 +1,96 @@ +{ + "scenarios": [ + { + "name": "python_protobuf_async_unary_ping_pong", + "clientConfig": { + "clientType": "ASYNC_CLIENT", + "securityParams": { + "useTestCa": true, + "serverHostOverride": "foo.test.google.fr" + }, + "outstandingRpcsPerChannel": 1, + "clientChannels": 1, + "asyncClientThreads": 1, + "loadParams": { + "closedLoop": {} + }, + "payloadConfig": { + "simpleParams": {} + }, + "histogramParams": { + "resolution": 0.01, + "maxPossible": 60000000000 + }, + "channelArgs": [ + { + "name": "grpc.optimization_target", + "strValue": "latency" + } + ] + }, + "numClients": 1, + "serverConfig": { + "serverType": "ASYNC_SERVER", + "securityParams": { + "useTestCa": true, + "serverHostOverride": "foo.test.google.fr" + }, + "channelArgs": [ + { + "name": "grpc.optimization_target", + "strValue": "latency" + } + ] + }, + "numServers": 1, + "warmupSeconds": 2, + "benchmarkSeconds": 10 + }, + { + "name": "python_protobuf_sync_streaming_ping_pong", + "clientConfig": { + "securityParams": { + "useTestCa": true, + "serverHostOverride": "foo.test.google.fr" + }, + "outstandingRpcsPerChannel": 1, + "clientChannels": 1, + "asyncClientThreads": 1, + "rpcType": "STREAMING", + "loadParams": { + "closedLoop": {} + }, + "payloadConfig": { + "simpleParams": {} + }, + "histogramParams": { + "resolution": 0.01, + "maxPossible": 60000000000 + }, + "channelArgs": [ + { + "name": "grpc.optimization_target", + "strValue": "latency" + } + ] + }, + "numClients": 1, + "serverConfig": { + "serverType": "ASYNC_SERVER", + "securityParams": { + "useTestCa": true, + "serverHostOverride": "foo.test.google.fr" + }, + "channelArgs": [ + { + "name": "grpc.optimization_target", + "strValue": "latency" + } + ] + }, + "numServers": 1, + "warmupSeconds": 2, + "benchmarkSeconds": 10 + } + ] +} diff --git a/test/cpp/qps/BUILD b/test/cpp/qps/BUILD index 8855a1c155d..41ae5d41e0c 100644 --- a/test/cpp/qps/BUILD +++ b/test/cpp/qps/BUILD @@ -14,8 +14,10 @@ licenses(["notice"]) # Apache v2 -load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library", "grpc_cc_binary", "grpc_package") -load("//test/cpp/qps:qps_benchmark_script.bzl", "qps_json_driver_batch", "json_run_localhost_batch") +package(default_visibility = ["//visibility:public"]) + +load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package") +load("//test/cpp/qps:qps_benchmark_script.bzl", "json_run_localhost_batch", "qps_json_driver_batch") grpc_package(name = "test/cpp/qps") From 95d4120f4658716936437adccf40f8eda01229f4 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Tue, 22 Jan 2019 18:34:17 -0800 Subject: [PATCH 032/218] Add copyright to BUILD file --- src/python/grpcio_tests/tests/qps/BUILD | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/python/grpcio_tests/tests/qps/BUILD b/src/python/grpcio_tests/tests/qps/BUILD index c1eb6b8e11a..e1c7d138ef3 100644 --- a/src/python/grpcio_tests/tests/qps/BUILD +++ b/src/python/grpcio_tests/tests/qps/BUILD @@ -1,3 +1,17 @@ +# Copyright 2019 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. + package(default_visibility = ["//visibility:public"]) load("@grpc_python_dependencies//:requirements.bzl", "requirement") From 6ca6a060757cca9d268808f9ccfe295918f271e5 Mon Sep 17 00:00:00 2001 From: matoro Date: Fri, 28 Dec 2018 21:53:36 +0000 Subject: [PATCH 033/218] Ruby tooling: respect user toolchain overrides While compilation flag overrides for the Ruby native extension are currently functional, specifying an alternate compiler is not, as the Rbconfig values for key toolchain binaries are hardcoded at compile time of the Ruby interpreter. This patch allows them to be overrridden on the command line via standard environment variables, defaulting to the Rbconfig values only if unspecified by the user. --- src/ruby/ext/grpc/extconf.rb | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/ruby/ext/grpc/extconf.rb b/src/ruby/ext/grpc/extconf.rb index 505357021e0..9950976eeb1 100644 --- a/src/ruby/ext/grpc/extconf.rb +++ b/src/ruby/ext/grpc/extconf.rb @@ -24,10 +24,18 @@ grpc_config = ENV['GRPC_CONFIG'] || 'opt' ENV['MACOSX_DEPLOYMENT_TARGET'] = '10.7' -ENV['AR'] = RbConfig::CONFIG['AR'] + ' rcs' -ENV['CC'] = RbConfig::CONFIG['CC'] -ENV['CXX'] = RbConfig::CONFIG['CXX'] -ENV['LD'] = ENV['CC'] +if ENV['AR'].nil? || ENV['AR'].size == 0 + ENV['AR'] = RbConfig::CONFIG['AR'] + ' rcs' +end +if ENV['CC'].nil? || ENV['CC'].size == 0 + ENV['CC'] = RbConfig::CONFIG['CC'] +end +if ENV['CXX'].nil? || ENV['CXX'].size == 0 + ENV['CXX'] = RbConfig::CONFIG['CXX'] +end +if ENV['LD'].nil? || ENV['LD'].size == 0 + ENV['LD'] = ENV['CC'] +end ENV['AR'] = 'libtool -o' if RUBY_PLATFORM =~ /darwin/ From da9237a9c5566044974ac8e83d5830aeb71e9575 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Thu, 10 Jan 2019 18:49:09 -0800 Subject: [PATCH 034/218] Fix windows localhost address sorting bypass --- .../resolver/dns/c_ares/grpc_ares_wrapper.cc | 4 +- test/core/iomgr/resolve_address_test.cc | 103 +++++++++++++++++- 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc index 1a7e5d06268..d41c8238f1c 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc @@ -548,13 +548,13 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( r, name, default_port); // Early out if the target is an ipv4 or ipv6 literal. if (resolve_as_ip_literal_locked(name, default_port, addrs)) { - GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE); + grpc_ares_complete_request_locked(r); return r; } // Early out if the target is localhost and we're on Windows. if (grpc_ares_maybe_resolve_localhost_manually_locked(name, default_port, addrs)) { - GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE); + grpc_ares_complete_request_locked(r); return r; } // Don't query for SRV and TXT records if the target is "localhost", so diff --git a/test/core/iomgr/resolve_address_test.cc b/test/core/iomgr/resolve_address_test.cc index 1d9e1ee27e2..e1c58bed852 100644 --- a/test/core/iomgr/resolve_address_test.cc +++ b/test/core/iomgr/resolve_address_test.cc @@ -23,6 +23,8 @@ #include #include +#include + #include #include "src/core/lib/gpr/env.h" @@ -120,6 +122,35 @@ static void must_fail(void* argsp, grpc_error* err) { gpr_mu_unlock(args->mu); } +// This test assumes the environment has an ipv6 loopback +static void must_succeed_with_ipv6_first(void* argsp, grpc_error* err) { + args_struct* args = static_cast(argsp); + GPR_ASSERT(err == GRPC_ERROR_NONE); + GPR_ASSERT(args->addrs != nullptr); + GPR_ASSERT(args->addrs->naddrs > 0); + const struct sockaddr* first_address = + reinterpret_cast(args->addrs->addrs[0].addr); + GPR_ASSERT(first_address->sa_family == AF_INET6); + 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_succeed_with_ipv4_first(void* argsp, grpc_error* err) { + args_struct* args = static_cast(argsp); + GPR_ASSERT(err == GRPC_ERROR_NONE); + GPR_ASSERT(args->addrs != nullptr); + GPR_ASSERT(args->addrs->naddrs > 0); + const struct sockaddr* first_address = + reinterpret_cast(args->addrs->addrs[0].addr); + GPR_ASSERT(first_address->sa_family == AF_INET); + 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_localhost(void) { grpc_core::ExecCtx exec_ctx; args_struct args; @@ -146,6 +177,33 @@ static void test_default_port(void) { args_finish(&args); } +static void test_localhost_result_has_ipv6_first(void) { + grpc_core::ExecCtx exec_ctx; + args_struct args; + args_init(&args); + grpc_resolve_address("localhost:1", nullptr, args.pollset_set, + GRPC_CLOSURE_CREATE(must_succeed_with_ipv6_first, &args, + grpc_schedule_on_exec_ctx), + &args.addrs); + grpc_core::ExecCtx::Get()->Flush(); + poll_pollset_until_request_done(&args); + args_finish(&args); +} + +static void test_localhost_result_has_ipv4_first_when_ipv6_isnt_available( + void) { + grpc_core::ExecCtx exec_ctx; + args_struct args; + args_init(&args); + grpc_resolve_address("localhost:1", nullptr, args.pollset_set, + GRPC_CLOSURE_CREATE(must_succeed_with_ipv4_first, &args, + grpc_schedule_on_exec_ctx), + &args.addrs); + grpc_core::ExecCtx::Get()->Flush(); + poll_pollset_until_request_done(&args); + args_finish(&args); +} + static void test_non_numeric_default_port(void) { grpc_core::ExecCtx exec_ctx; args_struct args; @@ -245,6 +303,34 @@ static void test_unparseable_hostports(void) { } } +typedef struct mock_ipv6_disabled_source_addr_factory { + address_sorting_source_addr_factory base; +} mock_ipv6_disabled_source_addr_factory; + +static bool mock_ipv6_disabled_source_addr_factory_get_source_addr( + address_sorting_source_addr_factory* factory, + const address_sorting_address* dest_addr, + address_sorting_address* source_addr) { + // Mock lack of IPv6. For IPv4, set the source addr to be the same + // as the destination; tests won't actually connect on the result anyways. + if (address_sorting_abstract_get_family(dest_addr) == + ADDRESS_SORTING_AF_INET6) { + return false; + } + memcpy(source_addr->addr, &dest_addr->addr, dest_addr->len); + source_addr->len = dest_addr->len; + return true; +} + +void mock_ipv6_disabled_source_addr_factory_destroy( + address_sorting_source_addr_factory* factory) {} + +const address_sorting_source_addr_factory_vtable + kMockIpv6DisabledSourceAddrFactoryVtable = { + mock_ipv6_disabled_source_addr_factory_get_source_addr, + mock_ipv6_disabled_source_addr_factory_destroy, +}; + int main(int argc, char** argv) { // First set the resolver type based off of --resolver const char* resolver_type = nullptr; @@ -289,11 +375,26 @@ int main(int argc, char** argv) { // these unit tests under c-ares risks flakiness. test_invalid_ip_addresses(); test_unparseable_hostports(); + } else { + test_localhost_result_has_ipv6_first(); } grpc_executor_shutdown(); } gpr_cmdline_destroy(cl); - grpc_shutdown(); + // The following test uses + // "address_sorting_override_source_addr_factory_for_testing", which works + // on a per-grpc-init basis, and so it's simplest to run this next test + // within a standalone grpc_init/grpc_shutdown pair. + if (gpr_stricmp(resolver_type, "ares") == 0) { + // Run a test case in which c-ares's address sorter + // thinks that IPv4 is available and IPv6 isn't. + grpc_init(); + mock_ipv6_disabled_source_addr_factory factory; + factory.base.vtable = &kMockIpv6DisabledSourceAddrFactoryVtable; + address_sorting_override_source_addr_factory_for_testing(&factory.base); + test_localhost_result_has_ipv4_first_when_ipv6_isnt_available(); + grpc_shutdown(); + } return 0; } From fab05d336c311b83a7f9b6acecd40ab1b6bbe8f7 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Wed, 9 Jan 2019 21:49:24 -0800 Subject: [PATCH 035/218] Dynamic callback requesting, graceful server shutdown, and separate ExecCtx for callbacks --- include/grpc/impl/codegen/grpc_types.h | 4 + include/grpcpp/server.h | 30 ++- src/core/lib/iomgr/exec_ctx.cc | 1 + src/core/lib/iomgr/exec_ctx.h | 57 ++++- src/core/lib/iomgr/executor.cc | 7 + src/core/lib/iomgr/timer_manager.cc | 7 + src/core/lib/surface/call.cc | 6 +- src/core/lib/surface/completion_queue.cc | 5 +- src/core/lib/surface/server.cc | 23 +- src/cpp/common/alarm.cc | 3 + src/cpp/server/server_cc.cc | 220 +++++++++++++----- test/core/surface/completion_queue_test.cc | 69 +++--- .../microbenchmarks/bm_chttp2_transport.cc | 2 - 13 files changed, 323 insertions(+), 111 deletions(-) diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index 8d7c21107f4..79b182c4515 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -693,6 +693,10 @@ typedef struct grpc_experimental_completion_queue_functor { pointer to this functor and a boolean that indicates whether the operation succeeded (non-zero) or failed (zero) */ void (*functor_run)(struct grpc_experimental_completion_queue_functor*, int); + + /** The following fields are not API. They are meant for internal use. */ + int internal_success; + struct grpc_experimental_completion_queue_functor* internal_next; } grpc_experimental_completion_queue_functor; /* The upgrade to version 2 is currently experimental. */ diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index cdcac186cb6..5bbbd704a02 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -248,8 +248,22 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { /// the \a sync_server_cqs) std::vector> sync_req_mgrs_; - /// Outstanding callback requests - std::vector> callback_reqs_; + // Outstanding callback requests. The vector is indexed by method with a + // list per method. Each element should store its own iterator + // in the list and should erase it when the request is actually bound to + // an RPC. Synchronize this list with its own mu_ (not the server mu_) since + // these must be active at Shutdown when the server mu_ is locked + // TODO(vjpai): Merge with the core request matcher to avoid duplicate work + struct MethodReqList { + std::mutex reqs_mu; + // Maintain our own list size count since list::size is still linear + // for some libraries (supposed to be constant since C++11) + // TODO(vjpai): Remove reqs_list_sz and use list::size when possible + size_t reqs_list_sz{0}; + std::list reqs_list; + using iterator = decltype(reqs_list)::iterator; + }; + std::vector callback_reqs_; // Server status std::mutex mu_; @@ -259,6 +273,18 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { std::condition_variable shutdown_cv_; + // It is ok (but not required) to nest callback_reqs_mu_ under mu_ . + // Incrementing callback_reqs_outstanding_ is ok without a lock + // but it should only be decremented under the lock in case it is the + // last request and enables the server shutdown. The increment is + // performance-critical since it happens during periods of increasing + // load; the decrement happens only when memory is maxed out, during server + // shutdown, or (possibly in a future version) during decreasing load, so + // it is less performance-critical. + std::mutex callback_reqs_mu_; + std::condition_variable callback_reqs_done_cv_; + std::atomic_int callback_reqs_outstanding_{0}; + std::shared_ptr global_callbacks_; std::vector services_; diff --git a/src/core/lib/iomgr/exec_ctx.cc b/src/core/lib/iomgr/exec_ctx.cc index 683dd2f6493..f45def43397 100644 --- a/src/core/lib/iomgr/exec_ctx.cc +++ b/src/core/lib/iomgr/exec_ctx.cc @@ -115,6 +115,7 @@ grpc_closure_scheduler* grpc_schedule_on_exec_ctx = &exec_ctx_scheduler; namespace grpc_core { GPR_TLS_CLASS_DEF(ExecCtx::exec_ctx_); +GPR_TLS_CLASS_DEF(ApplicationCallbackExecCtx::callback_exec_ctx_); // WARNING: for testing purposes only! void ExecCtx::TestOnlyGlobalInit(gpr_timespec new_val) { diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index e90eb54cd35..36c1a907cbc 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -21,12 +21,14 @@ #include +#include #include #include #include #include "src/core/lib/gpr/tls.h" #include "src/core/lib/gprpp/fork.h" +#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/iomgr/closure.h" typedef int64_t grpc_millis; @@ -34,9 +36,8 @@ typedef int64_t grpc_millis; #define GRPC_MILLIS_INF_FUTURE INT64_MAX #define GRPC_MILLIS_INF_PAST INT64_MIN -/** A workqueue represents a list of work to be executed asynchronously. - Forward declared here to avoid a circular dependency with workqueue.h. */ -typedef struct grpc_workqueue grpc_workqueue; +/** A combiner represents a list of work to be executed later. + Forward declared here to avoid a circular dependency with combiner.h. */ typedef struct grpc_combiner grpc_combiner; /* This exec_ctx is ready to return: either pre-populated, or cached as soon as @@ -226,6 +227,56 @@ class ExecCtx { GPR_TLS_CLASS_DECL(exec_ctx_); ExecCtx* last_exec_ctx_ = Get(); }; + +class ApplicationCallbackExecCtx { + public: + ApplicationCallbackExecCtx() { + if (reinterpret_cast( + gpr_tls_get(&callback_exec_ctx_)) == nullptr) { + grpc_core::Fork::IncExecCtxCount(); + gpr_tls_set(&callback_exec_ctx_, reinterpret_cast(this)); + } + } + ~ApplicationCallbackExecCtx() { + if (reinterpret_cast( + gpr_tls_get(&callback_exec_ctx_)) == this) { + while (head_ != nullptr) { + auto* f = head_; + head_ = f->internal_next; + if (f->internal_next == nullptr) { + tail_ = nullptr; + } + (*f->functor_run)(f, f->internal_success); + } + gpr_tls_set(&callback_exec_ctx_, reinterpret_cast(nullptr)); + grpc_core::Fork::DecExecCtxCount(); + } else { + GPR_DEBUG_ASSERT(head_ == nullptr); + GPR_DEBUG_ASSERT(tail_ == nullptr); + } + } + static void Enqueue(grpc_experimental_completion_queue_functor* functor, + int is_success) { + functor->internal_success = is_success; + functor->internal_next = nullptr; + + auto* ctx = reinterpret_cast( + gpr_tls_get(&callback_exec_ctx_)); + + if (ctx->head_ == nullptr) { + ctx->head_ = functor; + } + if (ctx->tail_ != nullptr) { + ctx->tail_->internal_next = functor; + } + ctx->tail_ = functor; + } + + private: + grpc_experimental_completion_queue_functor* head_{nullptr}; + grpc_experimental_completion_queue_functor* tail_{nullptr}; + GPR_TLS_CLASS_DECL(callback_exec_ctx_); +}; } // namespace grpc_core #endif /* GRPC_CORE_LIB_IOMGR_EXEC_CTX_H */ diff --git a/src/core/lib/iomgr/executor.cc b/src/core/lib/iomgr/executor.cc index 2703e1a0b77..34683273cf6 100644 --- a/src/core/lib/iomgr/executor.cc +++ b/src/core/lib/iomgr/executor.cc @@ -111,6 +111,13 @@ size_t Executor::RunClosures(const char* executor_name, grpc_closure_list list) { size_t n = 0; + // In the executor, the ExecCtx for the thread is declared + // in the executor thread itself, but this is the point where we + // could start seeing application-level callbacks. No need to + // create a new ExecCtx, though, since there already is one and it is + // flushed (but not destructed) in this function itself + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_closure* c = list.head; while (c != nullptr) { grpc_closure* next = c->next_data.next; diff --git a/src/core/lib/iomgr/timer_manager.cc b/src/core/lib/iomgr/timer_manager.cc index cb123298cf5..1da242938a2 100644 --- a/src/core/lib/iomgr/timer_manager.cc +++ b/src/core/lib/iomgr/timer_manager.cc @@ -105,6 +105,13 @@ void grpc_timer_manager_tick() { } static void run_some_timers() { + // In the case of timers, the ExecCtx for the thread is declared + // in the timer thread itself, but this is the point where we + // could start seeing application-level callbacks. No need to + // create a new ExecCtx, though, since there already is one and it is + // flushed (but not destructed) in this function itself + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + // if there's something to execute... gpr_mu_lock(&g_mu); // remove a waiter from the pool, and start another thread if necessary diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 89b3f77822c..d53eb704420 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -556,6 +556,7 @@ void grpc_call_unref(grpc_call* c) { GPR_TIMER_SCOPE("grpc_call_unref", 0); child_call* cc = c->child; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_call_unref(c=%p)", 1, (c)); @@ -597,6 +598,7 @@ void grpc_call_unref(grpc_call* c) { grpc_call_error grpc_call_cancel(grpc_call* call, void* reserved) { GRPC_API_TRACE("grpc_call_cancel(call=%p, reserved=%p)", 2, (call, reserved)); GPR_ASSERT(!reserved); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; cancel_with_error(call, GRPC_ERROR_CANCELLED); return GRPC_CALL_OK; @@ -646,6 +648,7 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call* c, grpc_status_code status, const char* description, void* reserved) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE( "grpc_call_cancel_with_status(" @@ -1894,7 +1897,6 @@ done_with_error: grpc_call_error grpc_call_start_batch(grpc_call* call, const grpc_op* ops, size_t nops, void* tag, void* reserved) { - grpc_core::ExecCtx exec_ctx; grpc_call_error err; GRPC_API_TRACE( @@ -1905,6 +1907,8 @@ grpc_call_error grpc_call_start_batch(grpc_call* call, const grpc_op* ops, if (reserved != nullptr) { err = GRPC_CALL_ERROR; } else { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_core::ExecCtx exec_ctx; err = call_start_batch(call, ops, nops, tag, 0); } diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc index 661022ec5f1..426a4a3f24e 100644 --- a/src/core/lib/surface/completion_queue.cc +++ b/src/core/lib/surface/completion_queue.cc @@ -868,7 +868,7 @@ static void cq_end_op_for_callback( GRPC_ERROR_UNREF(error); auto* functor = static_cast(tag); - (*functor->functor_run)(functor, is_success); + grpc_core::ApplicationCallbackExecCtx::Enqueue(functor, is_success); } void grpc_cq_end_op(grpc_completion_queue* cq, void* tag, grpc_error* error, @@ -1352,7 +1352,7 @@ static void cq_finish_shutdown_callback(grpc_completion_queue* cq) { GPR_ASSERT(cqd->shutdown_called); cq->poller_vtable->shutdown(POLLSET_FROM_CQ(cq), &cq->pollset_shutdown_done); - (*callback->functor_run)(callback, true); + grpc_core::ApplicationCallbackExecCtx::Enqueue(callback, true); } static void cq_shutdown_callback(grpc_completion_queue* cq) { @@ -1385,6 +1385,7 @@ static void cq_shutdown_callback(grpc_completion_queue* cq) { to zero here, then enter shutdown mode and wake up any waiters */ void grpc_completion_queue_shutdown(grpc_completion_queue* cq) { GPR_TIMER_SCOPE("grpc_completion_queue_shutdown", 0); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_completion_queue_shutdown(cq=%p)", 1, (cq)); cq->vtable->shutdown(cq); diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc index cdfd3336437..c20796f5acf 100644 --- a/src/core/lib/surface/server.cc +++ b/src/core/lib/surface/server.cc @@ -1302,6 +1302,7 @@ void grpc_server_shutdown_and_notify(grpc_server* server, listener* l; shutdown_tag* sdt; channel_broadcaster broadcaster; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_server_shutdown_and_notify(server=%p, cq=%p, tag=%p)", 3, @@ -1369,6 +1370,7 @@ void grpc_server_shutdown_and_notify(grpc_server* server, void grpc_server_cancel_all_calls(grpc_server* server) { channel_broadcaster broadcaster; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_server_cancel_all_calls(server=%p)", 1, (server)); @@ -1384,6 +1386,7 @@ void grpc_server_cancel_all_calls(grpc_server* server) { void grpc_server_destroy(grpc_server* server) { listener* l; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_server_destroy(server=%p)", 1, (server)); @@ -1469,6 +1472,7 @@ grpc_call_error grpc_server_request_call( grpc_completion_queue* cq_bound_to_call, grpc_completion_queue* cq_for_notification, void* tag) { grpc_call_error error; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; requested_call* rc = static_cast(gpr_malloc(sizeof(*rc))); GRPC_STATS_INC_SERVER_REQUESTED_CALLS(); @@ -1515,11 +1519,11 @@ grpc_call_error grpc_server_request_registered_call( grpc_metadata_array* initial_metadata, grpc_byte_buffer** optional_payload, grpc_completion_queue* cq_bound_to_call, grpc_completion_queue* cq_for_notification, void* tag) { - grpc_call_error error; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; + GRPC_STATS_INC_SERVER_REQUESTED_CALLS(); requested_call* rc = static_cast(gpr_malloc(sizeof(*rc))); registered_method* rm = static_cast(rmp); - GRPC_STATS_INC_SERVER_REQUESTED_CALLS(); GRPC_API_TRACE( "grpc_server_request_registered_call(" "server=%p, rmp=%p, call=%p, deadline=%p, initial_metadata=%p, " @@ -1537,19 +1541,17 @@ grpc_call_error grpc_server_request_registered_call( } if (cq_idx == server->cq_count) { gpr_free(rc); - error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE; - goto done; + return GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE; } if ((optional_payload == nullptr) != (rm->payload_handling == GRPC_SRM_PAYLOAD_NONE)) { gpr_free(rc); - error = GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH; - goto done; + return GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH; } + if (grpc_cq_begin_op(cq_for_notification, tag) == false) { gpr_free(rc); - error = GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN; - goto done; + return GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN; } rc->cq_idx = cq_idx; rc->type = REGISTERED_CALL; @@ -1561,10 +1563,7 @@ grpc_call_error grpc_server_request_registered_call( rc->data.registered.deadline = deadline; rc->initial_metadata = initial_metadata; rc->data.registered.optional_payload = optional_payload; - error = queue_call_request(server, cq_idx, rc); -done: - - return error; + return queue_call_request(server, cq_idx, rc); } static void fail_call(grpc_server* server, size_t cq_idx, requested_call* rc, diff --git a/src/cpp/common/alarm.cc b/src/cpp/common/alarm.cc index 148f0b9bc94..6bfe26f04c4 100644 --- a/src/cpp/common/alarm.cc +++ b/src/cpp/common/alarm.cc @@ -52,6 +52,7 @@ class AlarmImpl : public ::grpc::internal::CompletionQueueTag { return true; } void Set(::grpc::CompletionQueue* cq, gpr_timespec deadline, void* tag) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_CQ_INTERNAL_REF(cq->cq(), "alarm"); cq_ = cq->cq(); @@ -72,6 +73,7 @@ class AlarmImpl : public ::grpc::internal::CompletionQueueTag { &on_alarm_); } void Set(gpr_timespec deadline, std::function f) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; // Don't use any CQ at all. Instead just use the timer to fire the function callback_ = std::move(f); @@ -87,6 +89,7 @@ class AlarmImpl : public ::grpc::internal::CompletionQueueTag { &on_alarm_); } void Cancel() { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; grpc_timer_cancel(&timer_); } diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 13741ce7aa5..12aa52ef704 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -59,7 +59,15 @@ namespace { #define DEFAULT_MAX_SYNC_SERVER_THREADS INT_MAX // How many callback requests of each method should we pre-register at start -#define DEFAULT_CALLBACK_REQS_PER_METHOD 32 +#define DEFAULT_CALLBACK_REQS_PER_METHOD 512 + +// What is the (soft) limit for outstanding requests in the server +#define MAXIMUM_CALLBACK_REQS_OUTSTANDING 30000 + +// If the number of unmatched requests for a method drops below this amount, +// try to allocate extra unless it pushes the total number of callbacks above +// the soft maximum +#define SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD 128 class DefaultGlobalCallbacks final : public Server::GlobalCallbacks { public: @@ -343,9 +351,10 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { class Server::CallbackRequest final : public internal::CompletionQueueTag { public: - CallbackRequest(Server* server, internal::RpcServiceMethod* method, - void* method_tag) + CallbackRequest(Server* server, Server::MethodReqList* list, + internal::RpcServiceMethod* method, void* method_tag) : server_(server), + req_list_(list), method_(method), method_tag_(method_tag), has_request_payload_( @@ -353,12 +362,22 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { method->method_type() == internal::RpcMethod::SERVER_STREAMING), cq_(server->CallbackCQ()), tag_(this) { + server_->callback_reqs_outstanding_++; Setup(); } - ~CallbackRequest() { Clear(); } + ~CallbackRequest() { + Clear(); - void Request() { + // The counter of outstanding requests must be decremented + // under a lock in case it causes the server shutdown. + std::lock_guard l(server_->callback_reqs_mu_); + if (--server_->callback_reqs_outstanding_ == 0) { + server_->callback_reqs_done_cv_.notify_one(); + } + } + + bool Request() { if (method_tag_) { if (GRPC_CALL_OK != grpc_server_request_registered_call( @@ -366,7 +385,7 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { &request_metadata_, has_request_payload_ ? &request_payload_ : nullptr, cq_->cq(), cq_->cq(), static_cast(&tag_))) { - return; + return false; } } else { if (!call_details_) { @@ -376,9 +395,10 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { if (grpc_server_request_call(server_->c_server(), &call_, call_details_, &request_metadata_, cq_->cq(), cq_->cq(), static_cast(&tag_)) != GRPC_CALL_OK) { - return; + return false; } } + return true; } bool FinalizeResult(void** tag, bool* status) override { return false; } @@ -409,10 +429,48 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { GPR_ASSERT(!req_->FinalizeResult(&ignored, &new_ok)); GPR_ASSERT(ignored == req_); - if (!ok) { - // The call has been shutdown - req_->Clear(); - return; + bool spawn_new = false; + { + std::unique_lock l(req_->req_list_->reqs_mu); + req_->req_list_->reqs_list.erase(req_->req_list_iterator_); + req_->req_list_->reqs_list_sz--; + if (!ok) { + // The call has been shutdown. + // Delete its contents to free up the request. + // First release the lock in case the deletion of the request + // completes the full server shutdown and allows the destructor + // of the req_list to proceed. + l.unlock(); + delete req_; + return; + } + + // If this was the last request in the list or it is below the soft + // minimum and there are spare requests available, set up a new one, but + // do it outside the lock since the Request could otherwise deadlock + if (req_->req_list_->reqs_list_sz == 0 || + (req_->req_list_->reqs_list_sz < + SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD && + req_->server_->callback_reqs_outstanding_ < + MAXIMUM_CALLBACK_REQS_OUTSTANDING)) { + spawn_new = true; + } + } + if (spawn_new) { + auto* new_req = new CallbackRequest(req_->server_, req_->req_list_, + req_->method_, req_->method_tag_); + if (!new_req->Request()) { + // The server must have just decided to shutdown. Erase + // from the list under lock but release the lock before + // deleting the new_req (in case that request was what + // would allow the destruction of the req_list) + { + std::lock_guard l(new_req->req_list_->reqs_mu); + new_req->req_list_->reqs_list.erase(new_req->req_list_iterator_); + new_req->req_list_->reqs_list_sz--; + } + delete new_req; + } } // Bind the call, deadline, and metadata from what we got @@ -462,17 +520,30 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { internal::MethodHandler::HandlerParameter( call_, &req_->ctx_, req_->request_, req_->request_status_, [this] { - req_->Reset(); - req_->Request(); + // Recycle this request if there aren't too many outstanding. + // Note that we don't have to worry about a case where there + // are no requests waiting to match for this method since that + // is already taken care of when binding a request to a call. + // TODO(vjpai): Also don't recycle this request if the dynamic + // load no longer justifies it. Consider measuring + // dynamic load and setting a target accordingly. + if (req_->server_->callback_reqs_outstanding_ < + MAXIMUM_CALLBACK_REQS_OUTSTANDING) { + req_->Clear(); + req_->Setup(); + } else { + // We can free up this request because there are too many + delete req_; + return; + } + if (!req_->Request()) { + // The server must have just decided to shutdown. + delete req_; + } })); } }; - void Reset() { - Clear(); - Setup(); - } - void Clear() { if (call_details_) { delete call_details_; @@ -492,9 +563,15 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { request_payload_ = nullptr; request_ = nullptr; request_status_ = Status(); + std::lock_guard l(req_list_->reqs_mu); + req_list_->reqs_list.push_front(this); + req_list_->reqs_list_sz++; + req_list_iterator_ = req_list_->reqs_list.begin(); } Server* const server_; + Server::MethodReqList* req_list_; + Server::MethodReqList::iterator req_list_iterator_; internal::RpcServiceMethod* const method_; void* const method_tag_; const bool has_request_payload_; @@ -715,6 +792,13 @@ Server::~Server() { } grpc_server_destroy(server_); + for (auto* method_list : callback_reqs_) { + // The entries of the method_list should have already been emptied + // during Shutdown as each request is failed by Shutdown. Check that + // this actually happened. + GPR_ASSERT(method_list->reqs_list.empty()); + delete method_list; + } } void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) { @@ -794,10 +878,12 @@ bool Server::RegisterService(const grpc::string* host, Service* service) { } } else { // a callback method. Register at least some callback requests + callback_reqs_.push_back(new Server::MethodReqList); + auto* method_req_list = callback_reqs_.back(); // TODO(vjpai): Register these dynamically based on need for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) { - auto* req = new CallbackRequest(this, method, method_registration_tag); - callback_reqs_.emplace_back(req); + new CallbackRequest(this, method_req_list, method, + method_registration_tag); } // Enqueue it so that it will be Request'ed later once // all request matchers are created at core server startup @@ -889,8 +975,10 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { (*it)->Start(); } - for (auto& cbreq : callback_reqs_) { - cbreq->Request(); + for (auto* cbmethods : callback_reqs_) { + for (auto* cbreq : cbmethods->reqs_list) { + GPR_ASSERT(cbreq->Request()); + } } if (default_health_check_service_impl != nullptr) { @@ -900,49 +988,69 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { void Server::ShutdownInternal(gpr_timespec deadline) { std::unique_lock lock(mu_); - if (!shutdown_) { - shutdown_ = true; + if (shutdown_) { + return; + } - /// The completion queue to use for server shutdown completion notification - CompletionQueue shutdown_cq; - ShutdownTag shutdown_tag; // Dummy shutdown tag - grpc_server_shutdown_and_notify(server_, shutdown_cq.cq(), &shutdown_tag); + shutdown_ = true; - shutdown_cq.Shutdown(); + /// The completion queue to use for server shutdown completion notification + CompletionQueue shutdown_cq; + ShutdownTag shutdown_tag; // Dummy shutdown tag + grpc_server_shutdown_and_notify(server_, shutdown_cq.cq(), &shutdown_tag); - void* tag; - bool ok; - CompletionQueue::NextStatus status = - shutdown_cq.AsyncNext(&tag, &ok, deadline); + shutdown_cq.Shutdown(); - // If this timed out, it means we are done with the grace period for a clean - // shutdown. We should force a shutdown now by cancelling all inflight calls - if (status == CompletionQueue::NextStatus::TIMEOUT) { - grpc_server_cancel_all_calls(server_); - } - // Else in case of SHUTDOWN or GOT_EVENT, it means that the server has - // successfully shutdown + void* tag; + bool ok; + CompletionQueue::NextStatus status = + shutdown_cq.AsyncNext(&tag, &ok, deadline); - // Shutdown all ThreadManagers. This will try to gracefully stop all the - // threads in the ThreadManagers (once they process any inflight requests) - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->Shutdown(); // ThreadManager's Shutdown() - } + // If this timed out, it means we are done with the grace period for a clean + // shutdown. We should force a shutdown now by cancelling all inflight calls + if (status == CompletionQueue::NextStatus::TIMEOUT) { + grpc_server_cancel_all_calls(server_); + } + // Else in case of SHUTDOWN or GOT_EVENT, it means that the server has + // successfully shutdown - // Wait for threads in all ThreadManagers to terminate - for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { - (*it)->Wait(); - } + // Shutdown all ThreadManagers. This will try to gracefully stop all the + // threads in the ThreadManagers (once they process any inflight requests) + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->Shutdown(); // ThreadManager's Shutdown() + } - // Drain the shutdown queue (if the previous call to AsyncNext() timed out - // and we didn't remove the tag from the queue yet) - while (shutdown_cq.Next(&tag, &ok)) { - // Nothing to be done here. Just ignore ok and tag values - } + // Wait for threads in all ThreadManagers to terminate + for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) { + (*it)->Wait(); + } - shutdown_notified_ = true; - shutdown_cv_.notify_all(); + // Wait for all outstanding callback requests to complete + // (whether waiting for a match or already active). + // We know that no new requests will be created after this point + // because they are only created at server startup time or when + // we have a successful match on a request. During the shutdown phase, + // requests that have not yet matched will be failed rather than + // allowed to succeed, which will cause the server to delete the + // request and decrement the count. Possibly a request will match before + // the shutdown but then find that shutdown has already started by the + // time it tries to register a new request. In that case, the registration + // will report a failure, indicating a shutdown and again we won't end + // up incrementing the counter. + { + std::unique_lock cblock(callback_reqs_mu_); + callback_reqs_done_cv_.wait( + cblock, [this] { return callback_reqs_outstanding_ == 0; }); + } + + // Drain the shutdown queue (if the previous call to AsyncNext() timed out + // and we didn't remove the tag from the queue yet) + while (shutdown_cq.Next(&tag, &ok)) { + // Nothing to be done here. Just ignore ok and tag values } + + shutdown_notified_ = true; + shutdown_cv_.notify_all(); } void Server::Wait() { diff --git a/test/core/surface/completion_queue_test.cc b/test/core/surface/completion_queue_test.cc index a157d75edab..7c3630eaf18 100644 --- a/test/core/surface/completion_queue_test.cc +++ b/test/core/surface/completion_queue_test.cc @@ -389,46 +389,49 @@ static void test_callback(void) { attr.cq_shutdown_cb = &shutdown_cb; for (size_t pidx = 0; pidx < GPR_ARRAY_SIZE(polling_types); pidx++) { - grpc_core::ExecCtx exec_ctx; // reset exec_ctx - attr.cq_polling_type = polling_types[pidx]; - cc = grpc_completion_queue_create( - grpc_completion_queue_factory_lookup(&attr), &attr, nullptr); - + int sumtags = 0; int counter = 0; - class TagCallback : public grpc_experimental_completion_queue_functor { - public: - TagCallback(int* counter, int tag) : counter_(counter), tag_(tag) { - functor_run = &TagCallback::Run; - } - ~TagCallback() {} - static void Run(grpc_experimental_completion_queue_functor* cb, int ok) { - GPR_ASSERT(static_cast(ok)); - auto* callback = static_cast(cb); - *callback->counter_ += callback->tag_; - grpc_core::Delete(callback); + { + // reset exec_ctx types + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_core::ExecCtx exec_ctx; + attr.cq_polling_type = polling_types[pidx]; + cc = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&attr), &attr, nullptr); + + class TagCallback : public grpc_experimental_completion_queue_functor { + public: + TagCallback(int* counter, int tag) : counter_(counter), tag_(tag) { + functor_run = &TagCallback::Run; + } + ~TagCallback() {} + static void Run(grpc_experimental_completion_queue_functor* cb, + int ok) { + GPR_ASSERT(static_cast(ok)); + auto* callback = static_cast(cb); + *callback->counter_ += callback->tag_; + grpc_core::Delete(callback); + }; + + private: + int* counter_; + int tag_; }; - private: - int* counter_; - int tag_; - }; + for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { + tags[i] = static_cast(grpc_core::New(&counter, i)); + sumtags += i; + } - int sumtags = 0; - for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { - tags[i] = static_cast(grpc_core::New(&counter, i)); - sumtags += i; - } + for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { + GPR_ASSERT(grpc_cq_begin_op(cc, tags[i])); + grpc_cq_end_op(cc, tags[i], GRPC_ERROR_NONE, do_nothing_end_completion, + nullptr, &completions[i]); + } - for (i = 0; i < GPR_ARRAY_SIZE(tags); i++) { - GPR_ASSERT(grpc_cq_begin_op(cc, tags[i])); - grpc_cq_end_op(cc, tags[i], GRPC_ERROR_NONE, do_nothing_end_completion, - nullptr, &completions[i]); + shutdown_and_destroy(cc); } - GPR_ASSERT(sumtags == counter); - - shutdown_and_destroy(cc); - GPR_ASSERT(got_shutdown); got_shutdown = false; } diff --git a/test/cpp/microbenchmarks/bm_chttp2_transport.cc b/test/cpp/microbenchmarks/bm_chttp2_transport.cc index 650152ecc0d..dcfaa684773 100644 --- a/test/cpp/microbenchmarks/bm_chttp2_transport.cc +++ b/test/cpp/microbenchmarks/bm_chttp2_transport.cc @@ -101,8 +101,6 @@ class DummyEndpoint : public grpc_endpoint { GRPC_CLOSURE_SCHED(cb, GRPC_ERROR_NONE); } - static grpc_workqueue* get_workqueue(grpc_endpoint* ep) { return nullptr; } - static void add_to_pollset(grpc_endpoint* ep, grpc_pollset* pollset) {} static void add_to_pollset_set(grpc_endpoint* ep, grpc_pollset_set* pollset) { From e230b2fce919b6d9ed9c97df12f337a28edb58ec Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Fri, 18 Jan 2019 16:56:29 -0800 Subject: [PATCH 036/218] Don't offload write to executor if already running from a background thread --- src/core/ext/transport/chttp2/transport/chttp2_transport.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index fe88d4818e4..c2b57ed2905 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -43,6 +43,7 @@ #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" @@ -963,6 +964,10 @@ void grpc_chttp2_mark_stream_writable(grpc_chttp2_transport* t, static grpc_closure_scheduler* write_scheduler(grpc_chttp2_transport* t, bool early_results_scheduled, bool partial_write) { + // If we're already in a background poller, don't offload this to an executor + if (grpc_iomgr_is_any_background_poller_thread()) { + return grpc_schedule_on_exec_ctx; + } /* if it's not the first write in a batch, always offload to the executor: we'll probably end up queuing against the kernel anyway, so we'll likely get better latency overall if we switch writing work elsewhere and continue From 7b7d52e4cc0ccd7c1dc76afe9c9387f32edf399e Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Wed, 23 Jan 2019 11:42:45 -0800 Subject: [PATCH 037/218] Condition another executor offload on stream destruction --- src/core/lib/transport/transport.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/lib/transport/transport.cc b/src/core/lib/transport/transport.cc index 43add28ce03..8be0b91b654 100644 --- a/src/core/lib/transport/transport.cc +++ b/src/core/lib/transport/transport.cc @@ -30,6 +30,7 @@ #include "src/core/lib/gpr/alloc.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/executor.h" +#include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/transport/transport_impl.h" @@ -63,8 +64,9 @@ void grpc_stream_unref(grpc_stream_refcount* refcount, const char* reason) { void grpc_stream_unref(grpc_stream_refcount* refcount) { #endif if (gpr_unref(&refcount->refs)) { - if (grpc_core::ExecCtx::Get()->flags() & - GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP) { + if (!grpc_iomgr_is_any_background_poller_thread() && + (grpc_core::ExecCtx::Get()->flags() & + GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP)) { /* Ick. The thread we're running on MAY be owned (indirectly) by a call-stack. If that's the case, destroying the call-stack MAY try to destroy the From b60c5cdc82ef8a037cc8a83806f681267570aa46 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Wed, 23 Jan 2019 12:26:05 -0800 Subject: [PATCH 038/218] Adopte reviewer's suggestion --- src/python/grpcio_tests/tests/qps/README.md | 2 +- src/python/grpcio_tests/tests/qps/basic_benchmark_test.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/python/grpcio_tests/tests/qps/README.md b/src/python/grpcio_tests/tests/qps/README.md index 504a2189f73..f5149509ce3 100644 --- a/src/python/grpcio_tests/tests/qps/README.md +++ b/src/python/grpcio_tests/tests/qps/README.md @@ -21,7 +21,7 @@ Here I picked the top 2 most representative scenarios of them, and reduce their ## Why keep the scenario file if it can be generated? -Well... The `tools/run_tests/performance/scenario_config.py` is 1274 lines long. The intention of building these benchmark tools is reducing the complexity of existing infrastructure code. Depending on something that is +Well... The `tools/run_tests/performance/scenario_config.py` is 1274 lines long. The intention of building these benchmark tools is reducing the complexity of existing infrastructure code. So, instead of calling layers of abstraction to generate the scenario file, keeping a valid static copy is more preferable. ## How to run it? diff --git a/src/python/grpcio_tests/tests/qps/basic_benchmark_test.sh b/src/python/grpcio_tests/tests/qps/basic_benchmark_test.sh index 6011a7e01c2..fecb528396a 100755 --- a/src/python/grpcio_tests/tests/qps/basic_benchmark_test.sh +++ b/src/python/grpcio_tests/tests/qps/basic_benchmark_test.sh @@ -22,10 +22,10 @@ SCENARIOS_FILE=src/python/grpcio_tests/tests/qps/scenarios.json function join { local IFS="$1"; shift; echo "$*"; } if [[ -e "${SCENARIOS_FILE}" ]]; then - echo "Running against scenarios.json:" + echo "Running against ${SCENARIOS_FILE}:" cat "${SCENARIOS_FILE}" else - echo "Failed to find scenarios.json!" + echo "Failed to find ${SCENARIOS_FILE}!" exit 1 fi From 3a429ecd552b46d29b5266ad0c5ed8bdaa2b8814 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Wed, 23 Jan 2019 17:08:14 -0800 Subject: [PATCH 039/218] Attempt to fix internal segv --- src/core/ext/filters/client_channel/subchannel.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 0c75ee046d9..8708cf21c3b 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -202,6 +202,7 @@ class ConnectedSubchannelStateWatcher // Must be instantiated while holding c->mu. explicit ConnectedSubchannelStateWatcher(grpc_subchannel* c) : subchannel_(c) { + gpr_mu_init(&mu_); // Steal subchannel ref for connecting. GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "state_watcher"); GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "connecting"); @@ -234,9 +235,13 @@ class ConnectedSubchannelStateWatcher ~ConnectedSubchannelStateWatcher() { GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "state_watcher"); + gpr_mu_destroy(&mu_); } - void Orphan() override { health_check_client_.reset(); } + void Orphan() override { + MutexLock lock(&mu_); + health_check_client_.reset(); + } private: static void OnConnectivityChanged(void* arg, grpc_error* error) { @@ -302,6 +307,7 @@ class ConnectedSubchannelStateWatcher static void OnHealthChanged(void* arg, grpc_error* error) { auto* self = static_cast(arg); + MutexLock health_state_lock(&self->mu_); if (self->health_state_ == GRPC_CHANNEL_SHUTDOWN) { self->Unref(); return; @@ -324,6 +330,8 @@ class ConnectedSubchannelStateWatcher grpc_core::OrphanablePtr health_check_client_; grpc_closure on_health_changed_; grpc_connectivity_state health_state_ = GRPC_CHANNEL_CONNECTING; + // Ensure atomic change to health_check_client_ and health_state_. + gpr_mu mu_; }; } // namespace grpc_core From d347ec7ce08db6e60130fe196540655995e71809 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 23 Jan 2019 19:11:51 -0800 Subject: [PATCH 040/218] Register for cq avalanching when interceptors are going to be run --- include/grpcpp/impl/codegen/call_op_set.h | 6 ++++ .../grpcpp/impl/codegen/completion_queue.h | 6 ++++ .../server_interceptors_end2end_test.cc | 35 +++++++++++-------- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index c0de5ed6025..521cafe439b 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -870,6 +871,9 @@ class CallOpSet : public CallOpSetInterface, if (RunInterceptors()) { ContinueFillOpsAfterInterception(); } else { + // This call is going to go through interceptors and would need to + // schedule new batches, so delay completion queue shutdown + call_.cq()->RegisterAvalanching(); // After the interceptors are run, ContinueFillOpsAfterInterception will // be run } @@ -947,6 +951,8 @@ class CallOpSet : public CallOpSetInterface, GPR_CODEGEN_ASSERT(GRPC_CALL_OK == g_core_codegen_interface->grpc_call_start_batch( call_.call(), nullptr, 0, core_cq_tag(), nullptr)); + // Complete the avalanching since we are done with this batch of ops + call_.cq()->CompleteAvalanching(); } private: diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index fb38788f7d6..6d0d56cef5a 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -84,6 +84,8 @@ template class ErrorMethodHandler; template class BlockingUnaryCallImpl; +template +class CallOpSet; } // namespace internal extern CoreCodegenInterface* g_core_codegen_interface; @@ -278,6 +280,10 @@ class CompletionQueue : private GrpcLibraryCodegen { // Friends that need access to constructor for callback CQ friend class ::grpc::Channel; + // For access to Register/CompleteAvalanching + template + friend class ::grpc::internal::CallOpSet; + /// EXPERIMENTAL /// Creates a Thread Local cache to store the first event /// On this completion queue queued from this thread. Once diff --git a/test/cpp/end2end/server_interceptors_end2end_test.cc b/test/cpp/end2end/server_interceptors_end2end_test.cc index 82f142ba913..028191c93c3 100644 --- a/test/cpp/end2end/server_interceptors_end2end_test.cc +++ b/test/cpp/end2end/server_interceptors_end2end_test.cc @@ -504,7 +504,8 @@ TEST_F(ServerInterceptorsAsyncEnd2endTest, GenericRPCTest) { new DummyInterceptorFactory())); } builder.experimental().SetInterceptorCreators(std::move(creators)); - auto cq = builder.AddCompletionQueue(); + auto srv_cq = builder.AddCompletionQueue(); + CompletionQueue cli_cq; auto server = builder.BuildAndStart(); ChannelArguments args; @@ -527,28 +528,28 @@ TEST_F(ServerInterceptorsAsyncEnd2endTest, GenericRPCTest) { cli_ctx.AddMetadata("testkey", "testvalue"); std::unique_ptr call = - generic_stub.PrepareCall(&cli_ctx, kMethodName, cq.get()); + generic_stub.PrepareCall(&cli_ctx, kMethodName, &cli_cq); call->StartCall(tag(1)); - Verifier().Expect(1, true).Verify(cq.get()); + Verifier().Expect(1, true).Verify(&cli_cq); std::unique_ptr send_buffer = SerializeToByteBuffer(&send_request); call->Write(*send_buffer, tag(2)); // Send ByteBuffer can be destroyed after calling Write. send_buffer.reset(); - Verifier().Expect(2, true).Verify(cq.get()); + Verifier().Expect(2, true).Verify(&cli_cq); call->WritesDone(tag(3)); - Verifier().Expect(3, true).Verify(cq.get()); + Verifier().Expect(3, true).Verify(&cli_cq); - service.RequestCall(&srv_ctx, &stream, cq.get(), cq.get(), tag(4)); + service.RequestCall(&srv_ctx, &stream, srv_cq.get(), srv_cq.get(), tag(4)); - Verifier().Expect(4, true).Verify(cq.get()); + Verifier().Expect(4, true).Verify(srv_cq.get()); EXPECT_EQ(kMethodName, srv_ctx.method()); EXPECT_TRUE(CheckMetadata(srv_ctx.client_metadata(), "testkey", "testvalue")); srv_ctx.AddTrailingMetadata("testkey", "testvalue"); ByteBuffer recv_buffer; stream.Read(&recv_buffer, tag(5)); - Verifier().Expect(5, true).Verify(cq.get()); + Verifier().Expect(5, true).Verify(srv_cq.get()); EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request)); EXPECT_EQ(send_request.message(), recv_request.message()); @@ -556,18 +557,23 @@ TEST_F(ServerInterceptorsAsyncEnd2endTest, GenericRPCTest) { send_buffer = SerializeToByteBuffer(&send_response); stream.Write(*send_buffer, tag(6)); send_buffer.reset(); - Verifier().Expect(6, true).Verify(cq.get()); + Verifier().Expect(6, true).Verify(srv_cq.get()); stream.Finish(Status::OK, tag(7)); - Verifier().Expect(7, true).Verify(cq.get()); + // Shutdown srv_cq before we try to get the tag back, to verify that the + // interception API handles completion queue shutdowns that take place before + // all the tags are returned + srv_cq->Shutdown(); + Verifier().Expect(7, true).Verify(srv_cq.get()); recv_buffer.Clear(); call->Read(&recv_buffer, tag(8)); - Verifier().Expect(8, true).Verify(cq.get()); + Verifier().Expect(8, true).Verify(&cli_cq); EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response)); call->Finish(&recv_status, tag(9)); - Verifier().Expect(9, true).Verify(cq.get()); + cli_cq.Shutdown(); + Verifier().Expect(9, true).Verify(&cli_cq); EXPECT_EQ(send_response.message(), recv_response.message()); EXPECT_TRUE(recv_status.ok()); @@ -578,10 +584,11 @@ TEST_F(ServerInterceptorsAsyncEnd2endTest, GenericRPCTest) { EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); server->Shutdown(); - cq->Shutdown(); void* ignored_tag; bool ignored_ok; - while (cq->Next(&ignored_tag, &ignored_ok)) + while (cli_cq.Next(&ignored_tag, &ignored_ok)) + ; + while (srv_cq->Next(&ignored_tag, &ignored_ok)) ; grpc_recycle_unused_port(port); } From fb06f89af988d1c22afb86c595b5747ddbebe80d Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 24 Jan 2019 10:32:14 +0100 Subject: [PATCH 041/218] move RBE test timeout configuration to a single place --- tools/internal_ci/linux/grpc_bazel_on_foundry_dbg.sh | 2 +- tools/internal_ci/linux/grpc_bazel_on_foundry_opt.sh | 2 +- .../linux/pull_request/grpc_bazel_on_foundry_dbg.sh | 2 +- .../linux/pull_request/grpc_bazel_on_foundry_opt.sh | 2 +- tools/remote_build/manual.bazelrc | 4 ---- tools/remote_build/rbe_common.bazelrc | 4 ++++ 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/internal_ci/linux/grpc_bazel_on_foundry_dbg.sh b/tools/internal_ci/linux/grpc_bazel_on_foundry_dbg.sh index fdd5b2e4cde..06b93f3d80f 100644 --- a/tools/internal_ci/linux/grpc_bazel_on_foundry_dbg.sh +++ b/tools/internal_ci/linux/grpc_bazel_on_foundry_dbg.sh @@ -16,5 +16,5 @@ set -ex export UPLOAD_TEST_RESULTS=true -EXTRA_FLAGS="--config=dbg --test_timeout=300,450,1200,3600 --cache_test_results=no" +EXTRA_FLAGS="--config=dbg --cache_test_results=no" github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}" diff --git a/tools/internal_ci/linux/grpc_bazel_on_foundry_opt.sh b/tools/internal_ci/linux/grpc_bazel_on_foundry_opt.sh index 30b2b17a674..66effabf972 100644 --- a/tools/internal_ci/linux/grpc_bazel_on_foundry_opt.sh +++ b/tools/internal_ci/linux/grpc_bazel_on_foundry_opt.sh @@ -16,5 +16,5 @@ set -ex export UPLOAD_TEST_RESULTS=true -EXTRA_FLAGS="--config=opt --test_timeout=300,450,1200,3600 --cache_test_results=no" +EXTRA_FLAGS="--config=opt --cache_test_results=no" github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}" diff --git a/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_dbg.sh b/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_dbg.sh index f1e6588517e..6cf7a881c70 100644 --- a/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_dbg.sh +++ b/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_dbg.sh @@ -15,5 +15,5 @@ set -ex -EXTRA_FLAGS="--config=dbg --test_timeout=300,450,1200,3600" +EXTRA_FLAGS="--config=dbg" github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}" diff --git a/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_opt.sh b/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_opt.sh index 77744de49fa..76df0b245e5 100644 --- a/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_opt.sh +++ b/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_opt.sh @@ -15,5 +15,5 @@ set -ex -EXTRA_FLAGS="--config=opt --test_timeout=300,450,1200,3600" +EXTRA_FLAGS="--config=opt" github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}" diff --git a/tools/remote_build/manual.bazelrc b/tools/remote_build/manual.bazelrc index b4fdc70637e..fcd41f57521 100644 --- a/tools/remote_build/manual.bazelrc +++ b/tools/remote_build/manual.bazelrc @@ -37,9 +37,5 @@ build --project_id=grpc-testing build --jobs=100 -# TODO(jtattermusch): this should be part of the common config -# but currently sanitizers use different test_timeout values -build --test_timeout=300,450,1200,3600 - # print output for tests that fail (default is "summary") build --test_output=errors diff --git a/tools/remote_build/rbe_common.bazelrc b/tools/remote_build/rbe_common.bazelrc index c4928fb83a7..9a86713f505 100644 --- a/tools/remote_build/rbe_common.bazelrc +++ b/tools/remote_build/rbe_common.bazelrc @@ -44,6 +44,10 @@ build --define GRPC_PORT_ISOLATED_RUNTIME=1 # without verbose gRPC logs the test outputs are not very useful test --test_env=GRPC_VERBOSITY=debug +# Default test timeouts for all RBE tests (sanitizers override these values) +# TODO(jtattermusch): revisit the non-standard test timeout values +build --test_timeout=300,450,1200,3600 + # address sanitizer: most settings are already in %workspace%/.bazelrc # we only need a few additional ones that are Foundry specific build:asan --copt=-gmlt From 9e510cc5d4375f6d2b3ae80d190e1e7fc089dbb0 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 24 Jan 2019 10:47:30 +0100 Subject: [PATCH 042/218] update test size to avoid RBE timeouts --- test/cpp/end2end/BUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index 47cb6ba14c3..4c28eee4d15 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -222,6 +222,7 @@ grpc_cc_test( deps = [ ":end2end_test_lib", ], + size = "large", # with poll-cv this takes long, see #17493 ) grpc_cc_test( From df6cf7c7416eb2cd874c3bb61059d03a03187894 Mon Sep 17 00:00:00 2001 From: Chris Wilcox Date: Thu, 27 Dec 2018 09:35:00 -0800 Subject: [PATCH 043/218] Add period at end of metadata.google.internal to prevent unnecessary DNS lookups. --- src/core/lib/security/credentials/alts/alts_credentials.cc | 2 +- src/core/lib/security/credentials/credentials.h | 2 +- .../google_default/google_default_credentials.cc | 2 +- test/core/security/credentials_test.cc | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/lib/security/credentials/alts/alts_credentials.cc b/src/core/lib/security/credentials/alts/alts_credentials.cc index 06546492bc7..9a337903063 100644 --- a/src/core/lib/security/credentials/alts/alts_credentials.cc +++ b/src/core/lib/security/credentials/alts/alts_credentials.cc @@ -31,7 +31,7 @@ #include "src/core/lib/security/security_connector/alts/alts_security_connector.h" #define GRPC_CREDENTIALS_TYPE_ALTS "Alts" -#define GRPC_ALTS_HANDSHAKER_SERVICE_URL "metadata.google.internal:8080" +#define GRPC_ALTS_HANDSHAKER_SERVICE_URL "metadata.google.internal.:8080" grpc_alts_credentials::grpc_alts_credentials( const grpc_alts_credentials_options* options, diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h index 4091ef3dfb5..21bc50be4b2 100644 --- a/src/core/lib/security/credentials/credentials.h +++ b/src/core/lib/security/credentials/credentials.h @@ -60,7 +60,7 @@ typedef enum { #define GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS 60 -#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata.google.internal" +#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata.google.internal." #define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \ "/computeMetadata/v1/instance/service-accounts/default/token" diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/src/core/lib/security/credentials/google_default/google_default_credentials.cc index a86a17d5864..5ab7efd7c20 100644 --- a/src/core/lib/security/credentials/google_default/google_default_credentials.cc +++ b/src/core/lib/security/credentials/google_default/google_default_credentials.cc @@ -46,7 +46,7 @@ /* -- Constants. -- */ -#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal" +#define GRPC_COMPUTE_ENGINE_DETECTION_HOST "metadata.google.internal." /* -- Default credentials. -- */ diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc index b6555353359..11cfc8cc905 100644 --- a/test/core/security/credentials_test.cc +++ b/test/core/security/credentials_test.cc @@ -534,7 +534,7 @@ static void test_channel_oauth2_google_iam_composite_creds(void) { static void validate_compute_engine_http_request( const grpc_httpcli_request* request) { GPR_ASSERT(request->handshaker != &grpc_httpcli_ssl); - GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal.") == 0); GPR_ASSERT( strcmp(request->http.path, "/computeMetadata/v1/instance/service-accounts/default/token") == @@ -930,7 +930,7 @@ static int default_creds_metadata_server_detection_httpcli_get_success_override( response->hdr_count = 1; response->hdrs = headers; GPR_ASSERT(strcmp(request->http.path, "/") == 0); - GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal.") == 0); GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE); return 1; } @@ -1020,7 +1020,7 @@ static int default_creds_gce_detection_httpcli_get_failure_override( grpc_closure* on_done, grpc_httpcli_response* response) { /* No magic header. */ GPR_ASSERT(strcmp(request->http.path, "/") == 0); - GPR_ASSERT(strcmp(request->host, "metadata.google.internal") == 0); + GPR_ASSERT(strcmp(request->host, "metadata.google.internal.") == 0); *response = http_response(200, ""); GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE); return 1; From dbad0522c3f92fdf533d56e9164bc2514e6d0d93 Mon Sep 17 00:00:00 2001 From: Richard Belleville Date: Thu, 24 Jan 2019 10:10:22 -0800 Subject: [PATCH 044/218] Revert "Merge pull request #17752 from grpc/license-symlinks" This reverts commit 3f8e15e2a4a3765dfe4be1563f30ee89c5729735, reversing changes made to a8662121c719f7de3e6a0f7d8cac54affc1c2324. --- src/python/grpcio_channelz/LICENSE | 1 - .../grpcio_channelz/channelz_commands.py | 3 ++ src/python/grpcio_health_checking/LICENSE | 1 - .../grpcio_health_checking/health_commands.py | 3 ++ src/python/grpcio_reflection/LICENSE | 1 - .../grpcio_reflection/reflection_commands.py | 3 ++ src/python/grpcio_status/LICENSE | 1 - src/python/grpcio_status/setup.py | 19 ++++++--- src/python/grpcio_status/status_commands.py | 39 +++++++++++++++++++ src/python/grpcio_testing/LICENSE | 1 - src/python/grpcio_testing/setup.py | 16 ++++++-- src/python/grpcio_testing/testing_commands.py | 39 +++++++++++++++++++ tools/distrib/yapf_code.sh | 2 +- 13 files changed, 114 insertions(+), 15 deletions(-) delete mode 120000 src/python/grpcio_channelz/LICENSE delete mode 120000 src/python/grpcio_health_checking/LICENSE delete mode 120000 src/python/grpcio_reflection/LICENSE delete mode 120000 src/python/grpcio_status/LICENSE create mode 100644 src/python/grpcio_status/status_commands.py delete mode 120000 src/python/grpcio_testing/LICENSE create mode 100644 src/python/grpcio_testing/testing_commands.py diff --git a/src/python/grpcio_channelz/LICENSE b/src/python/grpcio_channelz/LICENSE deleted file mode 120000 index 5853aaea53b..00000000000 --- a/src/python/grpcio_channelz/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../../../LICENSE \ No newline at end of file diff --git a/src/python/grpcio_channelz/channelz_commands.py b/src/python/grpcio_channelz/channelz_commands.py index 0137959e9d4..7f158c2a4bf 100644 --- a/src/python/grpcio_channelz/channelz_commands.py +++ b/src/python/grpcio_channelz/channelz_commands.py @@ -21,6 +21,7 @@ import setuptools ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) CHANNELZ_PROTO = os.path.join(ROOT_DIR, '../../proto/grpc/channelz/channelz.proto') +LICENSE = os.path.join(ROOT_DIR, '../../../LICENSE') class Preprocess(setuptools.Command): @@ -41,6 +42,8 @@ class Preprocess(setuptools.Command): shutil.copyfile(CHANNELZ_PROTO, os.path.join(ROOT_DIR, 'grpc_channelz/v1/channelz.proto')) + if os.path.isfile(LICENSE): + shutil.copyfile(LICENSE, os.path.join(ROOT_DIR, 'LICENSE')) class BuildPackageProtos(setuptools.Command): diff --git a/src/python/grpcio_health_checking/LICENSE b/src/python/grpcio_health_checking/LICENSE deleted file mode 120000 index 5853aaea53b..00000000000 --- a/src/python/grpcio_health_checking/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../../../LICENSE \ No newline at end of file diff --git a/src/python/grpcio_health_checking/health_commands.py b/src/python/grpcio_health_checking/health_commands.py index d1bf03f7a9c..3820ef0bbad 100644 --- a/src/python/grpcio_health_checking/health_commands.py +++ b/src/python/grpcio_health_checking/health_commands.py @@ -20,6 +20,7 @@ import setuptools ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) HEALTH_PROTO = os.path.join(ROOT_DIR, '../../proto/grpc/health/v1/health.proto') +LICENSE = os.path.join(ROOT_DIR, '../../../LICENSE') class Preprocess(setuptools.Command): @@ -40,6 +41,8 @@ class Preprocess(setuptools.Command): shutil.copyfile(HEALTH_PROTO, os.path.join(ROOT_DIR, 'grpc_health/v1/health.proto')) + if os.path.isfile(LICENSE): + shutil.copyfile(LICENSE, os.path.join(ROOT_DIR, 'LICENSE')) class BuildPackageProtos(setuptools.Command): diff --git a/src/python/grpcio_reflection/LICENSE b/src/python/grpcio_reflection/LICENSE deleted file mode 120000 index 5853aaea53b..00000000000 --- a/src/python/grpcio_reflection/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../../../LICENSE \ No newline at end of file diff --git a/src/python/grpcio_reflection/reflection_commands.py b/src/python/grpcio_reflection/reflection_commands.py index ac235576ae0..311ca4c4dba 100644 --- a/src/python/grpcio_reflection/reflection_commands.py +++ b/src/python/grpcio_reflection/reflection_commands.py @@ -21,6 +21,7 @@ import setuptools ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) REFLECTION_PROTO = os.path.join( ROOT_DIR, '../../proto/grpc/reflection/v1alpha/reflection.proto') +LICENSE = os.path.join(ROOT_DIR, '../../../LICENSE') class Preprocess(setuptools.Command): @@ -42,6 +43,8 @@ class Preprocess(setuptools.Command): REFLECTION_PROTO, os.path.join(ROOT_DIR, 'grpc_reflection/v1alpha/reflection.proto')) + if os.path.isfile(LICENSE): + shutil.copyfile(LICENSE, os.path.join(ROOT_DIR, 'LICENSE')) class BuildPackageProtos(setuptools.Command): diff --git a/src/python/grpcio_status/LICENSE b/src/python/grpcio_status/LICENSE deleted file mode 120000 index 5853aaea53b..00000000000 --- a/src/python/grpcio_status/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../../../LICENSE \ No newline at end of file diff --git a/src/python/grpcio_status/setup.py b/src/python/grpcio_status/setup.py index 2a39af721d9..983d3ea430b 100644 --- a/src/python/grpcio_status/setup.py +++ b/src/python/grpcio_status/setup.py @@ -63,11 +63,20 @@ INSTALL_REQUIRES = ( 'googleapis-common-protos>=1.5.5', ) -COMMAND_CLASS = { - # wire up commands to no-op not to break the external dependencies - 'preprocess': _NoOpCommand, - 'build_package_protos': _NoOpCommand, -} +try: + import status_commands as _status_commands + # we are in the build environment, otherwise the above import fails + COMMAND_CLASS = { + # Run preprocess from the repository *before* doing any packaging! + 'preprocess': _status_commands.Preprocess, + 'build_package_protos': _NoOpCommand, + } +except ImportError: + COMMAND_CLASS = { + # wire up commands to no-op not to break the external dependencies + 'preprocess': _NoOpCommand, + 'build_package_protos': _NoOpCommand, + } setuptools.setup( name='grpcio-status', diff --git a/src/python/grpcio_status/status_commands.py b/src/python/grpcio_status/status_commands.py new file mode 100644 index 00000000000..78cd497f622 --- /dev/null +++ b/src/python/grpcio_status/status_commands.py @@ -0,0 +1,39 @@ +# 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. +"""Provides distutils command classes for the GRPC Python setup process.""" + +import os +import shutil + +import setuptools + +ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) +LICENSE = os.path.join(ROOT_DIR, '../../../LICENSE') + + +class Preprocess(setuptools.Command): + """Command to copy LICENSE from root directory.""" + + description = '' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + if os.path.isfile(LICENSE): + shutil.copyfile(LICENSE, os.path.join(ROOT_DIR, 'LICENSE')) diff --git a/src/python/grpcio_testing/LICENSE b/src/python/grpcio_testing/LICENSE deleted file mode 120000 index 5853aaea53b..00000000000 --- a/src/python/grpcio_testing/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../../../LICENSE \ No newline at end of file diff --git a/src/python/grpcio_testing/setup.py b/src/python/grpcio_testing/setup.py index b0df0915347..18db71e0f09 100644 --- a/src/python/grpcio_testing/setup.py +++ b/src/python/grpcio_testing/setup.py @@ -50,10 +50,18 @@ INSTALL_REQUIRES = ( 'grpcio>={version}'.format(version=grpc_version.VERSION), ) -COMMAND_CLASS = { - # wire up commands to no-op not to break the external dependencies - 'preprocess': _NoOpCommand, -} +try: + import testing_commands as _testing_commands + # we are in the build environment, otherwise the above import fails + COMMAND_CLASS = { + # Run preprocess from the repository *before* doing any packaging! + 'preprocess': _testing_commands.Preprocess, + } +except ImportError: + COMMAND_CLASS = { + # wire up commands to no-op not to break the external dependencies + 'preprocess': _NoOpCommand, + } setuptools.setup( name='grpcio-testing', diff --git a/src/python/grpcio_testing/testing_commands.py b/src/python/grpcio_testing/testing_commands.py new file mode 100644 index 00000000000..fb40d37efb6 --- /dev/null +++ b/src/python/grpcio_testing/testing_commands.py @@ -0,0 +1,39 @@ +# 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. +"""Provides distutils command classes for the GRPC Python setup process.""" + +import os +import shutil + +import setuptools + +ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) +LICENSE = os.path.join(ROOT_DIR, '../../../LICENSE') + + +class Preprocess(setuptools.Command): + """Command to copy LICENSE from root directory.""" + + description = '' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + if os.path.isfile(LICENSE): + shutil.copyfile(LICENSE, os.path.join(ROOT_DIR, 'LICENSE')) diff --git a/tools/distrib/yapf_code.sh b/tools/distrib/yapf_code.sh index 9ded3f3762a..27c5e3129dd 100755 --- a/tools/distrib/yapf_code.sh +++ b/tools/distrib/yapf_code.sh @@ -54,7 +54,7 @@ else tempdir=$(mktemp -d) cp -RT "${dir}" "${tempdir}" yapf "${tempdir}" - diff -x 'LICENSE' -x '*.pyc' -ru "${dir}" "${tempdir}" || ok=no + diff -x '*.pyc' -ru "${dir}" "${tempdir}" || ok=no rm -rf "${tempdir}" done if [[ ${ok} == no ]]; then From 7d959465f2b457144f9e02ffca95d92b25095058 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 24 Jan 2019 10:27:12 -0800 Subject: [PATCH 045/218] Update podspec version --- gRPC-Core.podspec | 2 +- templates/gRPC-Core.podspec.template | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 1d69658bdb3..2d8d85bd16e 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -183,7 +183,7 @@ Pod::Spec.new do |s| ss.header_mappings_dir = '.' ss.libraries = 'z' ss.dependency "#{s.name}/Interface", version - ss.dependency 'BoringSSL-GRPC', '0.0.2' + ss.dependency 'BoringSSL-GRPC', '0.0.3' ss.dependency 'nanopb', '~> 0.3' ss.compiler_flags = '-DGRPC_SHADOW_BORINGSSL_SYMBOLS' diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template index 1d68f0d0b93..17048765437 100644 --- a/templates/gRPC-Core.podspec.template +++ b/templates/gRPC-Core.podspec.template @@ -176,7 +176,7 @@ ss.header_mappings_dir = '.' ss.libraries = 'z' ss.dependency "#{s.name}/Interface", version - ss.dependency 'BoringSSL-GRPC', '0.0.2' + ss.dependency 'BoringSSL-GRPC', '0.0.3' ss.dependency 'nanopb', '~> 0.3' ss.compiler_flags = '-DGRPC_SHADOW_BORINGSSL_SYMBOLS' From 0c2fc6101d495242af00331bd4aec3d3b74a805b Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Thu, 24 Jan 2019 10:27:26 -0800 Subject: [PATCH 046/218] Parse xDS config --- .../ext/filters/client_channel/lb_policy.cc | 27 +++++++ .../ext/filters/client_channel/lb_policy.h | 4 + .../client_channel/lb_policy/xds/xds.cc | 81 +++++++++++++++++-- .../client_channel/resolver_result_parsing.cc | 42 ++-------- 4 files changed, 112 insertions(+), 42 deletions(-) diff --git a/src/core/ext/filters/client_channel/lb_policy.cc b/src/core/ext/filters/client_channel/lb_policy.cc index 2450775109f..d9b3927d1ca 100644 --- a/src/core/ext/filters/client_channel/lb_policy.cc +++ b/src/core/ext/filters/client_channel/lb_policy.cc @@ -20,6 +20,7 @@ #include "src/core/ext/filters/client_channel/lb_policy.h" +#include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/lib/iomgr/combiner.h" grpc_core::DebugOnlyTraceFlag grpc_trace_lb_policy_refcount( @@ -27,6 +28,32 @@ grpc_core::DebugOnlyTraceFlag grpc_trace_lb_policy_refcount( namespace grpc_core { +grpc_json* LoadBalancingPolicy::ParseLoadBalancingConfig( + const grpc_json* lb_config_array) { + if (lb_config_array == nullptr || lb_config_array->type != GRPC_JSON_ARRAY) { + return nullptr; + } + // Find the first LB policy that this client supports. + for (const grpc_json* lb_config = lb_config_array->child; + lb_config != nullptr; lb_config = lb_config->next) { + if (lb_config->type != GRPC_JSON_OBJECT) return nullptr; + grpc_json* policy = nullptr; + for (grpc_json* field = lb_config->child; field != nullptr; + field = field->next) { + if (field->key == nullptr || field->type != GRPC_JSON_OBJECT) + return nullptr; + if (policy != nullptr) return nullptr; // Violate "oneof" type. + policy = field; + } + if (policy == nullptr) return nullptr; + // If we support this policy, then select it. + if (LoadBalancingPolicyRegistry::LoadBalancingPolicyExists(policy->key)) { + return policy; + } + } + return nullptr; +} + LoadBalancingPolicy::LoadBalancingPolicy(Args args) : InternallyRefCounted(&grpc_trace_lb_policy_refcount), combiner_(GRPC_COMBINER_REF(args.combiner, "lb_policy")), diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h index 08634917ac1..56bf1951cfb 100644 --- a/src/core/ext/filters/client_channel/lb_policy.h +++ b/src/core/ext/filters/client_channel/lb_policy.h @@ -179,6 +179,10 @@ class LoadBalancingPolicy : public InternallyRefCounted { GRPC_ERROR_NONE); } + /// Returns the JSON node of policy (with both policy name and config content) + /// given the JSON node of a LoadBalancingConfig array. + static grpc_json* ParseLoadBalancingConfig(const grpc_json* lb_config_array); + /// Sets the re-resolution closure to \a request_reresolution. void SetReresolutionClosureLocked(grpc_closure* request_reresolution) { GPR_ASSERT(request_reresolution_ == nullptr); diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc b/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc index add38eedd20..678b4d75eb9 100644 --- a/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +++ b/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc @@ -100,6 +100,7 @@ #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel_init.h" +#include "src/core/lib/transport/service_config.h" #include "src/core/lib/transport/static_metadata.h" #define GRPC_XDS_INITIAL_CONNECT_BACKOFF_SECONDS 1 @@ -247,6 +248,12 @@ class XdsLb : public LoadBalancingPolicy { // Helper function used in ctor and UpdateLocked(). void ProcessChannelArgsLocked(const grpc_channel_args& args); + // Parses the xds config given the JSON node of the first child of XdsConfig. + // If parsing succeeds, updates \a balancer_name, and updates \a + // child_policy_json_dump_ and \a fallback_policy_json_dump_ if they are also + // found. Does nothing upon failure. + void ParseLbConfig(grpc_json* xds_config_json); + // Methods for dealing with the balancer channel and call. void StartPickingLocked(); void StartBalancerCallLocked(); @@ -265,7 +272,7 @@ class XdsLb : public LoadBalancingPolicy { // Methods for dealing with the child policy. void CreateOrUpdateChildPolicyLocked(); grpc_channel_args* CreateChildPolicyArgsLocked(); - void CreateChildPolicyLocked(Args args); + void CreateChildPolicyLocked(const char* name, Args args); bool PickFromChildPolicyLocked(bool force_async, PendingPick* pp, grpc_error** error); void UpdateConnectivityStateFromChildPolicyLocked( @@ -278,6 +285,9 @@ class XdsLb : public LoadBalancingPolicy { // Who the client is trying to communicate with. const char* server_name_ = nullptr; + // Name of the balancer to connect to. + UniquePtr balancer_name_; + // Current channel args from the resolver. grpc_channel_args* args_ = nullptr; @@ -318,6 +328,7 @@ class XdsLb : public LoadBalancingPolicy { // Timeout in milliseconds for before using fallback backend addresses. // 0 means not using fallback. + UniquePtr fallback_policy_json_string_; int lb_fallback_timeout_ms_ = 0; // The backend addresses from the resolver. UniquePtr fallback_backend_addresses_; @@ -331,6 +342,7 @@ class XdsLb : public LoadBalancingPolicy { // The policy to use for the backends. OrphanablePtr child_policy_; + UniquePtr child_policy_json_string_; grpc_connectivity_state child_connectivity_state_; grpc_closure on_child_connectivity_changed_; grpc_closure on_child_request_reresolution_; @@ -934,6 +946,8 @@ XdsLb::XdsLb(LoadBalancingPolicy::Args args) arg = grpc_channel_args_find(args.args, GRPC_ARG_GRPCLB_FALLBACK_TIMEOUT_MS); lb_fallback_timeout_ms_ = grpc_channel_arg_get_integer( arg, {GRPC_XDS_DEFAULT_FALLBACK_TIMEOUT_MS, 0, INT_MAX}); + // Parse the LB config. + ParseLbConfig(args.lb_config); // Process channel args. ProcessChannelArgsLocked(*args.args); } @@ -1184,8 +1198,44 @@ void XdsLb::ProcessChannelArgsLocked(const grpc_channel_args& args) { grpc_channel_args_destroy(lb_channel_args); } -// TODO(vishalpowar): Use lb_config to configure LB policy. +void XdsLb::ParseLbConfig(grpc_json* xds_config_json) { + const char* balancer_name = nullptr; + grpc_json* child_policy = nullptr; + grpc_json* fallback_policy = nullptr; + for (grpc_json* field = xds_config_json; field != nullptr; + field = field->next) { + if (field->key == nullptr) return; + if (strcmp(field->key, "balancerName") == 0) { + if (balancer_name != nullptr) return; // Duplicate. + if (field->type != GRPC_JSON_STRING) return; + balancer_name = field->value; + } else if (strcmp(field->key, "childPolicy") == 0) { + if (child_policy != nullptr) return; // Duplicate. + child_policy = ParseLoadBalancingConfig(field); + } else if (strcmp(field->key, "fallbackPolicy") == 0) { + if (fallback_policy != nullptr) return; // Duplicate. + fallback_policy = ParseLoadBalancingConfig(field); + } + } + if (balancer_name == nullptr) return; // Required field. + if (child_policy != nullptr) { + child_policy_json_string_ = + UniquePtr(grpc_json_dump_to_string(child_policy, 0 /* indent */)); + } + if (fallback_policy != nullptr) { + fallback_policy_json_string_ = UniquePtr( + grpc_json_dump_to_string(fallback_policy, 0 /* indent */)); + } + balancer_name_ = UniquePtr(gpr_strdup(balancer_name)); +} + void XdsLb::UpdateLocked(const grpc_channel_args& args, grpc_json* lb_config) { + ParseLbConfig(lb_config); + // TODO(juanlishen): Pass fallback policy config update after fallback policy + // is added. + if (balancer_name_ == nullptr) { + gpr_log(GPR_ERROR, "[xdslb %p] LB config parsing fails.", this); + } ProcessChannelArgsLocked(args); // Update the existing child policy. // Note: We have disabled fallback mode in the code, so this child policy must @@ -1436,10 +1486,10 @@ bool XdsLb::PickFromChildPolicyLocked(bool force_async, PendingPick* pp, return pick_done; } -void XdsLb::CreateChildPolicyLocked(Args args) { +void XdsLb::CreateChildPolicyLocked(const char* name, Args args) { GPR_ASSERT(child_policy_ == nullptr); child_policy_ = LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy( - "round_robin", std::move(args)); + name, std::move(args)); if (GPR_UNLIKELY(child_policy_ == nullptr)) { gpr_log(GPR_ERROR, "[xdslb %p] Failure creating a child policy", this); return; @@ -1512,26 +1562,43 @@ void XdsLb::CreateOrUpdateChildPolicyLocked() { if (shutting_down_) return; grpc_channel_args* args = CreateChildPolicyArgsLocked(); GPR_ASSERT(args != nullptr); + const char* child_policy_name = nullptr; + grpc_json* child_policy_config = nullptr; + grpc_json* child_policy_json = + grpc_json_parse_string(child_policy_json_string_.get()); + // TODO(juanlishen): If the child policy is not configured via service config, + // use whatever algorithm is specified by the balancer. + if (child_policy_json != nullptr) { + child_policy_name = child_policy_json->key; + child_policy_config = child_policy_json->child; + } else { + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, "[xdslb %p] No valid child policy LB config", this); + } + child_policy_name = "round_robin"; + } + // TODO(juanlishen): Switch policy according to child_policy_config->key. if (child_policy_ != nullptr) { if (grpc_lb_xds_trace.enabled()) { gpr_log(GPR_INFO, "[xdslb %p] Updating the child policy %p", this, child_policy_.get()); } - // TODO(vishalpowar): Pass the correct LB config. - child_policy_->UpdateLocked(*args, nullptr); + child_policy_->UpdateLocked(*args, child_policy_config); } else { LoadBalancingPolicy::Args lb_policy_args; lb_policy_args.combiner = combiner(); lb_policy_args.client_channel_factory = client_channel_factory(); lb_policy_args.subchannel_pool = subchannel_pool()->Ref(); lb_policy_args.args = args; - CreateChildPolicyLocked(std::move(lb_policy_args)); + lb_policy_args.lb_config = child_policy_config; + CreateChildPolicyLocked(child_policy_name, std::move(lb_policy_args)); if (grpc_lb_xds_trace.enabled()) { gpr_log(GPR_INFO, "[xdslb %p] Created a new child policy %p", this, child_policy_.get()); } } grpc_channel_args_destroy(args); + grpc_json_destroy(child_policy_json); } void XdsLb::OnChildPolicyRequestReresolutionLocked(void* arg, diff --git a/src/core/ext/filters/client_channel/resolver_result_parsing.cc b/src/core/ext/filters/client_channel/resolver_result_parsing.cc index 9a0122e8ece..0af07dc4e64 100644 --- a/src/core/ext/filters/client_channel/resolver_result_parsing.cc +++ b/src/core/ext/filters/client_channel/resolver_result_parsing.cc @@ -141,42 +141,14 @@ void ProcessedResolverResult::ParseServiceConfig( void ProcessedResolverResult::ParseLbConfigFromServiceConfig( const grpc_json* field) { if (lb_policy_config_ != nullptr) return; // Already found. - // Find the LB config global parameter. - if (field->key == nullptr || strcmp(field->key, "loadBalancingConfig") != 0 || - field->type != GRPC_JSON_ARRAY) { - return; // Not valid lb config array. + if (field->key == nullptr || strcmp(field->key, "loadBalancingConfig") != 0) { + return; // Not the LB config global parameter. } - // Find the first LB policy that this client supports. - for (grpc_json* lb_config = field->child; lb_config != nullptr; - lb_config = lb_config->next) { - if (lb_config->type != GRPC_JSON_OBJECT) return; - // Find the policy object. - grpc_json* policy = nullptr; - for (grpc_json* field = lb_config->child; field != nullptr; - field = field->next) { - if (field->key == nullptr || strcmp(field->key, "policy") != 0 || - field->type != GRPC_JSON_OBJECT) { - return; - } - if (policy != nullptr) return; // Duplicate. - policy = field; - } - // Find the specific policy content since the policy object is of type - // "oneof". - grpc_json* policy_content = nullptr; - for (grpc_json* field = policy->child; field != nullptr; - field = field->next) { - if (field->key == nullptr || field->type != GRPC_JSON_OBJECT) return; - if (policy_content != nullptr) return; // Violate "oneof" type. - policy_content = field; - } - // If we support this policy, then select it. - if (grpc_core::LoadBalancingPolicyRegistry::LoadBalancingPolicyExists( - policy_content->key)) { - lb_policy_name_.reset(gpr_strdup(policy_content->key)); - lb_policy_config_ = policy_content->child; - return; - } + const grpc_json* policy = + LoadBalancingPolicy::ParseLoadBalancingConfig(field); + if (policy != nullptr) { + lb_policy_name_.reset(gpr_strdup(policy->key)); + lb_policy_config_ = policy->child; } } From 4dcb14ec9e6f926ed24f51464955ce6e147e3e05 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 24 Jan 2019 13:05:05 -0800 Subject: [PATCH 047/218] Fix codegen_test_minimal --- include/grpcpp/impl/codegen/call_op_set.h | 2 +- include/grpcpp/impl/codegen/completion_queue.h | 7 ++++++- include/grpcpp/impl/codegen/core_codegen.h | 3 ++- include/grpcpp/impl/codegen/core_codegen_interface.h | 1 + src/cpp/common/completion_queue_cc.cc | 10 +--------- src/cpp/common/core_codegen.cc | 6 +++++- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index 521cafe439b..feef745701f 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -1,6 +1,6 @@ /* * - * Copyright 2018 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index 6d0d56cef5a..4812f0253d4 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -367,7 +367,12 @@ class CompletionQueue : private GrpcLibraryCodegen { gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, static_cast(1)); } - void CompleteAvalanching(); + void CompleteAvalanching() { + if (gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, + static_cast(-1)) == 1) { + g_core_codegen_interface->grpc_completion_queue_shutdown(cq_); + } + } grpc_completion_queue* cq_; // owned diff --git a/include/grpcpp/impl/codegen/core_codegen.h b/include/grpcpp/impl/codegen/core_codegen.h index 6ef184d01ab..6230555e1a7 100644 --- a/include/grpcpp/impl/codegen/core_codegen.h +++ b/include/grpcpp/impl/codegen/core_codegen.h @@ -1,6 +1,6 @@ /* * - * Copyright 2016 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ class CoreCodegen final : public CoreCodegenInterface { void* reserved) override; grpc_completion_queue* grpc_completion_queue_create_for_pluck( void* reserved) override; + void grpc_completion_queue_shutdown(grpc_completion_queue* cq) override; void grpc_completion_queue_destroy(grpc_completion_queue* cq) override; grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq, void* tag, gpr_timespec deadline, diff --git a/include/grpcpp/impl/codegen/core_codegen_interface.h b/include/grpcpp/impl/codegen/core_codegen_interface.h index 20a5b3300c4..1d92b4f0dff 100644 --- a/include/grpcpp/impl/codegen/core_codegen_interface.h +++ b/include/grpcpp/impl/codegen/core_codegen_interface.h @@ -52,6 +52,7 @@ class CoreCodegenInterface { void* reserved) = 0; virtual grpc_completion_queue* grpc_completion_queue_create_for_pluck( void* reserved) = 0; + virtual void grpc_completion_queue_shutdown(grpc_completion_queue* cq) = 0; virtual void grpc_completion_queue_destroy(grpc_completion_queue* cq) = 0; virtual grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq, void* tag, diff --git a/src/cpp/common/completion_queue_cc.cc b/src/cpp/common/completion_queue_cc.cc index d93a54aed71..3df45128ecb 100644 --- a/src/cpp/common/completion_queue_cc.cc +++ b/src/cpp/common/completion_queue_cc.cc @@ -1,5 +1,5 @@ /* - * Copyright 2015 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,14 +42,6 @@ void CompletionQueue::Shutdown() { CompleteAvalanching(); } -void CompletionQueue::CompleteAvalanching() { - // Check if this was the last avalanching operation - if (gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_, - static_cast(-1)) == 1) { - grpc_completion_queue_shutdown(cq_); - } -} - CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal( void** tag, bool* ok, gpr_timespec deadline) { for (;;) { diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc index cfaa2e7b193..986c3df7736 100644 --- a/src/cpp/common/core_codegen.cc +++ b/src/cpp/common/core_codegen.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2016 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,6 +59,10 @@ grpc_completion_queue* CoreCodegen::grpc_completion_queue_create_for_pluck( return ::grpc_completion_queue_create_for_pluck(reserved); } +void CoreCodegen::grpc_completion_queue_shutdown(grpc_completion_queue* cq) { + ::grpc_completion_queue_shutdown(cq); +} + void CoreCodegen::grpc_completion_queue_destroy(grpc_completion_queue* cq) { ::grpc_completion_queue_destroy(cq); } From 222dd9f3402e013aa229b260ccc87d70f7c4831d Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 24 Jan 2019 16:05:24 -0500 Subject: [PATCH 048/218] fixes from code review --- src/csharp/Grpc.Core/CallOptions.cs | 2 +- src/csharp/Grpc.Core/Internal/AsyncCall.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/csharp/Grpc.Core/CallOptions.cs b/src/csharp/Grpc.Core/CallOptions.cs index 89fd047a1ea..a92caae917d 100644 --- a/src/csharp/Grpc.Core/CallOptions.cs +++ b/src/csharp/Grpc.Core/CallOptions.cs @@ -238,7 +238,7 @@ namespace Grpc.Core var newOptions = this; // silently ignore the context propagation token if it wasn't produced by "us" var propagationTokenImpl = propagationToken.AsImplOrNull(); - if (propagationToken != null) + if (propagationTokenImpl != null) { if (propagationTokenImpl.Options.IsPropagateDeadline) { diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs index f80ac4a2f9d..785081c341a 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs @@ -494,7 +494,7 @@ namespace Grpc.Core.Internal return injectedNativeCall; // allows injecting a mock INativeCall in tests. } - var parentCall = details.Options.PropagationToken != null ? details.Options.PropagationToken.AsImplOrNull().ParentCall : CallSafeHandle.NullInstance; + var parentCall = details.Options.PropagationToken.AsImplOrNull()?.ParentCall ?? CallSafeHandle.NullInstance; var credentials = details.Options.Credentials; using (var nativeCredentials = credentials != null ? credentials.ToNativeCredentials() : null) From 7c58a8ae7627d4a39a8db9f578e88f32479c4e31 Mon Sep 17 00:00:00 2001 From: Jerry Date: Thu, 24 Jan 2019 13:09:43 -0800 Subject: [PATCH 049/218] rename valgrind.includ to php_valgrind.include --- .../tools/dockerfile/{valgrind.include => php_valgrind.include} | 0 .../tools/dockerfile/test/php7_jessie_x64/Dockerfile.template | 2 +- .../tools/dockerfile/test/php_jessie_x64/Dockerfile.template | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename templates/tools/dockerfile/{valgrind.include => php_valgrind.include} (100%) diff --git a/templates/tools/dockerfile/valgrind.include b/templates/tools/dockerfile/php_valgrind.include similarity index 100% rename from templates/tools/dockerfile/valgrind.include rename to templates/tools/dockerfile/php_valgrind.include diff --git a/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template index f6f52805b8c..0b2290b741c 100644 --- a/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template @@ -19,7 +19,7 @@ <%include file="../../php7_deps.include"/> <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> - <%include file="../../valgrind.include"/> + <%include file="../../php_valgrind.include"/> <%include file="../../run_tests_addons.include"/> # Define the default command. CMD ["bash"] diff --git a/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template index 1a07522c011..329205363e3 100644 --- a/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template @@ -20,7 +20,7 @@ <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../php_deps.include"/> - <%include file="../../valgrind.include"/> + <%include file="../../php_valgrind.include"/> <%include file="../../run_tests_addons.include"/> # Define the default command. CMD ["bash"] From 141e42f9b9309be15338f8def0bc018675960469 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Thu, 24 Jan 2019 13:45:07 -0800 Subject: [PATCH 050/218] Revert "Remove the fake package dependency && temporarily skip the Channelz tests" This reverts commit 08a90f03d4d0ac846f517c9aeab7aeb05b1cfdca. --- src/python/grpcio_tests/setup.py | 12 +++--------- .../tests/channelz/_channelz_servicer_test.py | 1 - 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py index 800b865da62..f9cb9d0cec9 100644 --- a/src/python/grpcio_tests/setup.py +++ b/src/python/grpcio_tests/setup.py @@ -37,19 +37,13 @@ PACKAGE_DIRECTORIES = { } INSTALL_REQUIRES = ( - 'coverage>=4.0', - 'enum34>=1.0.4', + 'coverage>=4.0', 'enum34>=1.0.4', 'grpcio>={version}'.format(version=grpc_version.VERSION), - # TODO(https://github.com/pypa/warehouse/issues/5196) - # Re-enable it once we got the name back - # 'grpcio-channelz>={version}'.format(version=grpc_version.VERSION), + 'grpcio-channelz>={version}'.format(version=grpc_version.VERSION), 'grpcio-status>={version}'.format(version=grpc_version.VERSION), 'grpcio-tools>={version}'.format(version=grpc_version.VERSION), 'grpcio-health-checking>={version}'.format(version=grpc_version.VERSION), - 'oauth2client>=1.4.7', - 'protobuf>=3.6.0', - 'six>=1.10', - 'google-auth>=1.0.0', + 'oauth2client>=1.4.7', 'protobuf>=3.6.0', 'six>=1.10', 'google-auth>=1.0.0', 'requests>=2.14.2') if not PY3: diff --git a/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py b/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py index c63ff5cd842..5265911a0be 100644 --- a/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py +++ b/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py @@ -91,7 +91,6 @@ def _close_channel_server_pairs(pairs): pair.channel.close() -@unittest.skip('https://github.com/pypa/warehouse/issues/5196') class ChannelzServicerTest(unittest.TestCase): def _send_successful_unary_unary(self, idx): From 9dd8a13439d02e2cb586032234c989816ce7eb8b Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 24 Jan 2019 19:03:55 -0800 Subject: [PATCH 051/218] Restructure code to handle cases exposed by the callback api --- include/grpcpp/impl/codegen/call_op_set.h | 13 ++++++---- .../grpcpp/impl/codegen/interceptor_common.h | 26 ++++++++++++++++--- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index feef745701f..03a32b9815d 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -871,9 +871,6 @@ class CallOpSet : public CallOpSetInterface, if (RunInterceptors()) { ContinueFillOpsAfterInterception(); } else { - // This call is going to go through interceptors and would need to - // schedule new batches, so delay completion queue shutdown - call_.cq()->RegisterAvalanching(); // After the interceptors are run, ContinueFillOpsAfterInterception will // be run } @@ -881,6 +878,8 @@ class CallOpSet : public CallOpSetInterface, bool FinalizeResult(void** tag, bool* status) override { if (done_intercepting_) { + // Complete the avalanching since we are done with this batch of ops + call_.cq()->CompleteAvalanching(); // We have already finished intercepting and filling in the results. This // round trip from the core needed to be made because interceptors were // run @@ -951,8 +950,6 @@ class CallOpSet : public CallOpSetInterface, GPR_CODEGEN_ASSERT(GRPC_CALL_OK == g_core_codegen_interface->grpc_call_start_batch( call_.call(), nullptr, 0, core_cq_tag(), nullptr)); - // Complete the avalanching since we are done with this batch of ops - call_.cq()->CompleteAvalanching(); } private: @@ -967,6 +964,12 @@ class CallOpSet : public CallOpSetInterface, this->Op4::SetInterceptionHookPoint(&interceptor_methods_); this->Op5::SetInterceptionHookPoint(&interceptor_methods_); this->Op6::SetInterceptionHookPoint(&interceptor_methods_); + if (interceptor_methods_.InterceptorsListEmpty()) { + return true; + } + // This call will go through interceptors and would need to + // schedule new batches, so delay completion queue shutdown + call_.cq()->RegisterAvalanching(); return interceptor_methods_.RunInterceptors(); } // Returns true if no interceptors need to be run diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index 09721343ffa..6c4847509e0 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -219,10 +219,28 @@ class InterceptorBatchMethodsImpl // Alternatively, RunInterceptors(std::function f) can be used. void SetCallOpSetInterface(CallOpSetInterface* ops) { ops_ = ops; } - // Returns true if no interceptors are run. This should be used only by - // subclasses of CallOpSetInterface. SetCall and SetCallOpSetInterface should - // have been called before this. After all the interceptors are done running, - // either ContinueFillOpsAfterInterception or + // Returns true if the interceptors list is empty + bool InterceptorsListEmpty() { + auto* client_rpc_info = call_->client_rpc_info(); + if (client_rpc_info != nullptr) { + if (client_rpc_info->interceptors_.size() == 0) { + return true; + } else { + return false; + } + } + + auto* server_rpc_info = call_->server_rpc_info(); + if (server_rpc_info == nullptr || + server_rpc_info->interceptors_.size() == 0) { + return true; + } + return false; + } + + // This should be used only by subclasses of CallOpSetInterface. SetCall and + // SetCallOpSetInterface should have been called before this. After all the + // interceptors are done running, either ContinueFillOpsAfterInterception or // ContinueFinalizeOpsAfterInterception will be called. Note that neither of // them is invoked if there were no interceptors registered. bool RunInterceptors() { From a682c75f6f7a33fa7ebf41fa7fa0f782a9d74c79 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 25 Jan 2019 03:50:45 -0500 Subject: [PATCH 052/218] add tests for foreign context propagation token --- .../Grpc.Core.Tests/ContextPropagationTest.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs b/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs index 9a878bde436..4158579194f 100644 --- a/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs +++ b/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs @@ -154,5 +154,28 @@ namespace Grpc.Core.Tests await call.RequestStream.CompleteAsync(); Assert.AreEqual("PASS", await call); } + + [Test] + public void ForeignPropagationTokenInterpretedAsNull() + { + Assert.IsNull(new ForeignContextPropagationToken().AsImplOrNull()); + } + + [Test] + public async Task ForeignPropagationTokenIsIgnored() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult("PASS"); + }); + + var callOptions = new CallOptions(propagationToken: new ForeignContextPropagationToken()); + await Calls.AsyncUnaryCall(helper.CreateUnaryCall(callOptions), "xyz"); + } + + // For testing, represents context propagation token that's not generated by Grpc.Core + private class ForeignContextPropagationToken : ContextPropagationToken + { + } } } From 27009f256bb0a3ca0c35cb9aa23e2c6704f77ec7 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 10 Jan 2019 19:25:53 +0100 Subject: [PATCH 053/218] add Grpc.Core.Api scaffolding --- src/csharp/Grpc.Core.Api/.gitignore | 2 + src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/csharp/Grpc.Core.Api/.gitignore create mode 100755 src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj diff --git a/src/csharp/Grpc.Core.Api/.gitignore b/src/csharp/Grpc.Core.Api/.gitignore new file mode 100644 index 00000000000..1746e3269ed --- /dev/null +++ b/src/csharp/Grpc.Core.Api/.gitignore @@ -0,0 +1,2 @@ +bin +obj diff --git a/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj b/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj new file mode 100755 index 00000000000..3ba3762676b --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj @@ -0,0 +1,38 @@ + + + + + + + Copyright 2015, Google Inc. + gRPC C# Surface API + $(GrpcCsharpVersion) + Google Inc. + net45;netstandard1.5 + Grpc.Core.Api + Grpc.Core.Api + gRPC RPC Protocol HTTP/2 + https://github.com/grpc/grpc + https://github.com/grpc/grpc/blob/master/LICENSE + true + true + + + + + + + + + + + + + + + + + + + + From 6382ca10e0f0841ef39daf6557646f3a4fe814bb Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 10 Jan 2019 19:30:54 +0100 Subject: [PATCH 054/218] add Grpc.Core.Api to the solution --- src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj | 6 ------ src/csharp/Grpc.sln | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj b/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj index 3ba3762676b..6ad1ac85ffc 100755 --- a/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj +++ b/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj @@ -29,10 +29,4 @@ - - - - - - diff --git a/src/csharp/Grpc.sln b/src/csharp/Grpc.sln index 6c1b2e99980..25030cc110e 100644 --- a/src/csharp/Grpc.sln +++ b/src/csharp/Grpc.sln @@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26430.4 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Core.Api", "Grpc.Core.Api\Grpc.Core.Api.csproj", "{63FCEA50-1505-11E9-B56E-0800200C9A66}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Core", "Grpc.Core\Grpc.Core.csproj", "{BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Auth", "Grpc.Auth\Grpc.Auth.csproj", "{2A16007A-5D67-4C53-BEC8-51E5064D18BF}" @@ -49,6 +51,10 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {63FCEA50-1505-11E9-B56E-0800200C9A66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {63FCEA50-1505-11E9-B56E-0800200C9A66}.Debug|Any CPU.Build.0 = Debug|Any CPU + {63FCEA50-1505-11E9-B56E-0800200C9A66}.Release|Any CPU.ActiveCfg = Release|Any CPU + {63FCEA50-1505-11E9-B56E-0800200C9A66}.Release|Any CPU.Build.0 = Release|Any CPU {BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}.Debug|Any CPU.Build.0 = Debug|Any CPU {BD878CB3-BDB4-46AB-84EF-C3B4729F56BC}.Release|Any CPU.ActiveCfg = Release|Any CPU From 3fda664d39c0658d19f6c8b156b32fc2423ef10f Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 10 Jan 2019 19:33:29 +0100 Subject: [PATCH 055/218] Grpc.Core depends on Grpc.Core.Api --- src/csharp/Grpc.Core/Grpc.Core.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index dc5683c9753..b99c23ae131 100755 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -80,6 +80,10 @@ + + + + From 55b9e5e3990d5c6e6ae5abdecfafb1370af68378 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 10 Jan 2019 20:12:44 +0100 Subject: [PATCH 056/218] move most of serverside API types to Grpc.Core.Api --- .../AuthContext.cs | 1 - .../AuthProperty.cs | 5 +- .../ContextPropagationOptions.cs | 0 .../ContextPropagationToken.cs | 0 .../DeserializationContext.cs | 0 .../IAsyncStreamReader.cs | 0 .../IAsyncStreamWriter.cs | 0 .../IServerStreamWriter.cs | 0 .../Logging/ILogger.cs | 0 .../Logging/LogLevel.cs | 0 .../Marshaller.cs | 0 .../{Grpc.Core => Grpc.Core.Api}/Metadata.cs | 18 +++--- .../{Grpc.Core => Grpc.Core.Api}/Method.cs | 0 .../Grpc.Core.Api/Properties/AssemblyInfo.cs | 63 +++++++++++++++++++ .../RpcException.cs | 0 .../SerializationContext.cs | 0 .../ServerCallContext.cs | 0 .../ServerMethods.cs | 0 .../{Grpc.Core => Grpc.Core.Api}/Status.cs | 4 +- .../StatusCode.cs | 0 .../Utils/GrpcPreconditions.cs | 0 .../WriteOptions.cs | 2 +- src/csharp/Grpc.Core/ForwardedTypes.cs | 56 +++++++++++++++++ 23 files changed, 133 insertions(+), 16 deletions(-) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/AuthContext.cs (99%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/AuthProperty.cs (94%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/ContextPropagationOptions.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/ContextPropagationToken.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/DeserializationContext.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/IAsyncStreamReader.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/IAsyncStreamWriter.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/IServerStreamWriter.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/Logging/ILogger.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/Logging/LogLevel.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/Marshaller.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/Metadata.cs (97%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/Method.cs (100%) create mode 100644 src/csharp/Grpc.Core.Api/Properties/AssemblyInfo.cs rename src/csharp/{Grpc.Core => Grpc.Core.Api}/RpcException.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/SerializationContext.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/ServerCallContext.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/ServerMethods.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/Status.cs (97%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/StatusCode.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/Utils/GrpcPreconditions.cs (100%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/WriteOptions.cs (99%) create mode 100644 src/csharp/Grpc.Core/ForwardedTypes.cs diff --git a/src/csharp/Grpc.Core/AuthContext.cs b/src/csharp/Grpc.Core.Api/AuthContext.cs similarity index 99% rename from src/csharp/Grpc.Core/AuthContext.cs rename to src/csharp/Grpc.Core.Api/AuthContext.cs index f2354310486..90887887f2d 100644 --- a/src/csharp/Grpc.Core/AuthContext.cs +++ b/src/csharp/Grpc.Core.Api/AuthContext.cs @@ -19,7 +19,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core diff --git a/src/csharp/Grpc.Core/AuthProperty.cs b/src/csharp/Grpc.Core.Api/AuthProperty.cs similarity index 94% rename from src/csharp/Grpc.Core/AuthProperty.cs rename to src/csharp/Grpc.Core.Api/AuthProperty.cs index 49765da6396..0907edba84d 100644 --- a/src/csharp/Grpc.Core/AuthProperty.cs +++ b/src/csharp/Grpc.Core.Api/AuthProperty.cs @@ -19,7 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Grpc.Core.Internal; +using System.Text; using Grpc.Core.Utils; namespace Grpc.Core @@ -30,6 +30,7 @@ namespace Grpc.Core /// public class AuthProperty { + static readonly Encoding EncodingUTF8 = System.Text.Encoding.UTF8; string name; byte[] valueBytes; Lazy value; @@ -38,7 +39,7 @@ namespace Grpc.Core { this.name = GrpcPreconditions.CheckNotNull(name); this.valueBytes = GrpcPreconditions.CheckNotNull(valueBytes); - this.value = new Lazy(() => MarshalUtils.GetStringUTF8(this.valueBytes)); + this.value = new Lazy(() => EncodingUTF8.GetString(this.valueBytes)); } /// diff --git a/src/csharp/Grpc.Core/ContextPropagationOptions.cs b/src/csharp/Grpc.Core.Api/ContextPropagationOptions.cs similarity index 100% rename from src/csharp/Grpc.Core/ContextPropagationOptions.cs rename to src/csharp/Grpc.Core.Api/ContextPropagationOptions.cs diff --git a/src/csharp/Grpc.Core/ContextPropagationToken.cs b/src/csharp/Grpc.Core.Api/ContextPropagationToken.cs similarity index 100% rename from src/csharp/Grpc.Core/ContextPropagationToken.cs rename to src/csharp/Grpc.Core.Api/ContextPropagationToken.cs diff --git a/src/csharp/Grpc.Core/DeserializationContext.cs b/src/csharp/Grpc.Core.Api/DeserializationContext.cs similarity index 100% rename from src/csharp/Grpc.Core/DeserializationContext.cs rename to src/csharp/Grpc.Core.Api/DeserializationContext.cs diff --git a/src/csharp/Grpc.Core/IAsyncStreamReader.cs b/src/csharp/Grpc.Core.Api/IAsyncStreamReader.cs similarity index 100% rename from src/csharp/Grpc.Core/IAsyncStreamReader.cs rename to src/csharp/Grpc.Core.Api/IAsyncStreamReader.cs diff --git a/src/csharp/Grpc.Core/IAsyncStreamWriter.cs b/src/csharp/Grpc.Core.Api/IAsyncStreamWriter.cs similarity index 100% rename from src/csharp/Grpc.Core/IAsyncStreamWriter.cs rename to src/csharp/Grpc.Core.Api/IAsyncStreamWriter.cs diff --git a/src/csharp/Grpc.Core/IServerStreamWriter.cs b/src/csharp/Grpc.Core.Api/IServerStreamWriter.cs similarity index 100% rename from src/csharp/Grpc.Core/IServerStreamWriter.cs rename to src/csharp/Grpc.Core.Api/IServerStreamWriter.cs diff --git a/src/csharp/Grpc.Core/Logging/ILogger.cs b/src/csharp/Grpc.Core.Api/Logging/ILogger.cs similarity index 100% rename from src/csharp/Grpc.Core/Logging/ILogger.cs rename to src/csharp/Grpc.Core.Api/Logging/ILogger.cs diff --git a/src/csharp/Grpc.Core/Logging/LogLevel.cs b/src/csharp/Grpc.Core.Api/Logging/LogLevel.cs similarity index 100% rename from src/csharp/Grpc.Core/Logging/LogLevel.cs rename to src/csharp/Grpc.Core.Api/Logging/LogLevel.cs diff --git a/src/csharp/Grpc.Core/Marshaller.cs b/src/csharp/Grpc.Core.Api/Marshaller.cs similarity index 100% rename from src/csharp/Grpc.Core/Marshaller.cs rename to src/csharp/Grpc.Core.Api/Marshaller.cs diff --git a/src/csharp/Grpc.Core/Metadata.cs b/src/csharp/Grpc.Core.Api/Metadata.cs similarity index 97% rename from src/csharp/Grpc.Core/Metadata.cs rename to src/csharp/Grpc.Core.Api/Metadata.cs index bc263c34696..27e72fbfa8b 100644 --- a/src/csharp/Grpc.Core/Metadata.cs +++ b/src/csharp/Grpc.Core.Api/Metadata.cs @@ -20,7 +20,6 @@ using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; -using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core @@ -52,6 +51,7 @@ namespace Grpc.Core /// feature and is not part of public API. /// internal const string CompressionRequestAlgorithmMetadataKey = "grpc-internal-encoding-request"; + static readonly Encoding EncodingASCII = System.Text.Encoding.ASCII; readonly List entries; bool readOnly; @@ -286,7 +286,7 @@ namespace Grpc.Core { if (valueBytes == null) { - return MarshalUtils.GetBytesASCII(value); + return EncodingASCII.GetBytes(value); } // defensive copy to guarantee immutability @@ -304,7 +304,7 @@ namespace Grpc.Core get { GrpcPreconditions.CheckState(!IsBinary, "Cannot access string value of a binary metadata entry"); - return value ?? MarshalUtils.GetStringASCII(valueBytes); + return value ?? EncodingASCII.GetString(valueBytes); } } @@ -328,7 +328,7 @@ namespace Grpc.Core { return string.Format("[Entry: key={0}, valueBytes={1}]", key, valueBytes); } - + return string.Format("[Entry: key={0}, value={1}]", key, value); } @@ -338,7 +338,7 @@ namespace Grpc.Core /// internal byte[] GetSerializedValueUnsafe() { - return valueBytes ?? MarshalUtils.GetBytesASCII(value); + return valueBytes ?? EncodingASCII.GetBytes(value); } /// @@ -351,21 +351,21 @@ namespace Grpc.Core { return new Entry(key, null, valueBytes); } - return new Entry(key, MarshalUtils.GetStringASCII(valueBytes), null); + return new Entry(key, EncodingASCII.GetString(valueBytes), null); } private static string NormalizeKey(string key) { GrpcPreconditions.CheckNotNull(key, "key"); - GrpcPreconditions.CheckArgument(IsValidKey(key, out bool isLowercase), + GrpcPreconditions.CheckArgument(IsValidKey(key, out bool isLowercase), "Metadata entry key not valid. Keys can only contain lowercase alphanumeric characters, underscores, hyphens and dots."); if (isLowercase) { // save allocation of a new string if already lowercase return key; } - + return key.ToLowerInvariant(); } @@ -378,7 +378,7 @@ namespace Grpc.Core if ('a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '.' || - c == '_' || + c == '_' || c == '-' ) continue; diff --git a/src/csharp/Grpc.Core/Method.cs b/src/csharp/Grpc.Core.Api/Method.cs similarity index 100% rename from src/csharp/Grpc.Core/Method.cs rename to src/csharp/Grpc.Core.Api/Method.cs diff --git a/src/csharp/Grpc.Core.Api/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core.Api/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..fa04d9328d4 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Properties/AssemblyInfo.cs @@ -0,0 +1,63 @@ +#region Copyright notice and license + +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Core.Api")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +#if SIGNED +[assembly: InternalsVisibleTo("Grpc.Core,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +[assembly: InternalsVisibleTo("Grpc.Core.Tests,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +[assembly: InternalsVisibleTo("Grpc.Core.Testing,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +[assembly: InternalsVisibleTo("Grpc.IntegrationTesting,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +[assembly: InternalsVisibleTo("Grpc.Microbenchmarks,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +#else +[assembly: InternalsVisibleTo("Grpc.Core")] +[assembly: InternalsVisibleTo("Grpc.Core.Tests")] +[assembly: InternalsVisibleTo("Grpc.Core.Testing")] +[assembly: InternalsVisibleTo("Grpc.IntegrationTesting")] +[assembly: InternalsVisibleTo("Grpc.Microbenchmarks")] +#endif diff --git a/src/csharp/Grpc.Core/RpcException.cs b/src/csharp/Grpc.Core.Api/RpcException.cs similarity index 100% rename from src/csharp/Grpc.Core/RpcException.cs rename to src/csharp/Grpc.Core.Api/RpcException.cs diff --git a/src/csharp/Grpc.Core/SerializationContext.cs b/src/csharp/Grpc.Core.Api/SerializationContext.cs similarity index 100% rename from src/csharp/Grpc.Core/SerializationContext.cs rename to src/csharp/Grpc.Core.Api/SerializationContext.cs diff --git a/src/csharp/Grpc.Core/ServerCallContext.cs b/src/csharp/Grpc.Core.Api/ServerCallContext.cs similarity index 100% rename from src/csharp/Grpc.Core/ServerCallContext.cs rename to src/csharp/Grpc.Core.Api/ServerCallContext.cs diff --git a/src/csharp/Grpc.Core/ServerMethods.cs b/src/csharp/Grpc.Core.Api/ServerMethods.cs similarity index 100% rename from src/csharp/Grpc.Core/ServerMethods.cs rename to src/csharp/Grpc.Core.Api/ServerMethods.cs diff --git a/src/csharp/Grpc.Core/Status.cs b/src/csharp/Grpc.Core.Api/Status.cs similarity index 97% rename from src/csharp/Grpc.Core/Status.cs rename to src/csharp/Grpc.Core.Api/Status.cs index 170a5b68c3e..b1a030b2d1f 100644 --- a/src/csharp/Grpc.Core/Status.cs +++ b/src/csharp/Grpc.Core.Api/Status.cs @@ -14,12 +14,10 @@ // limitations under the License. #endregion -using Grpc.Core.Utils; - namespace Grpc.Core { /// - /// Represents RPC result, which consists of and an optional detail string. + /// Represents RPC result, which consists of and an optional detail string. /// public struct Status { diff --git a/src/csharp/Grpc.Core/StatusCode.cs b/src/csharp/Grpc.Core.Api/StatusCode.cs similarity index 100% rename from src/csharp/Grpc.Core/StatusCode.cs rename to src/csharp/Grpc.Core.Api/StatusCode.cs diff --git a/src/csharp/Grpc.Core/Utils/GrpcPreconditions.cs b/src/csharp/Grpc.Core.Api/Utils/GrpcPreconditions.cs similarity index 100% rename from src/csharp/Grpc.Core/Utils/GrpcPreconditions.cs rename to src/csharp/Grpc.Core.Api/Utils/GrpcPreconditions.cs diff --git a/src/csharp/Grpc.Core/WriteOptions.cs b/src/csharp/Grpc.Core.Api/WriteOptions.cs similarity index 99% rename from src/csharp/Grpc.Core/WriteOptions.cs rename to src/csharp/Grpc.Core.Api/WriteOptions.cs index f99a6a0631e..cbb866b0a90 100644 --- a/src/csharp/Grpc.Core/WriteOptions.cs +++ b/src/csharp/Grpc.Core.Api/WriteOptions.cs @@ -48,7 +48,7 @@ namespace Grpc.Core /// Default write options. /// public static readonly WriteOptions Default = new WriteOptions(); - + private readonly WriteFlags flags; /// diff --git a/src/csharp/Grpc.Core/ForwardedTypes.cs b/src/csharp/Grpc.Core/ForwardedTypes.cs new file mode 100644 index 00000000000..8e104fd410d --- /dev/null +++ b/src/csharp/Grpc.Core/ForwardedTypes.cs @@ -0,0 +1,56 @@ +#region Copyright notice and license + +// Copyright 2019 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. + +#endregion + +using System.Runtime.CompilerServices; +using Grpc.Core; +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +// API types that used to be in Grpc.Core package, but were moved to Grpc.Core.Api +// https://docs.microsoft.com/en-us/dotnet/framework/app-domains/type-forwarding-in-the-common-language-runtime + +// TODO(jtattermusch): move types needed for implementing a client +// TODO(jtattermusch): ServerServiceDefinition depends on IServerCallHandler (which depends on other stuff) + +[assembly:TypeForwardedToAttribute(typeof(ILogger))] +[assembly:TypeForwardedToAttribute(typeof(LogLevel))] +[assembly:TypeForwardedToAttribute(typeof(GrpcPreconditions))] +[assembly:TypeForwardedToAttribute(typeof(AuthContext))] +[assembly:TypeForwardedToAttribute(typeof(ContextPropagationOptions))] +[assembly:TypeForwardedToAttribute(typeof(ContextPropagationToken))] +[assembly:TypeForwardedToAttribute(typeof(DeserializationContext))] +[assembly:TypeForwardedToAttribute(typeof(IAsyncStreamReader<>))] +[assembly:TypeForwardedToAttribute(typeof(IAsyncStreamWriter<>))] +[assembly:TypeForwardedToAttribute(typeof(IServerStreamWriter<>))] +[assembly:TypeForwardedToAttribute(typeof(Marshaller<>))] +[assembly:TypeForwardedToAttribute(typeof(Marshallers))] +[assembly:TypeForwardedToAttribute(typeof(Metadata))] +[assembly:TypeForwardedToAttribute(typeof(MethodType))] +[assembly:TypeForwardedToAttribute(typeof(IMethod))] +[assembly:TypeForwardedToAttribute(typeof(Method<,>))] +[assembly:TypeForwardedToAttribute(typeof(RpcException))] +[assembly:TypeForwardedToAttribute(typeof(SerializationContext))] +[assembly:TypeForwardedToAttribute(typeof(ServerCallContext))] +[assembly:TypeForwardedToAttribute(typeof(UnaryServerMethod<,>))] +[assembly:TypeForwardedToAttribute(typeof(ClientStreamingServerMethod<,>))] +[assembly:TypeForwardedToAttribute(typeof(ServerStreamingServerMethod<,>))] +[assembly:TypeForwardedToAttribute(typeof(DuplexStreamingServerMethod<,>))] +[assembly:TypeForwardedToAttribute(typeof(Status))] +[assembly:TypeForwardedToAttribute(typeof(StatusCode))] +[assembly:TypeForwardedToAttribute(typeof(WriteOptions))] +[assembly:TypeForwardedToAttribute(typeof(WriteFlags))] From 0f59ff7b4d5c3784ddea590d28c5df412fd56098 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 21 Jan 2019 15:43:09 +0100 Subject: [PATCH 057/218] remove unused methods from MarshalUtils --- src/csharp/Grpc.Core/Internal/MarshalUtils.cs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/csharp/Grpc.Core/Internal/MarshalUtils.cs b/src/csharp/Grpc.Core/Internal/MarshalUtils.cs index 09ded1a0363..e3e41617955 100644 --- a/src/csharp/Grpc.Core/Internal/MarshalUtils.cs +++ b/src/csharp/Grpc.Core/Internal/MarshalUtils.cs @@ -28,7 +28,6 @@ namespace Grpc.Core.Internal internal static class MarshalUtils { static readonly Encoding EncodingUTF8 = System.Text.Encoding.UTF8; - static readonly Encoding EncodingASCII = System.Text.Encoding.ASCII; /// /// Converts IntPtr pointing to a UTF-8 encoded byte array to string. @@ -62,21 +61,5 @@ namespace Grpc.Core.Internal { return EncodingUTF8.GetString(bytes); } - - /// - /// Returns byte array containing ASCII encoding of given string. - /// - public static byte[] GetBytesASCII(string str) - { - return EncodingASCII.GetBytes(str); - } - - /// - /// Get string from an ASCII encoded byte array. - /// - public static string GetStringASCII(byte[] bytes) - { - return EncodingASCII.GetString(bytes); - } } } From 140d8dcab9ad0bb9a2cb65e062917e206f285c82 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 21 Jan 2019 16:14:52 +0100 Subject: [PATCH 058/218] package build should build Grpc.Core.Api nuget --- src/csharp/build_packages_dotnetcli.bat | 1 + templates/src/csharp/build_packages_dotnetcli.bat.template | 1 + 2 files changed, 2 insertions(+) diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index fef1a43bb88..9fdfbcbd315 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -34,6 +34,7 @@ powershell -Command "cp -r ..\..\input_artifacts\protoc_* protoc_plugins" @rem To be able to build, we also need to put grpc_csharp_ext to its normal location xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release\ +%DOTNET% pack --configuration Release Grpc.Core.Api --output ..\..\..\artifacts || goto :error %DOTNET% pack --configuration Release Grpc.Core --output ..\..\..\artifacts || goto :error %DOTNET% pack --configuration Release Grpc.Core.Testing --output ..\..\..\artifacts || goto :error %DOTNET% pack --configuration Release Grpc.Auth --output ..\..\..\artifacts || goto :error diff --git a/templates/src/csharp/build_packages_dotnetcli.bat.template b/templates/src/csharp/build_packages_dotnetcli.bat.template index 877899c7bd9..aa35ae1e6fc 100755 --- a/templates/src/csharp/build_packages_dotnetcli.bat.template +++ b/templates/src/csharp/build_packages_dotnetcli.bat.template @@ -36,6 +36,7 @@ @rem To be able to build, we also need to put grpc_csharp_ext to its normal location xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release${"\\"} + %%DOTNET% pack --configuration Release Grpc.Core.Api --output ..\..\..\artifacts || goto :error %%DOTNET% pack --configuration Release Grpc.Core --output ..\..\..\artifacts || goto :error %%DOTNET% pack --configuration Release Grpc.Core.Testing --output ..\..\..\artifacts || goto :error %%DOTNET% pack --configuration Release Grpc.Auth --output ..\..\..\artifacts || goto :error From fbb04abd028d85aeb65af4abb2aad37640faf5af Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 25 Jan 2019 05:49:02 -0500 Subject: [PATCH 059/218] fix C# net45 distribtests --- test/distrib/csharp/DistribTest/DistribTest.csproj | 3 +++ test/distrib/csharp/DistribTest/packages.config | 1 + 2 files changed, 4 insertions(+) diff --git a/test/distrib/csharp/DistribTest/DistribTest.csproj b/test/distrib/csharp/DistribTest/DistribTest.csproj index 0bff9ff3e0b..d18bb05be68 100644 --- a/test/distrib/csharp/DistribTest/DistribTest.csproj +++ b/test/distrib/csharp/DistribTest/DistribTest.csproj @@ -62,6 +62,9 @@ ..\packages\Grpc.Core.__GRPC_NUGET_VERSION__\lib\net45\Grpc.Core.dll + + ..\packages\Grpc.Core.Api.__GRPC_NUGET_VERSION__\lib\net45\Grpc.Core.Api.dll + diff --git a/test/distrib/csharp/DistribTest/packages.config b/test/distrib/csharp/DistribTest/packages.config index 3cb2c46bcf0..134add7504d 100644 --- a/test/distrib/csharp/DistribTest/packages.config +++ b/test/distrib/csharp/DistribTest/packages.config @@ -6,6 +6,7 @@ + From 5e8608a97f95ba90e4591d4e270a9e95b1929bef Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 25 Jan 2019 06:19:54 -0500 Subject: [PATCH 060/218] update unity package build --- src/csharp/build_unitypackage.bat | 3 +++ templates/src/csharp/build_unitypackage.bat.template | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/csharp/build_unitypackage.bat b/src/csharp/build_unitypackage.bat index 6b66b941a8d..e304c6e4cf1 100644 --- a/src/csharp/build_unitypackage.bat +++ b/src/csharp/build_unitypackage.bat @@ -40,6 +40,9 @@ xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\bu @rem copy Grpc assemblies to the unity package skeleton @rem TODO(jtattermusch): Add Grpc.Auth assembly and its dependencies +copy /Y Grpc.Core.Api\bin\Release\net45\Grpc.Core.Api.dll unitypackage\unitypackage_skeleton\Plugins\Grpc.Core.Api\lib\net45\Grpc.Core.Api.dll || goto :error +copy /Y Grpc.Core.Api\bin\Release\net45\Grpc.Core.Api.pdb unitypackage\unitypackage_skeleton\Plugins\Grpc.Core.Api\lib\net45\Grpc.Core.Api.pdb || goto :error +copy /Y Grpc.Core.Api\bin\Release\net45\Grpc.Core.Api.xml unitypackage\unitypackage_skeleton\Plugins\Grpc.Core.Api\lib\net45\Grpc.Core.Api.xml || goto :error copy /Y Grpc.Core\bin\Release\net45\Grpc.Core.dll unitypackage\unitypackage_skeleton\Plugins\Grpc.Core\lib\net45\Grpc.Core.dll || goto :error copy /Y Grpc.Core\bin\Release\net45\Grpc.Core.pdb unitypackage\unitypackage_skeleton\Plugins\Grpc.Core\lib\net45\Grpc.Core.pdb || goto :error copy /Y Grpc.Core\bin\Release\net45\Grpc.Core.xml unitypackage\unitypackage_skeleton\Plugins\Grpc.Core\lib\net45\Grpc.Core.xml || goto :error diff --git a/templates/src/csharp/build_unitypackage.bat.template b/templates/src/csharp/build_unitypackage.bat.template index 76ec10dbd90..d6f2e3c7f0d 100755 --- a/templates/src/csharp/build_unitypackage.bat.template +++ b/templates/src/csharp/build_unitypackage.bat.template @@ -42,6 +42,9 @@ @rem copy Grpc assemblies to the unity package skeleton @rem TODO(jtattermusch): Add Grpc.Auth assembly and its dependencies + copy /Y Grpc.Core.Api\bin\Release\net45\Grpc.Core.Api.dll unitypackage\unitypackage_skeleton\Plugins\Grpc.Core.Api\lib\net45\Grpc.Core.Api.dll || goto :error + copy /Y Grpc.Core.Api\bin\Release\net45\Grpc.Core.Api.pdb unitypackage\unitypackage_skeleton\Plugins\Grpc.Core.Api\lib\net45\Grpc.Core.Api.pdb || goto :error + copy /Y Grpc.Core.Api\bin\Release\net45\Grpc.Core.Api.xml unitypackage\unitypackage_skeleton\Plugins\Grpc.Core.Api\lib\net45\Grpc.Core.Api.xml || goto :error copy /Y Grpc.Core\bin\Release\net45\Grpc.Core.dll unitypackage\unitypackage_skeleton\Plugins\Grpc.Core\lib\net45\Grpc.Core.dll || goto :error copy /Y Grpc.Core\bin\Release\net45\Grpc.Core.pdb unitypackage\unitypackage_skeleton\Plugins\Grpc.Core\lib\net45\Grpc.Core.pdb || goto :error copy /Y Grpc.Core\bin\Release\net45\Grpc.Core.xml unitypackage\unitypackage_skeleton\Plugins\Grpc.Core\lib\net45\Grpc.Core.xml || goto :error From c09423f8c19705a7357460edb07f44de68518f00 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 25 Jan 2019 12:48:08 +0100 Subject: [PATCH 061/218] add unity package skeleton for Grpc.Core.Api --- .../Plugins/Grpc.Core.Api.meta | 10 ++++++ .../Plugins/Grpc.Core.Api/lib.meta | 10 ++++++ .../Plugins/Grpc.Core.Api/lib/net45.meta | 10 ++++++ .../lib/net45/Grpc.Core.Api.dll.meta | 32 +++++++++++++++++++ .../lib/net45/Grpc.Core.Api.pdb.meta | 9 ++++++ .../lib/net45/Grpc.Core.Api.xml.meta | 9 ++++++ 6 files changed, 80 insertions(+) create mode 100644 src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api.meta create mode 100644 src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib.meta create mode 100644 src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45.meta create mode 100644 src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.dll.meta create mode 100644 src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.pdb.meta create mode 100644 src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.xml.meta diff --git a/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api.meta b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api.meta new file mode 100644 index 00000000000..f5d5149c2a5 --- /dev/null +++ b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 9b4ba511bab164bf9a5d0db8bb681b05 +folderAsset: yes +timeCreated: 1531219385 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib.meta b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib.meta new file mode 100644 index 00000000000..88c1aedbae1 --- /dev/null +++ b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 21a3894045fc74e85a09ab84c0e35c3a +folderAsset: yes +timeCreated: 1531219385 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45.meta b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45.meta new file mode 100644 index 00000000000..8012e3d581b --- /dev/null +++ b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 9fd1c7cd7b6ed4d5285de90a332fb93e +folderAsset: yes +timeCreated: 1531219385 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.dll.meta b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.dll.meta new file mode 100644 index 00000000000..7b939f861c8 --- /dev/null +++ b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.dll.meta @@ -0,0 +1,32 @@ +fileFormatVersion: 2 +guid: c9bf7237d50ec4e99ba7d2c153b80e8f +timeCreated: 1531219386 +licenseType: Free +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.pdb.meta b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.pdb.meta new file mode 100644 index 00000000000..48019325cdc --- /dev/null +++ b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.pdb.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: bf384c9cae7a648c488af0193b3e74c0 +timeCreated: 1531219385 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.xml.meta b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.xml.meta new file mode 100644 index 00000000000..e3814dc5850 --- /dev/null +++ b/src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core.Api/lib/net45/Grpc.Core.Api.xml.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0a4fb8823a783423880c9d8c9d3b5cf4 +timeCreated: 1531219386 +licenseType: Free +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From ae7254aa79b2ba5941b9bd95287958b4703748bc Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Fri, 25 Jan 2019 10:04:16 -0800 Subject: [PATCH 062/218] adding ptrace to asan --- third_party/toolchains/BUILD | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/third_party/toolchains/BUILD b/third_party/toolchains/BUILD index 04fd795b566..943690a2efd 100644 --- a/third_party/toolchains/BUILD +++ b/third_party/toolchains/BUILD @@ -56,6 +56,14 @@ platform( name: "dockerNetwork" value: "off" } + properties: { + name: "dockerAddCapabilities" + value: "SYS_PTRACE" + } + properties: { + name: "dockerPrivileged" + value: "true" + } """, ) @@ -87,6 +95,14 @@ platform( name: "dockerNetwork" value: "off" } + properties: { + name: "dockerAddCapabilities" + value: "SYS_PTRACE" + } + properties: { + name: "dockerPrivileged" + value: "true" + } """, ) From 59004219ff3781fc8b231cfa845e09c8df1c2521 Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Fri, 25 Jan 2019 10:07:49 -0800 Subject: [PATCH 063/218] removed override argument for asan --- tools/remote_build/rbe_common.bazelrc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tools/remote_build/rbe_common.bazelrc b/tools/remote_build/rbe_common.bazelrc index 9a86713f505..3438b1873d5 100644 --- a/tools/remote_build/rbe_common.bazelrc +++ b/tools/remote_build/rbe_common.bazelrc @@ -54,12 +54,6 @@ build:asan --copt=-gmlt # TODO(jtattermusch): use more reasonable test timeout build:asan --test_timeout=3600 build:asan --test_tag_filters=-qps_json_driver -build:asan --host_platform_remote_properties_override=''' - properties: { - name: "dockerDropCapabilities" - value: "" - } -''' # memory sanitizer: most settings are already in %workspace%/.bazelrc # we only need a few additional ones that are Foundry specific From 6d569523216d9f03d7c4816e2ad55e5140854a23 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Thu, 24 Jan 2019 14:32:40 -0800 Subject: [PATCH 064/218] Reuse subchannel's mu --- src/core/ext/filters/client_channel/subchannel.cc | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 8708cf21c3b..7f15cb416b9 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -202,7 +202,6 @@ class ConnectedSubchannelStateWatcher // Must be instantiated while holding c->mu. explicit ConnectedSubchannelStateWatcher(grpc_subchannel* c) : subchannel_(c) { - gpr_mu_init(&mu_); // Steal subchannel ref for connecting. GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "state_watcher"); GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "connecting"); @@ -235,13 +234,10 @@ class ConnectedSubchannelStateWatcher ~ConnectedSubchannelStateWatcher() { GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "state_watcher"); - gpr_mu_destroy(&mu_); } - void Orphan() override { - MutexLock lock(&mu_); - health_check_client_.reset(); - } + // Must be called while holding subchannel_->mu. + void Orphan() override { health_check_client_.reset(); } private: static void OnConnectivityChanged(void* arg, grpc_error* error) { @@ -307,13 +303,12 @@ class ConnectedSubchannelStateWatcher static void OnHealthChanged(void* arg, grpc_error* error) { auto* self = static_cast(arg); - MutexLock health_state_lock(&self->mu_); + grpc_subchannel* c = self->subchannel_; + MutexLock lock(&c->mu); if (self->health_state_ == GRPC_CHANNEL_SHUTDOWN) { self->Unref(); return; } - grpc_subchannel* c = self->subchannel_; - MutexLock lock(&c->mu); if (self->last_connectivity_state_ == GRPC_CHANNEL_READY) { grpc_connectivity_state_set(&c->state_and_health_tracker, self->health_state_, GRPC_ERROR_REF(error), @@ -330,8 +325,6 @@ class ConnectedSubchannelStateWatcher grpc_core::OrphanablePtr health_check_client_; grpc_closure on_health_changed_; grpc_connectivity_state health_state_ = GRPC_CHANNEL_CONNECTING; - // Ensure atomic change to health_check_client_ and health_state_. - gpr_mu mu_; }; } // namespace grpc_core From 16dcc172fe25ba4b8aedfc501e8763d92a1a7290 Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Fri, 25 Jan 2019 10:21:24 -0800 Subject: [PATCH 065/218] putting a retry on apt-get jq --- .../helper_scripts/prepare_build_linux_perf_rc | 8 +++++++- tools/internal_ci/linux/grpc_run_tests_matrix.sh | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc b/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc index ff5593e031a..b66ac38942f 100644 --- a/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc +++ b/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc @@ -21,7 +21,13 @@ ulimit -c unlimited # Performance PR testing needs GH API key and PR metadata to comment results if [ -n "$KOKORO_GITHUB_PULL_REQUEST_NUMBER" ]; then - sudo apt-get install -y jq + retry=0 + until [ $retry -ge 3 ] + do + sudo apt-get install -y jq && break + retry=$[$retry+1] + sleep 5 + done export ghprbTargetBranch=$(curl -s https://api.github.com/repos/grpc/grpc/pulls/$KOKORO_GITHUB_PULL_REQUEST_NUMBER | jq -r .base.ref) fi diff --git a/tools/internal_ci/linux/grpc_run_tests_matrix.sh b/tools/internal_ci/linux/grpc_run_tests_matrix.sh index f9acd814ae8..f8fd963ccf3 100755 --- a/tools/internal_ci/linux/grpc_run_tests_matrix.sh +++ b/tools/internal_ci/linux/grpc_run_tests_matrix.sh @@ -23,7 +23,13 @@ source tools/internal_ci/helper_scripts/prepare_build_linux_rc # If this is a PR using RUN_TESTS_FLAGS var, then add flags to filter tests if [ -n "$KOKORO_GITHUB_PULL_REQUEST_NUMBER" ] && [ -n "$RUN_TESTS_FLAGS" ]; then sudo apt-get update - sudo apt-get install -y jq + retry=0 + until [ $retry -ge 3 ] + do + sudo apt-get install -y jq && break + retry=$[$retry+1] + sleep 5 + done ghprbTargetBranch=$(curl -s https://api.github.com/repos/grpc/grpc/pulls/$KOKORO_GITHUB_PULL_REQUEST_NUMBER | jq -r .base.ref) export RUN_TESTS_FLAGS="$RUN_TESTS_FLAGS --filter_pr_tests --base_branch origin/$ghprbTargetBranch" fi From 7a164229dbbb0944eb9410b15415d626d44937c3 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Fri, 25 Jan 2019 10:25:08 -0800 Subject: [PATCH 066/218] Address reviewer comments --- include/grpcpp/server.h | 23 +++++++++++------------ src/core/lib/iomgr/executor.cc | 10 +++++----- src/cpp/server/server_cc.cc | 17 ++++++++--------- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index 5bbbd704a02..df68cf31441 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -248,11 +248,11 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { /// the \a sync_server_cqs) std::vector> sync_req_mgrs_; - // Outstanding callback requests. The vector is indexed by method with a - // list per method. Each element should store its own iterator - // in the list and should erase it when the request is actually bound to - // an RPC. Synchronize this list with its own mu_ (not the server mu_) since - // these must be active at Shutdown when the server mu_ is locked + // Outstanding callback requests. The vector is indexed by method with a list + // per method. Each element should store its own iterator in the list and + // should erase it when the request is actually bound to an RPC. Synchronize + // this list with its own mu_ (not the server mu_) since these must be active + // at Shutdown when the server mu_ is locked. // TODO(vjpai): Merge with the core request matcher to avoid duplicate work struct MethodReqList { std::mutex reqs_mu; @@ -274,13 +274,12 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { std::condition_variable shutdown_cv_; // It is ok (but not required) to nest callback_reqs_mu_ under mu_ . - // Incrementing callback_reqs_outstanding_ is ok without a lock - // but it should only be decremented under the lock in case it is the - // last request and enables the server shutdown. The increment is - // performance-critical since it happens during periods of increasing - // load; the decrement happens only when memory is maxed out, during server - // shutdown, or (possibly in a future version) during decreasing load, so - // it is less performance-critical. + // Incrementing callback_reqs_outstanding_ is ok without a lock but it must be + // decremented under the lock in case it is the last request and enables the + // server shutdown. The increment is performance-critical since it happens + // during periods of increasing load; the decrement happens only when memory + // is maxed out, during server shutdown, or (possibly in a future version) + // during decreasing load, so it is less performance-critical. std::mutex callback_reqs_mu_; std::condition_variable callback_reqs_done_cv_; std::atomic_int callback_reqs_outstanding_{0}; diff --git a/src/core/lib/iomgr/executor.cc b/src/core/lib/iomgr/executor.cc index 34683273cf6..1e7c6a907a2 100644 --- a/src/core/lib/iomgr/executor.cc +++ b/src/core/lib/iomgr/executor.cc @@ -111,11 +111,11 @@ size_t Executor::RunClosures(const char* executor_name, grpc_closure_list list) { size_t n = 0; - // In the executor, the ExecCtx for the thread is declared - // in the executor thread itself, but this is the point where we - // could start seeing application-level callbacks. No need to - // create a new ExecCtx, though, since there already is one and it is - // flushed (but not destructed) in this function itself + // In the executor, the ExecCtx for the thread is declared in the executor + // thread itself, but this is the point where we could start seeing + // application-level callbacks. No need to create a new ExecCtx, though, + // since there already is one and it is flushed (but not destructed) in this + // function itself. grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_closure* c = list.head; diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 12aa52ef704..1e642681467 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -62,11 +62,11 @@ namespace { #define DEFAULT_CALLBACK_REQS_PER_METHOD 512 // What is the (soft) limit for outstanding requests in the server -#define MAXIMUM_CALLBACK_REQS_OUTSTANDING 30000 +#define SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING 30000 -// If the number of unmatched requests for a method drops below this amount, -// try to allocate extra unless it pushes the total number of callbacks above -// the soft maximum +// If the number of unmatched requests for a method drops below this amount, try +// to allocate extra unless it pushes the total number of callbacks above the +// soft maximum #define SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD 128 class DefaultGlobalCallbacks final : public Server::GlobalCallbacks { @@ -185,11 +185,10 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { GPR_ASSERT(cq_ && !in_flight_); in_flight_ = true; if (method_tag_) { - if (GRPC_CALL_OK != - grpc_server_request_registered_call( + if (grpc_server_request_registered_call( server, method_tag_, &call_, &deadline_, &request_metadata_, has_request_payload_ ? &request_payload_ : nullptr, cq_, - notify_cq, this)) { + notify_cq, this) != GRPC_CALL_OK) { TeardownRequest(); return; } @@ -452,7 +451,7 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { (req_->req_list_->reqs_list_sz < SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD && req_->server_->callback_reqs_outstanding_ < - MAXIMUM_CALLBACK_REQS_OUTSTANDING)) { + SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING)) { spawn_new = true; } } @@ -528,7 +527,7 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { // load no longer justifies it. Consider measuring // dynamic load and setting a target accordingly. if (req_->server_->callback_reqs_outstanding_ < - MAXIMUM_CALLBACK_REQS_OUTSTANDING) { + SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING) { req_->Clear(); req_->Setup(); } else { From bd19173114eb71c288890e52e874f0c9d8f8015d Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 25 Jan 2019 10:29:39 -0800 Subject: [PATCH 067/218] Collect timestamps for all data written for a stream instead of just data frames --- src/core/ext/transport/chttp2/transport/writing.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc index 265d3365d3c..cf77ddc8278 100644 --- a/src/core/ext/transport/chttp2/transport/writing.cc +++ b/src/core/ext/transport/chttp2/transport/writing.cc @@ -363,7 +363,6 @@ class DataSendContext { grpc_chttp2_encode_data(s_->id, &s_->compressed_data_buffer, send_bytes, is_last_frame_, &s_->stats.outgoing, &t_->outbuf); s_->flow_control->SentData(send_bytes); - s_->byte_counter += send_bytes; if (s_->compressed_data_buffer.length == 0) { s_->sending_bytes += s_->uncompressed_data_size; } @@ -498,9 +497,6 @@ class StreamWriteContext { data_send_context.CompressMoreBytes(); } } - if (s_->traced && grpc_endpoint_can_track_err(t_->ep)) { - grpc_core::ContextList::Append(&t_->cl, s_); - } write_context_->ResetPingClock(); if (data_send_context.is_last_frame()) { SentLastFrame(); @@ -610,11 +606,18 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write( (according to available window sizes) and add to the output buffer */ while (grpc_chttp2_stream* s = ctx.NextStream()) { StreamWriteContext stream_ctx(&ctx, s); + size_t orig_len = t->outbuf.length; stream_ctx.FlushInitialMetadata(); stream_ctx.FlushWindowUpdates(); stream_ctx.FlushData(); stream_ctx.FlushTrailingMetadata(); - + if (t->outbuf.length > orig_len) { + /* Add this stream to the list of the contexts to be traced at TCP */ + s->byte_counter += t->outbuf.length - orig_len; + if (s->traced && grpc_endpoint_can_track_err(t->ep)) { + grpc_core::ContextList::Append(&t->cl, s); + } + } if (stream_ctx.stream_became_writable()) { if (!grpc_chttp2_list_add_writing_stream(t, s)) { /* already in writing list: drop ref */ From d098a0dabc1be2ed0a89359ed6fcca62b430b332 Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 25 Jan 2019 12:12:39 -0800 Subject: [PATCH 068/218] fixed small issue in run_tests.sh and remove duplicate in CallTest.php --- src/php/bin/run_tests.sh | 9 ++++----- src/php/tests/unit_tests/CallTest.php | 10 ---------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/php/bin/run_tests.sh b/src/php/bin/run_tests.sh index cfe16ee3e85..2f9c9f636ec 100755 --- a/src/php/bin/run_tests.sh +++ b/src/php/bin/run_tests.sh @@ -32,9 +32,8 @@ php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \ export ZEND_DONT_UNLOAD_MODULES=1 export USE_ZEND_ALLOC=0 # Detect whether valgrind is executable -if ! [ -x "$(command -v valgrind)" ]; then - echo 'Error: valgrind is not installed and is not executable' >&2 - exit 1 -fi -valgrind --error-exitcode=10 --leak-check=yes php $extension_dir -d max_execution_time=300 \ +if [ -x "$(command -v valgrind)" ]; then + valgrind --error-exitcode=10 --leak-check=yes php $extension_dir -d max_execution_time=300 \ ../tests/MemoryLeakTest/MemoryLeakTest.php + exit 0 +fi diff --git a/src/php/tests/unit_tests/CallTest.php b/src/php/tests/unit_tests/CallTest.php index 20c35299cb0..28098c4016e 100644 --- a/src/php/tests/unit_tests/CallTest.php +++ b/src/php/tests/unit_tests/CallTest.php @@ -96,16 +96,6 @@ class CallTest extends PHPUnit_Framework_TestCase $this->assertTrue($result->send_metadata); } - public function testAddMultiAndMultiValueMetadata() - { - $batch = [ - Grpc\OP_SEND_INITIAL_METADATA => ['key1' => ['value1', 'value2'], - 'key2' => ['value3', 'value4'],], - ]; - $result = $this->call->startBatch($batch); - $this->assertTrue($result->send_metadata); - } - public function testGetPeer() { $this->assertTrue(is_string($this->call->getPeer())); From ca30b2240f6f8e86b51452097c3cb43c5d4f7117 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Fri, 25 Jan 2019 13:29:58 -0800 Subject: [PATCH 069/218] Revert c-ares as the default resolvre --- .../client_channel/resolver/dns/c_ares/dns_resolver_ares.cc | 3 +-- .../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(+), 3 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 bf8b0ea5f62..fe245bfef09 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 @@ -478,8 +478,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 || strlen(resolver_env) == 0 || - 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 a4438cb100e..8a5b1f53dcf 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 f817d49e478fc8ae28ee8999d3195c759ed12e3a Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Fri, 25 Jan 2019 14:03:37 -0800 Subject: [PATCH 070/218] Update the README.md --- src/python/grpcio_tests/tests/qps/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/python/grpcio_tests/tests/qps/README.md b/src/python/grpcio_tests/tests/qps/README.md index f5149509ce3..8ae155a5b4b 100644 --- a/src/python/grpcio_tests/tests/qps/README.md +++ b/src/python/grpcio_tests/tests/qps/README.md @@ -15,13 +15,15 @@ All Python related benchmark scenarios are: * python_protobuf_sync_streaming_qps_unconstrained * python_protobuf_sync_unary_ping_pong_1MB -Here I picked the top 2 most representative scenarios of them, and reduce their benchmark duration from 30 seconds to 10 seconds: +Here we picked a small but representative subset, and reduce their benchmark duration from 30 seconds to 10 seconds: * python_protobuf_async_unary_ping_pong * python_protobuf_sync_streaming_ping_pong ## Why keep the scenario file if it can be generated? -Well... The `tools/run_tests/performance/scenario_config.py` is 1274 lines long. The intention of building these benchmark tools is reducing the complexity of existing infrastructure code. So, instead of calling layers of abstraction to generate the scenario file, keeping a valid static copy is more preferable. +Well... The `tools/run_tests/performance/scenario_config.py` is 1274 lines long. The intention of building these benchmark tools is reducing the complexity of existing infrastructure code. So, instead of calling layers of abstraction to generate the scenario file, keeping a valid static copy is preferable. + +Also, if the use case for this tool grows beyond simple static scenarios, we can incorporate automatic generation and selection of scenarios into the tool. ## How to run it? @@ -29,7 +31,7 @@ Well... The `tools/run_tests/performance/scenario_config.py` is 1274 lines long. bazel test --test_output=streamed src/python/grpcio_tests/tests/qps:basic_benchmark_test ``` -## How is the output look like? +## What does the output look like? ``` RUNNING SCENARIO: python_protobuf_async_unary_ping_pong From bf098ed49b6a0c24f8b3fba50bb9c581513bf593 Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 25 Jan 2019 15:13:40 -0800 Subject: [PATCH 071/218] remove exit status --- src/php/bin/run_tests.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/src/php/bin/run_tests.sh b/src/php/bin/run_tests.sh index 2f9c9f636ec..861ce433c4e 100755 --- a/src/php/bin/run_tests.sh +++ b/src/php/bin/run_tests.sh @@ -35,5 +35,4 @@ export USE_ZEND_ALLOC=0 if [ -x "$(command -v valgrind)" ]; then valgrind --error-exitcode=10 --leak-check=yes php $extension_dir -d max_execution_time=300 \ ../tests/MemoryLeakTest/MemoryLeakTest.php - exit 0 fi From 08e06da780d3794e8b457f762179abe08fbd220f Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Fri, 25 Jan 2019 15:25:34 -0800 Subject: [PATCH 072/218] explicitly lengthened timeout --- test/cpp/end2end/BUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index 4c28eee4d15..c061947e1cb 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -223,6 +223,7 @@ grpc_cc_test( ":end2end_test_lib", ], size = "large", # with poll-cv this takes long, see #17493 + timeout = "long", ) grpc_cc_test( From dd5ead2ac1ef1a442289b911f6e6602b4c808a82 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 25 Jan 2019 18:41:06 -0800 Subject: [PATCH 073/218] Extra argument for grpc_endpoint_write --- test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm b/test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm index fbc34c74d66..528f4b1cdad 100644 --- a/test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm @@ -167,7 +167,7 @@ static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const ch slice = grpc_slice_from_static_buffer(write_buffer, kBufferSize); grpc_slice_buffer_add(&write_slices, slice); init_event_closure(&write_done, &write); - grpc_endpoint_write(ep_, &write_slices, &write_done); + grpc_endpoint_write(ep_, &write_slices, &write_done, nullptr); XCTAssertEqual([self waitForEvent:&write timeout:kWriteTimeout], YES); XCTAssertEqual(reinterpret_cast(write), GRPC_ERROR_NONE); @@ -224,7 +224,7 @@ static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const ch slice = grpc_slice_from_static_buffer(write_buffer, kBufferSize); grpc_slice_buffer_add(&write_slices, slice); init_event_closure(&write_done, &write); - grpc_endpoint_write(ep_, &write_slices, &write_done); + grpc_endpoint_write(ep_, &write_slices, &write_done, nullptr); XCTAssertEqual([self waitForEvent:&write timeout:kWriteTimeout], YES); XCTAssertEqual(reinterpret_cast(write), GRPC_ERROR_NONE); @@ -273,7 +273,7 @@ static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const ch slice = grpc_slice_from_static_buffer(write_buffer, kBufferSize); grpc_slice_buffer_add(&write_slices, slice); init_event_closure(&write_done, &write); - grpc_endpoint_write(ep_, &write_slices, &write_done); + grpc_endpoint_write(ep_, &write_slices, &write_done, nullptr); XCTAssertEqual([self waitForEvent:&write timeout:kWriteTimeout], YES); XCTAssertEqual(reinterpret_cast(write), GRPC_ERROR_NONE); From 564be999dea89dd88ff4cc4619ff3ea289da21e9 Mon Sep 17 00:00:00 2001 From: Kumar Akshay Date: Mon, 14 Jan 2019 00:19:03 +0530 Subject: [PATCH 074/218] Fix warning Fix clang format --- .../server/load_reporter/load_reporter_async_service_impl.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc b/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc index d001199b8c5..859ad9946c8 100644 --- a/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc +++ b/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc @@ -211,8 +211,8 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::OnReadDone( load_key_); const auto& load_report_interval = initial_request.load_report_interval(); load_report_interval_ms_ = - static_cast(load_report_interval.seconds() * 1000 + - load_report_interval.nanos() / 1000); + static_cast(load_report_interval.seconds() * 1000 + + load_report_interval.nanos() / 1000); gpr_log( GPR_INFO, "[LRS %p] Initial request received. Start load reporting (load " From cc6ef78972f7d8c745c11915dfac1475a82e0c24 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 28 Jan 2019 09:13:57 -0500 Subject: [PATCH 075/218] Use test timeout implied by test size (unless overridden). Currently, grpc_cc_test with size="large" will still have timeout="moderate" (which corresponds to medium size test) because the timeout will be overriden by the default arg. Fixing as this behavior is very counterintuitive. --- bazel/grpc_build_system.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl index caeafc76b69..be85bc87324 100644 --- a/bazel/grpc_build_system.bzl +++ b/bazel/grpc_build_system.bzl @@ -132,7 +132,7 @@ def grpc_proto_library( generate_mocks = generate_mocks, ) -def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data = [], uses_polling = True, language = "C++", size = "medium", timeout = "moderate", tags = [], exec_compatible_with = []): +def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data = [], uses_polling = True, language = "C++", size = "medium", timeout = None, tags = [], exec_compatible_with = []): copts = [] if language.upper() == "C": copts = if_not_windows(["-std=c99"]) From baaf93b830d9af858f7315875c7342fadd9dcf7d Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 28 Jan 2019 09:19:28 -0500 Subject: [PATCH 076/218] revert no-longer-needed hotfix from #17820 --- test/cpp/end2end/BUILD | 1 - 1 file changed, 1 deletion(-) diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index c061947e1cb..4c28eee4d15 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -223,7 +223,6 @@ grpc_cc_test( ":end2end_test_lib", ], size = "large", # with poll-cv this takes long, see #17493 - timeout = "long", ) grpc_cc_test( From d4f58b0f226c0008ed5e21b1f4b76c48ad5bea5b Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 28 Jan 2019 16:05:12 +0100 Subject: [PATCH 077/218] Revert "Collect timestamps for all data written for a stream instead of just data frames" --- src/core/ext/transport/chttp2/transport/writing.cc | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc index cf77ddc8278..265d3365d3c 100644 --- a/src/core/ext/transport/chttp2/transport/writing.cc +++ b/src/core/ext/transport/chttp2/transport/writing.cc @@ -363,6 +363,7 @@ class DataSendContext { grpc_chttp2_encode_data(s_->id, &s_->compressed_data_buffer, send_bytes, is_last_frame_, &s_->stats.outgoing, &t_->outbuf); s_->flow_control->SentData(send_bytes); + s_->byte_counter += send_bytes; if (s_->compressed_data_buffer.length == 0) { s_->sending_bytes += s_->uncompressed_data_size; } @@ -497,6 +498,9 @@ class StreamWriteContext { data_send_context.CompressMoreBytes(); } } + if (s_->traced && grpc_endpoint_can_track_err(t_->ep)) { + grpc_core::ContextList::Append(&t_->cl, s_); + } write_context_->ResetPingClock(); if (data_send_context.is_last_frame()) { SentLastFrame(); @@ -606,18 +610,11 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write( (according to available window sizes) and add to the output buffer */ while (grpc_chttp2_stream* s = ctx.NextStream()) { StreamWriteContext stream_ctx(&ctx, s); - size_t orig_len = t->outbuf.length; stream_ctx.FlushInitialMetadata(); stream_ctx.FlushWindowUpdates(); stream_ctx.FlushData(); stream_ctx.FlushTrailingMetadata(); - if (t->outbuf.length > orig_len) { - /* Add this stream to the list of the contexts to be traced at TCP */ - s->byte_counter += t->outbuf.length - orig_len; - if (s->traced && grpc_endpoint_can_track_err(t->ep)) { - grpc_core::ContextList::Append(&t->cl, s); - } - } + if (stream_ctx.stream_became_writable()) { if (!grpc_chttp2_list_add_writing_stream(t, s)) { /* already in writing list: drop ref */ From ee23fc3d2e1898bb712b67aa5f3f2a891695d444 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Mon, 28 Jan 2019 10:47:12 -0800 Subject: [PATCH 078/218] Avoid 'which' failure --- third_party/py/python_configure.bzl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/third_party/py/python_configure.bzl b/third_party/py/python_configure.bzl index 6e25cc493b3..9036a95909b 100644 --- a/third_party/py/python_configure.bzl +++ b/third_party/py/python_configure.bzl @@ -139,7 +139,12 @@ def _symlink_genrule_for_dir(repository_ctx, def _get_python_bin(repository_ctx): """Gets the python bin path.""" python_bin = repository_ctx.os.environ.get(_PYTHON_BIN_PATH, 'python') - python_bin_path = repository_ctx.which(python_bin) + if not '/' in python_bin and not '\\' in python_bin: + # It's a command, use 'which' to find its path. + python_bin_path = repository_ctx.which(python_bin) + else: + # It's a path, use it as it is. + python_bin_path = python_bin if python_bin_path != None: return str(python_bin_path) _fail("Cannot find python in PATH, please make sure " + From 7e90dad67543d393379a15b9c1cb7674d64b7d05 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Mon, 28 Jan 2019 10:55:19 -0800 Subject: [PATCH 079/218] Adopt reviewer's advices --- src/python/grpcio_tests/tests/BUILD.bazel | 10 +++++----- ...{bazel_patch.py => bazel_namespace_package_hack.py} | 2 +- src/python/grpcio_tests/tests/interop/BUILD.bazel | 2 +- src/python/grpcio_tests/tests/interop/methods.py | 4 ++-- src/python/grpcio_tests/tests/status/BUILD.bazel | 2 +- .../grpcio_tests/tests/status/_grpc_status_test.py | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) rename src/python/grpcio_tests/tests/{bazel_patch.py => bazel_namespace_package_hack.py} (97%) diff --git a/src/python/grpcio_tests/tests/BUILD.bazel b/src/python/grpcio_tests/tests/BUILD.bazel index 118cd0ea0dd..b908ab85173 100644 --- a/src/python/grpcio_tests/tests/BUILD.bazel +++ b/src/python/grpcio_tests/tests/BUILD.bazel @@ -1,8 +1,8 @@ py_library( - name = "bazel_patch", - srcs = ["bazel_patch.py"], - visibility = ["//visibility:public"], - data=[ - "//src/python/grpcio_tests/tests/unit/credentials", + name = "bazel_namespace_package_hack", + srcs = ["bazel_namespace_package_hack.py"], + visibility = [ + "//src/python/grpcio_tests/tests/status:__subpackages__", + "//src/python/grpcio_tests/tests/interop:__subpackages__", ], ) diff --git a/src/python/grpcio_tests/tests/bazel_patch.py b/src/python/grpcio_tests/tests/bazel_namespace_package_hack.py similarity index 97% rename from src/python/grpcio_tests/tests/bazel_patch.py rename to src/python/grpcio_tests/tests/bazel_namespace_package_hack.py index af48697de30..c6b72c327b1 100644 --- a/src/python/grpcio_tests/tests/bazel_patch.py +++ b/src/python/grpcio_tests/tests/bazel_namespace_package_hack.py @@ -22,7 +22,7 @@ import sys # Python process to parse the .pth file in the sys.path to resolve namespace # package in the right place. # Analysis in depth: https://github.com/bazelbuild/rules_python/issues/55 -def bazel_patch(): +def sys_path_to_site_dir_hack(): """Add valid sys.path item to site directory to parse the .pth files.""" for item in sys.path: if os.path.exists(item): diff --git a/src/python/grpcio_tests/tests/interop/BUILD.bazel b/src/python/grpcio_tests/tests/interop/BUILD.bazel index bb5f0f344e2..770b1f78a70 100644 --- a/src/python/grpcio_tests/tests/interop/BUILD.bazel +++ b/src/python/grpcio_tests/tests/interop/BUILD.bazel @@ -29,7 +29,7 @@ py_library( srcs = ["methods.py"], deps = [ "//src/python/grpcio/grpc:grpcio", - "//src/python/grpcio_tests/tests:bazel_patch", + "//src/python/grpcio_tests/tests:bazel_namespace_package_hack", "//src/proto/grpc/testing:py_empty_proto", "//src/proto/grpc/testing:py_messages_proto", "//src/proto/grpc/testing:py_test_proto", diff --git a/src/python/grpcio_tests/tests/interop/methods.py b/src/python/grpcio_tests/tests/interop/methods.py index e037046691b..e16966e3918 100644 --- a/src/python/grpcio_tests/tests/interop/methods.py +++ b/src/python/grpcio_tests/tests/interop/methods.py @@ -13,8 +13,8 @@ # limitations under the License. """Implementations of interoperability test methods.""" -from tests.bazel_patch import bazel_patch -bazel_patch() +from tests import bazel_namespace_package_hack +bazel_namespace_package_hack.sys_path_to_site_dir_hack() import enum import json diff --git a/src/python/grpcio_tests/tests/status/BUILD.bazel b/src/python/grpcio_tests/tests/status/BUILD.bazel index 21dea5a76dc..b163fe3975e 100644 --- a/src/python/grpcio_tests/tests/status/BUILD.bazel +++ b/src/python/grpcio_tests/tests/status/BUILD.bazel @@ -10,7 +10,7 @@ py_test( deps = [ "//src/python/grpcio/grpc:grpcio", "//src/python/grpcio_status/grpc_status:grpc_status", - "//src/python/grpcio_tests/tests:bazel_patch", + "//src/python/grpcio_tests/tests:bazel_namespace_package_hack", "//src/python/grpcio_tests/tests/unit:test_common", "//src/python/grpcio_tests/tests/unit/framework/common:common", requirement('protobuf'), diff --git a/src/python/grpcio_tests/tests/status/_grpc_status_test.py b/src/python/grpcio_tests/tests/status/_grpc_status_test.py index 67b1785becb..77f5fb283d1 100644 --- a/src/python/grpcio_tests/tests/status/_grpc_status_test.py +++ b/src/python/grpcio_tests/tests/status/_grpc_status_test.py @@ -13,8 +13,8 @@ # limitations under the License. """Tests of grpc_status.""" -from tests.bazel_patch import bazel_patch -bazel_patch() +from tests import bazel_namespace_package_hack +bazel_namespace_package_hack.sys_path_to_site_dir_hack() import unittest From 062e2bcadea19e3a0fb3a518207d91109828c97b Mon Sep 17 00:00:00 2001 From: Bill Feng Date: Mon, 28 Jan 2019 11:22:20 -0800 Subject: [PATCH 080/218] added retry statements to jq installation commands --- .../helper_scripts/prepare_build_linux_perf_rc | 8 +++++++- tools/internal_ci/linux/grpc_run_tests_matrix.sh | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc b/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc index ff5593e031a..b66ac38942f 100644 --- a/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc +++ b/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc @@ -21,7 +21,13 @@ ulimit -c unlimited # Performance PR testing needs GH API key and PR metadata to comment results if [ -n "$KOKORO_GITHUB_PULL_REQUEST_NUMBER" ]; then - sudo apt-get install -y jq + retry=0 + until [ $retry -ge 3 ] + do + sudo apt-get install -y jq && break + retry=$[$retry+1] + sleep 5 + done export ghprbTargetBranch=$(curl -s https://api.github.com/repos/grpc/grpc/pulls/$KOKORO_GITHUB_PULL_REQUEST_NUMBER | jq -r .base.ref) fi diff --git a/tools/internal_ci/linux/grpc_run_tests_matrix.sh b/tools/internal_ci/linux/grpc_run_tests_matrix.sh index f9acd814ae8..f8fd963ccf3 100755 --- a/tools/internal_ci/linux/grpc_run_tests_matrix.sh +++ b/tools/internal_ci/linux/grpc_run_tests_matrix.sh @@ -23,7 +23,13 @@ source tools/internal_ci/helper_scripts/prepare_build_linux_rc # If this is a PR using RUN_TESTS_FLAGS var, then add flags to filter tests if [ -n "$KOKORO_GITHUB_PULL_REQUEST_NUMBER" ] && [ -n "$RUN_TESTS_FLAGS" ]; then sudo apt-get update - sudo apt-get install -y jq + retry=0 + until [ $retry -ge 3 ] + do + sudo apt-get install -y jq && break + retry=$[$retry+1] + sleep 5 + done ghprbTargetBranch=$(curl -s https://api.github.com/repos/grpc/grpc/pulls/$KOKORO_GITHUB_PULL_REQUEST_NUMBER | jq -r .base.ref) export RUN_TESTS_FLAGS="$RUN_TESTS_FLAGS --filter_pr_tests --base_branch origin/$ghprbTargetBranch" fi From 1a688982a424b849c7fb5702a3357d9789cbaa54 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Mon, 28 Jan 2019 11:33:19 -0800 Subject: [PATCH 081/218] Cast the str type if it is unicode --- src/python/grpcio/_parallel_compile_patch.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/python/grpcio/_parallel_compile_patch.py b/src/python/grpcio/_parallel_compile_patch.py index 4d03ef49ba0..de48a4099b5 100644 --- a/src/python/grpcio/_parallel_compile_patch.py +++ b/src/python/grpcio/_parallel_compile_patch.py @@ -19,6 +19,7 @@ Enabling parallel build helps a lot. import distutils.ccompiler import os +import six try: BUILD_EXT_COMPILER_JOBS = int( @@ -37,6 +38,8 @@ def _parallel_compile(self, extra_preargs=None, extra_postargs=None, depends=None): + if isinstance(output_dir, six.text_type): + output_dir = str(output_dir) # setup the same way as distutils.ccompiler.CCompiler # https://github.com/python/cpython/blob/31368a4f0e531c19affe2a1becd25fc316bc7501/Lib/distutils/ccompiler.py#L564 macros, objects, extra_postargs, pp_opts, build = self._setup_compile( From 91fde06b12c0bda8da88141f5ae756b526e039ee Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Mon, 28 Jan 2019 12:12:06 -0800 Subject: [PATCH 082/218] Remove the dependency of 'six' --- src/python/grpcio/_parallel_compile_patch.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/python/grpcio/_parallel_compile_patch.py b/src/python/grpcio/_parallel_compile_patch.py index de48a4099b5..b34aa17fd0b 100644 --- a/src/python/grpcio/_parallel_compile_patch.py +++ b/src/python/grpcio/_parallel_compile_patch.py @@ -19,7 +19,6 @@ Enabling parallel build helps a lot. import distutils.ccompiler import os -import six try: BUILD_EXT_COMPILER_JOBS = int( @@ -38,12 +37,10 @@ def _parallel_compile(self, extra_preargs=None, extra_postargs=None, depends=None): - if isinstance(output_dir, six.text_type): - output_dir = str(output_dir) # setup the same way as distutils.ccompiler.CCompiler # https://github.com/python/cpython/blob/31368a4f0e531c19affe2a1becd25fc316bc7501/Lib/distutils/ccompiler.py#L564 macros, objects, extra_postargs, pp_opts, build = self._setup_compile( - output_dir, macros, include_dirs, sources, depends, extra_postargs) + str(output_dir), macros, include_dirs, sources, depends, extra_postargs) cc_args = self._get_cc_args(pp_opts, debug, extra_preargs) def _compile_single_file(obj): From abd75e04aadb4681b768c029dc0d7372c789da93 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Mon, 28 Jan 2019 13:36:26 -0800 Subject: [PATCH 083/218] Remove unneeded header --- src/core/lib/iomgr/exec_ctx.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index 36c1a907cbc..c6c30d3129e 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -28,7 +28,6 @@ #include "src/core/lib/gpr/tls.h" #include "src/core/lib/gprpp/fork.h" -#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/iomgr/closure.h" typedef int64_t grpc_millis; From d98de1facf4680fb5b03b8bec94aaffd8a664d7e Mon Sep 17 00:00:00 2001 From: John Luo Date: Tue, 22 Jan 2019 09:17:19 -0800 Subject: [PATCH 084/218] Add new overload to BindService that doesn't require an implementation --- src/compiler/csharp_generator.cc | 31 +++++++++++++++ src/csharp/Grpc.Core/ServiceBinderBase.cs | 14 +++++++ src/csharp/Grpc.Examples/MathGrpc.cs | 17 +++++++-- src/csharp/Grpc.HealthCheck/HealthGrpc.cs | 15 ++++++-- .../BenchmarkServiceGrpc.cs | 18 +++++++-- src/csharp/Grpc.IntegrationTesting/Control.cs | 10 +++-- src/csharp/Grpc.IntegrationTesting/Empty.cs | 1 + .../EmptyServiceGrpc.cs | 13 +++++-- .../Grpc.IntegrationTesting/MetricsGrpc.cs | 17 +++++++-- .../ReportQpsScenarioServiceGrpc.cs | 14 +++++-- .../Grpc.IntegrationTesting/TestGrpc.cs | 38 +++++++++++++++++-- .../WorkerServiceGrpc.cs | 17 +++++++-- src/csharp/Grpc.Reflection/ReflectionGrpc.cs | 14 +++++-- 13 files changed, 187 insertions(+), 32 deletions(-) diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index 59ddbd82f61..c1eaf971483 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -645,6 +645,36 @@ void GenerateBindServiceWithBinderMethod(Printer* out, out->Print("\n"); } +void GenerateBindServiceWithBinderMethodWithoutImplementation( + Printer* out, const ServiceDescriptor* service) { + out->Print( + "/// Register service method with a service " + "binder without implementation. Useful when customizing the service " + "binding logic.\n" + "/// Note: this method is part of an experimental API that can change or " + "be " + "removed without any prior notice.\n"); + out->Print( + "/// Service methods will be bound by " + "calling AddMethod on this object." + "\n"); + out->Print( + "public static void BindService(grpc::ServiceBinderBase " + "serviceBinder)\n"); + out->Print("{\n"); + out->Indent(); + + for (int i = 0; i < service->method_count(); i++) { + const MethodDescriptor* method = service->method(i); + out->Print("serviceBinder.AddMethod($methodfield$);\n", "methodfield", + GetMethodFieldName(method)); + } + + out->Outdent(); + out->Print("}\n"); + out->Print("\n"); +} + void GenerateService(Printer* out, const ServiceDescriptor* service, bool generate_client, bool generate_server, bool internal_access) { @@ -674,6 +704,7 @@ void GenerateService(Printer* out, const ServiceDescriptor* service, if (generate_server) { GenerateBindServiceMethod(out, service); GenerateBindServiceWithBinderMethod(out, service); + GenerateBindServiceWithBinderMethodWithoutImplementation(out, service); } out->Outdent(); diff --git a/src/csharp/Grpc.Core/ServiceBinderBase.cs b/src/csharp/Grpc.Core/ServiceBinderBase.cs index d4909f4a269..79267d8f3d1 100644 --- a/src/csharp/Grpc.Core/ServiceBinderBase.cs +++ b/src/csharp/Grpc.Core/ServiceBinderBase.cs @@ -97,5 +97,19 @@ namespace Grpc.Core { throw new NotImplementedException(); } + + /// + /// Adds a method without a handler. + /// + /// The request message class. + /// The response message class. + /// The method. + public virtual void AddMethod( + Method method) + where TRequest : class + where TResponse : class + { + throw new NotImplementedException(); + } } } diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index e5be387e67e..717f3fab5ea 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -4,13 +4,13 @@ // // Original file comments: // 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. @@ -299,6 +299,17 @@ namespace Math { serviceBinder.AddMethod(__Method_Sum, serviceImpl.Sum); } + /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + public static void BindService(grpc::ServiceBinderBase serviceBinder) + { + serviceBinder.AddMethod(__Method_Div); + serviceBinder.AddMethod(__Method_DivMany); + serviceBinder.AddMethod(__Method_Fib); + serviceBinder.AddMethod(__Method_Sum); + } + } } #endregion diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs index 51956f2f234..f7002328acd 100644 --- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs +++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs @@ -4,13 +4,13 @@ // // Original file comments: // Copyright 2015 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. @@ -243,6 +243,15 @@ namespace Grpc.Health.V1 { serviceBinder.AddMethod(__Method_Watch, serviceImpl.Watch); } + /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + public static void BindService(grpc::ServiceBinderBase serviceBinder) + { + serviceBinder.AddMethod(__Method_Check); + serviceBinder.AddMethod(__Method_Watch); + } + } } #endregion diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs index 3431b5fa181..39a48f2bb38 100644 --- a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs @@ -4,13 +4,13 @@ // // Original file comments: // 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. @@ -337,6 +337,18 @@ namespace Grpc.Testing { serviceBinder.AddMethod(__Method_StreamingBothWays, serviceImpl.StreamingBothWays); } + /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + public static void BindService(grpc::ServiceBinderBase serviceBinder) + { + serviceBinder.AddMethod(__Method_UnaryCall); + serviceBinder.AddMethod(__Method_StreamingCall); + serviceBinder.AddMethod(__Method_StreamingFromClient); + serviceBinder.AddMethod(__Method_StreamingFromServer); + serviceBinder.AddMethod(__Method_StreamingBothWays); + } + } } #endregion diff --git a/src/csharp/Grpc.IntegrationTesting/Control.cs b/src/csharp/Grpc.IntegrationTesting/Control.cs index 368b86659a5..2e80dac074c 100644 --- a/src/csharp/Grpc.IntegrationTesting/Control.cs +++ b/src/csharp/Grpc.IntegrationTesting/Control.cs @@ -96,12 +96,13 @@ namespace Grpc.Testing { "GAcgAygIEhYKDnNlcnZlcl9zdWNjZXNzGAggAygIEjkKD3JlcXVlc3RfcmVz", "dWx0cxgJIAMoCzIgLmdycGMudGVzdGluZy5SZXF1ZXN0UmVzdWx0Q291bnQq", "VgoKQ2xpZW50VHlwZRIPCgtTWU5DX0NMSUVOVBAAEhAKDEFTWU5DX0NMSUVO", - "VBABEhAKDE9USEVSX0NMSUVOVBACEhMKD0NBTExCQUNLX0NMSUVOVBADKlsK", + "VBABEhAKDE9USEVSX0NMSUVOVBACEhMKD0NBTExCQUNLX0NMSUVOVBADKnAK", "ClNlcnZlclR5cGUSDwoLU1lOQ19TRVJWRVIQABIQCgxBU1lOQ19TRVJWRVIQ", "ARIYChRBU1lOQ19HRU5FUklDX1NFUlZFUhACEhAKDE9USEVSX1NFUlZFUhAD", - "KnIKB1JwY1R5cGUSCQoFVU5BUlkQABINCglTVFJFQU1JTkcQARIZChVTVFJF", - "QU1JTkdfRlJPTV9DTElFTlQQAhIZChVTVFJFQU1JTkdfRlJPTV9TRVJWRVIQ", - "AxIXChNTVFJFQU1JTkdfQk9USF9XQVlTEARiBnByb3RvMw==")); + "EhMKD0NBTExCQUNLX1NFUlZFUhAEKnIKB1JwY1R5cGUSCQoFVU5BUlkQABIN", + "CglTVFJFQU1JTkcQARIZChVTVFJFQU1JTkdfRlJPTV9DTElFTlQQAhIZChVT", + "VFJFQU1JTkdfRlJPTV9TRVJWRVIQAxIXChNTVFJFQU1JTkdfQk9USF9XQVlT", + "EARiBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedClrTypeInfo[] { @@ -152,6 +153,7 @@ namespace Grpc.Testing { /// used for some language-specific variants /// [pbr::OriginalName("OTHER_SERVER")] OtherServer = 3, + [pbr::OriginalName("CALLBACK_SERVER")] CallbackServer = 4, } public enum RpcType { diff --git a/src/csharp/Grpc.IntegrationTesting/Empty.cs b/src/csharp/Grpc.IntegrationTesting/Empty.cs index 0d4c28bf7fc..389fe433755 100644 --- a/src/csharp/Grpc.IntegrationTesting/Empty.cs +++ b/src/csharp/Grpc.IntegrationTesting/Empty.cs @@ -44,6 +44,7 @@ namespace Grpc.Testing { /// service Foo { /// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { }; /// }; + /// /// public sealed partial class Empty : pb::IMessage { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Empty()); diff --git a/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs index 7e77f8d1141..965d08d8a36 100644 --- a/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs @@ -4,13 +4,13 @@ // // Original file comments: // 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. @@ -88,6 +88,13 @@ namespace Grpc.Testing { { } + /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + public static void BindService(grpc::ServiceBinderBase serviceBinder) + { + } + } } #endregion diff --git a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs index c66a9a9161e..64db5b3ad08 100644 --- a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs @@ -4,13 +4,13 @@ // // Original file comments: // Copyright 2015-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. @@ -19,7 +19,7 @@ // // Contains the definitions for a metrics service and the type of metrics // exposed by the service. -// +// // Currently, 'Gauge' (i.e a metric that represents the measured value of // something at an instant of time) is the only metric type supported by the // service. @@ -203,6 +203,15 @@ namespace Grpc.Testing { serviceBinder.AddMethod(__Method_GetGauge, serviceImpl.GetGauge); } + /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + public static void BindService(grpc::ServiceBinderBase serviceBinder) + { + serviceBinder.AddMethod(__Method_GetAllGauges); + serviceBinder.AddMethod(__Method_GetGauge); + } + } } #endregion diff --git a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs index 954c1722723..81787892c32 100644 --- a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs @@ -4,13 +4,13 @@ // // Original file comments: // 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. @@ -152,6 +152,14 @@ namespace Grpc.Testing { serviceBinder.AddMethod(__Method_ReportScenario, serviceImpl.ReportScenario); } + /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + public static void BindService(grpc::ServiceBinderBase serviceBinder) + { + serviceBinder.AddMethod(__Method_ReportScenario); + } + } } #endregion diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index d125fd5627b..049cb65d7de 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -4,13 +4,13 @@ // // Original file comments: // Copyright 2015-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. @@ -555,6 +555,21 @@ namespace Grpc.Testing { serviceBinder.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall); } + /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + public static void BindService(grpc::ServiceBinderBase serviceBinder) + { + serviceBinder.AddMethod(__Method_EmptyCall); + serviceBinder.AddMethod(__Method_UnaryCall); + serviceBinder.AddMethod(__Method_CacheableUnaryCall); + serviceBinder.AddMethod(__Method_StreamingOutputCall); + serviceBinder.AddMethod(__Method_StreamingInputCall); + serviceBinder.AddMethod(__Method_FullDuplexCall); + serviceBinder.AddMethod(__Method_HalfDuplexCall); + serviceBinder.AddMethod(__Method_UnimplementedCall); + } + } /// /// A simple service NOT implemented at servers so clients can test for @@ -686,6 +701,14 @@ namespace Grpc.Testing { serviceBinder.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall); } + /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + public static void BindService(grpc::ServiceBinderBase serviceBinder) + { + serviceBinder.AddMethod(__Method_UnimplementedCall); + } + } /// /// A service used to control reconnect server. @@ -814,6 +837,15 @@ namespace Grpc.Testing { serviceBinder.AddMethod(__Method_Stop, serviceImpl.Stop); } + /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + public static void BindService(grpc::ServiceBinderBase serviceBinder) + { + serviceBinder.AddMethod(__Method_Start); + serviceBinder.AddMethod(__Method_Stop); + } + } } #endregion diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs index 5b22337d533..b58d71a784d 100644 --- a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs @@ -4,13 +4,13 @@ // // Original file comments: // 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. @@ -333,6 +333,17 @@ namespace Grpc.Testing { serviceBinder.AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker); } + /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + public static void BindService(grpc::ServiceBinderBase serviceBinder) + { + serviceBinder.AddMethod(__Method_RunServer); + serviceBinder.AddMethod(__Method_RunClient); + serviceBinder.AddMethod(__Method_CoreCount); + serviceBinder.AddMethod(__Method_QuitWorker); + } + } } #endregion diff --git a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs index ed55c2f584f..51ef8ace5cc 100644 --- a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs +++ b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs @@ -4,13 +4,13 @@ // // Original file comments: // 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. @@ -132,6 +132,14 @@ namespace Grpc.Reflection.V1Alpha { serviceBinder.AddMethod(__Method_ServerReflectionInfo, serviceImpl.ServerReflectionInfo); } + /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + public static void BindService(grpc::ServiceBinderBase serviceBinder) + { + serviceBinder.AddMethod(__Method_ServerReflectionInfo); + } + } } #endregion From ac61379b1eaa929bc9120401608e5c1fd5f474c4 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 28 Jan 2019 14:44:15 -0800 Subject: [PATCH 085/218] Add alignment to size calculation --- src/core/ext/filters/client_channel/subchannel.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 7f15cb416b9..60e408e8c98 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -1004,7 +1004,8 @@ grpc_subchannel_get_connected_subchannel(grpc_subchannel* c) { void* grpc_connected_subchannel_call_get_parent_data( grpc_subchannel_call* subchannel_call) { grpc_channel_stack* chanstk = subchannel_call->connection->channel_stack(); - return (char*)subchannel_call + sizeof(grpc_subchannel_call) + + return (char*)subchannel_call + + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_subchannel_call)) + chanstk->call_stack_size; } From fcbb126bafe5f791965c094d1bda881237f13924 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Mon, 28 Jan 2019 14:56:52 -0800 Subject: [PATCH 086/218] Point the hack of proto message comparison to new issue --- .../tests/reflection/_reflection_servicer_test.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 0ee40e6f2da..c0d0e7cf34e 100644 --- a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py +++ b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py @@ -50,10 +50,10 @@ def _file_descriptor_to_proto(descriptor): class ReflectionServicerTest(unittest.TestCase): - # NOTE(lidiz) Bazel + Python 3 will result in creating two different - # instance of DESCRIPTOR for each message. So, the equal comparision - # between protobuf returned by stub and manually crafted protobuf will - # always fail. + # TODO(https://github.com/grpc/grpc/issues/17844) + # Bazel + Python 3 will result in creating two different instance of + # DESCRIPTOR for each message. So, the equal comparision between protobuf + # returned by stub and manually crafted protobuf will always fail. def _assert_sequence_of_proto_equal(self, x, y): self.assertSequenceEqual( list(map(lambda x: x.SerializeToString(), x)), From 6cdbd8a49a87c33b26b9dc5d980d2479b482ee06 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 28 Jan 2019 15:02:00 -0800 Subject: [PATCH 087/218] Another alignment --- src/core/ext/filters/client_channel/subchannel.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 60e408e8c98..d77bb3c286b 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -1006,7 +1006,7 @@ void* grpc_connected_subchannel_call_get_parent_data( grpc_channel_stack* chanstk = subchannel_call->connection->channel_stack(); return (char*)subchannel_call + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_subchannel_call)) + - chanstk->call_stack_size; + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(chanstk->call_stack_size); } grpc_call_stack* grpc_subchannel_call_get_call_stack( From 5b7f0532ac6fba1366ee7ddfa83d83894650503d Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Mon, 28 Jan 2019 11:32:32 -0800 Subject: [PATCH 088/218] Properly init TLS for callback exec context --- src/core/lib/iomgr/exec_ctx.h | 6 ++++++ src/core/lib/surface/init.cc | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index c6c30d3129e..16ac14ba6c5 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -271,6 +271,12 @@ class ApplicationCallbackExecCtx { ctx->tail_ = functor; } + /** Global initialization for ApplicationCallbackExecCtx. Called by init. */ + static void GlobalInit(void) { gpr_tls_init(&callback_exec_ctx_); } + + /** Global shutdown for ApplicationCallbackExecCtx. Called by init. */ + static void GlobalShutdown(void) { gpr_tls_destroy(&callback_exec_ctx_); } + private: grpc_experimental_completion_queue_functor* head_{nullptr}; grpc_experimental_completion_queue_functor* tail_{nullptr}; diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc index 60f506ef5e2..f704a64b1c9 100644 --- a/src/core/lib/surface/init.cc +++ b/src/core/lib/surface/init.cc @@ -130,6 +130,7 @@ void grpc_init(void) { grpc_channel_init_init(); grpc_core::channelz::ChannelzRegistry::Init(); grpc_security_pre_init(); + grpc_core::ApplicationCallbackExecCtx::GlobalInit(); grpc_core::ExecCtx::GlobalInit(); grpc_iomgr_init(); gpr_timers_global_init(); @@ -183,6 +184,7 @@ void grpc_shutdown(void) { grpc_core::Fork::GlobalShutdown(); } grpc_core::ExecCtx::GlobalShutdown(); + grpc_core::ApplicationCallbackExecCtx::GlobalShutdown(); } gpr_mu_unlock(&g_init_mu); } From 3a2cfe50ec768dd83eefd5e29da567c1c98db298 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 28 Jan 2019 16:18:49 -0800 Subject: [PATCH 089/218] Rever copyright changes --- include/grpcpp/impl/codegen/call_op_set.h | 2 +- include/grpcpp/impl/codegen/core_codegen.h | 2 +- src/cpp/common/completion_queue_cc.cc | 2 +- src/cpp/common/core_codegen.cc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index 03a32b9815d..4ca87a99fca 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -1,6 +1,6 @@ /* * - * Copyright 2019 gRPC authors. + * 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. diff --git a/include/grpcpp/impl/codegen/core_codegen.h b/include/grpcpp/impl/codegen/core_codegen.h index 6230555e1a7..b7ddb0c791c 100644 --- a/include/grpcpp/impl/codegen/core_codegen.h +++ b/include/grpcpp/impl/codegen/core_codegen.h @@ -1,6 +1,6 @@ /* * - * Copyright 2019 gRPC authors. + * 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. diff --git a/src/cpp/common/completion_queue_cc.cc b/src/cpp/common/completion_queue_cc.cc index 3df45128ecb..4bb3bcbd8b6 100644 --- a/src/cpp/common/completion_queue_cc.cc +++ b/src/cpp/common/completion_queue_cc.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 gRPC authors. + * 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. diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc index 986c3df7736..9430dcc9881 100644 --- a/src/cpp/common/core_codegen.cc +++ b/src/cpp/common/core_codegen.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2019 gRPC authors. + * 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. From 5e2e61b6e57e6ae1682fe461f8cbaba5603e9ae4 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 28 Jan 2019 16:37:02 -0800 Subject: [PATCH 090/218] Note on conditions of usage --- include/grpcpp/impl/codegen/interceptor_common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index 6c4847509e0..8ed84230911 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -219,6 +219,7 @@ class InterceptorBatchMethodsImpl // Alternatively, RunInterceptors(std::function f) can be used. void SetCallOpSetInterface(CallOpSetInterface* ops) { ops_ = ops; } + // SetCall should have been called before this. // Returns true if the interceptors list is empty bool InterceptorsListEmpty() { auto* client_rpc_info = call_->client_rpc_info(); From a7899511817c18b95e8449ed8ebbe3ccb4ec07e0 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 28 Jan 2019 19:22:57 -0800 Subject: [PATCH 091/218] Revert "Revert "Collect timestamps for all data written for a stream instead of just data frames"" --- src/core/ext/transport/chttp2/transport/writing.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc index 265d3365d3c..cf77ddc8278 100644 --- a/src/core/ext/transport/chttp2/transport/writing.cc +++ b/src/core/ext/transport/chttp2/transport/writing.cc @@ -363,7 +363,6 @@ class DataSendContext { grpc_chttp2_encode_data(s_->id, &s_->compressed_data_buffer, send_bytes, is_last_frame_, &s_->stats.outgoing, &t_->outbuf); s_->flow_control->SentData(send_bytes); - s_->byte_counter += send_bytes; if (s_->compressed_data_buffer.length == 0) { s_->sending_bytes += s_->uncompressed_data_size; } @@ -498,9 +497,6 @@ class StreamWriteContext { data_send_context.CompressMoreBytes(); } } - if (s_->traced && grpc_endpoint_can_track_err(t_->ep)) { - grpc_core::ContextList::Append(&t_->cl, s_); - } write_context_->ResetPingClock(); if (data_send_context.is_last_frame()) { SentLastFrame(); @@ -610,11 +606,18 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write( (according to available window sizes) and add to the output buffer */ while (grpc_chttp2_stream* s = ctx.NextStream()) { StreamWriteContext stream_ctx(&ctx, s); + size_t orig_len = t->outbuf.length; stream_ctx.FlushInitialMetadata(); stream_ctx.FlushWindowUpdates(); stream_ctx.FlushData(); stream_ctx.FlushTrailingMetadata(); - + if (t->outbuf.length > orig_len) { + /* Add this stream to the list of the contexts to be traced at TCP */ + s->byte_counter += t->outbuf.length - orig_len; + if (s->traced && grpc_endpoint_can_track_err(t->ep)) { + grpc_core::ContextList::Append(&t->cl, s); + } + } if (stream_ctx.stream_became_writable()) { if (!grpc_chttp2_list_add_writing_stream(t, s)) { /* already in writing list: drop ref */ From b099ca217e95234781d70c873af6696cd2fe6ef0 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Mon, 28 Jan 2019 23:09:49 -0800 Subject: [PATCH 092/218] Revert "Memory leak test for PHP unit tests" --- src/php/bin/run_tests.sh | 8 - .../tests/MemoryLeakTest/MemoryLeakTest.php | 2310 ----------------- src/php/tests/unit_tests/CallTest.php | 10 - .../tools/dockerfile/php_valgrind.include | 7 - .../test/php7_jessie_x64/Dockerfile.template | 1 - .../test/php_jessie_x64/Dockerfile.template | 1 - .../test/php7_jessie_x64/Dockerfile | 8 - .../dockerfile/test/php_jessie_x64/Dockerfile | 8 - 8 files changed, 2353 deletions(-) delete mode 100644 src/php/tests/MemoryLeakTest/MemoryLeakTest.php delete mode 100644 templates/tools/dockerfile/php_valgrind.include diff --git a/src/php/bin/run_tests.sh b/src/php/bin/run_tests.sh index 861ce433c4e..295bcb2430c 100755 --- a/src/php/bin/run_tests.sh +++ b/src/php/bin/run_tests.sh @@ -22,17 +22,9 @@ cd src/php/bin source ./determine_extension_dir.sh # in some jenkins macos machine, somehow the PHP build script can't find libgrpc.dylib export DYLD_LIBRARY_PATH=$root/libs/$CONFIG - php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \ --exclude-group persistent_list_bound_tests ../tests/unit_tests php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \ ../tests/unit_tests/PersistentChannelTests -export ZEND_DONT_UNLOAD_MODULES=1 -export USE_ZEND_ALLOC=0 -# Detect whether valgrind is executable -if [ -x "$(command -v valgrind)" ]; then - valgrind --error-exitcode=10 --leak-check=yes php $extension_dir -d max_execution_time=300 \ - ../tests/MemoryLeakTest/MemoryLeakTest.php -fi diff --git a/src/php/tests/MemoryLeakTest/MemoryLeakTest.php b/src/php/tests/MemoryLeakTest/MemoryLeakTest.php deleted file mode 100644 index 6b5fcb1ec78..00000000000 --- a/src/php/tests/MemoryLeakTest/MemoryLeakTest.php +++ /dev/null @@ -1,2310 +0,0 @@ - "v1"]; -} - -function assertConnecting($state) -{ - assert(($state == GRPC\CHANNEL_CONNECTING || $state == GRPC\CHANNEL_TRANSIENT_FAILURE) == true); -} - -function waitUntilNotIdle($channel) { - for ($i = 0; $i < 10; $i++) { - $now = Grpc\Timeval::now(); - $deadline = $now->add(new Grpc\Timeval(10000)); - if ($channel->watchConnectivityState(GRPC\CHANNEL_IDLE, - $deadline)) { - return true; - } - } - assert(true == false); -} - -// Set up -$channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); - -// Test InsecureCredentials -assert('Grpc\Channel' == get_class($channel)); - -// Test ConnectivityState -$state = $channel->getConnectivityState(); -assert(0 == $state); - -// Test GetConnectivityStateWithInt -$state = $channel->getConnectivityState(123); -assert(0 == $state); - -// Test GetConnectivityStateWithString -$state = $channel->getConnectivityState('hello'); -assert(0 == $state); - -// Test GetConnectivityStateWithBool -$state = $channel->getConnectivityState(true); -assert(0 == $state); - -$channel->close(); - -// Test GetTarget -$channel = new Grpc\Channel('localhost:8888', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); -$target = $channel->getTarget(); -assert(is_string($target) == true); -$channel->close(); - -// Test WatchConnectivityState -$channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); -$now = Grpc\Timeval::now(); -$deadline = $now->add(new Grpc\Timeval(100*1000)); - -$state = $channel->watchConnectivityState(1, $deadline); -assert($state == true); - -unset($now); -unset($deadline); - -$channel->close(); - -// Test InvalidConstructorWithNull -try { - $channel = new Grpc\Channel(); - assert($channel == NULL); -} -catch (\Exception $e) { -} - -// Test InvalidConstructorWith -try { - $channel = new Grpc\Channel('localhost:0', 'invalid'); - assert($channel == NULL); -} -catch (\Exception $e) { -} - -// Test InvalideCredentials -try { - $channel = new Grpc\Channel('localhost:0', ['credentials' => new Grpc\Timeval(100)]); -} -catch (\Exception $e) { -} - -// Test InvalidOptionsArrray -try { - $channel = new Grpc\Channel('localhost:0', ['abc' => []]); -} -catch (\Exception $e) { -} - -// Test InvalidGetConnectivityStateWithArray -$channel = new Grpc\Channel('localhost:0', ['credentials' => Grpc\ChannelCredentials::createInsecure()]); -try { - $channel->getConnectivityState([]); -} -catch (\Exception $e) { -} - -// Test InvalidWatchConnectivityState -try { - $channel->watchConnectivityState([]); -} -catch (\Exception $e) { -} - -// Test InvalidWatchConnectivityState2 -try { - $channel->watchConnectivityState(1, 'hi'); -} -catch (\Exception $e) { -} - -$channel->close(); - -// Test PersistentChannelSameHost -$channel1 = new Grpc\Channel('localhost:1', []); -$channel2 = new Grpc\Channel('localhost:1', []); -$state = $channel1->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -$state = $channel1->getConnectivityState(true); -waitUntilNotIdle($channel1); - -$state = $channel1->getConnectivityState(); -assertConnecting($state); -$state = $channel2->getConnectivityState(); -assertConnecting($state); - -$channel1->close(); -$channel2->close(); - -// Test PersistentChannelDifferentHost -$channel1 = new Grpc\Channel('localhost:1', ["grpc_target_persist_bound" => 3,]); -$channel2 = new Grpc\Channel('localhost:2', []); -$state = $channel1->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -$state = $channel1->getConnectivityState(true); -waitUntilNotIdle($channel1); - -$state = $channel1->getConnectivityState(); -assertConnecting($state); -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -$channel1->close(); -$channel2->close(); - -// Test PersistentChannelSameArgs -$channel1 = new Grpc\Channel('localhost:1', [ - "grpc_target_persist_bound" => 3, - "abc" => "def", - ]); -$channel2 = new Grpc\Channel('localhost:1', ["abc" => "def"]); -$state = $channel1->getConnectivityState(true); -waitUntilNotIdle($channel1); - -$state = $channel1->getConnectivityState(); -assertConnecting($state); -$state = $channel2->getConnectivityState(); -assertConnecting($state); - -$channel1->close(); -$channel2->close(); - -// Test PersistentChannelDifferentArgs -$channel1 = new Grpc\Channel('localhost:1', []); -$channel2 = new Grpc\Channel('localhost:1', ["abc" => "def"]); -$state = $channel1->getConnectivityState(true); -waitUntilNotIdle($channel1); - -$state = $channel1->getConnectivityState(); -assertConnecting($state); -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -$channel1->close(); -$channel2->close(); - -// Test PersistentChannelSameChannelCredentials -$creds1 = Grpc\ChannelCredentials::createSsl(); -$creds2 = Grpc\ChannelCredentials::createSsl(); - -$channel1 = new Grpc\Channel('localhost:1', - ["credentials" => $creds1, - "grpc_target_persist_bound" => 3, - ]); -$channel2 = new Grpc\Channel('localhost:1', - ["credentials" => $creds2]); - -$state = $channel1->getConnectivityState(true); -print "state: ".$state."......................"; -waitUntilNotIdle($channel1); - -$state = $channel1->getConnectivityState(); -assertConnecting($state); -$state = $channel2->getConnectivityState(); -assertConnecting($state); - -$channel1->close(); -$channel2->close(); - -// Test PersistentChannelDifferentChannelCredentials -$creds1 = Grpc\ChannelCredentials::createSsl(); -$creds2 = Grpc\ChannelCredentials::createSsl( - file_get_contents(dirname(__FILE__).'/../data/ca.pem')); - -$channel1 = new Grpc\Channel('localhost:1', - ["credentials" => $creds1, - "grpc_target_persist_bound" => 3, - ]); -$channel2 = new Grpc\Channel('localhost:1', - ["credentials" => $creds2]); - -$state = $channel1->getConnectivityState(true); -waitUntilNotIdle($channel1); - -$state = $channel1->getConnectivityState(); -assertConnecting($state); -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -$channel1->close(); -$channel2->close(); - - -// Test PersistentChannelSameChannelCredentialsRootCerts -$creds1 = Grpc\ChannelCredentials::createSsl( - file_get_contents(dirname(__FILE__).'/../data/ca.pem')); -$creds2 = Grpc\ChannelCredentials::createSsl( - file_get_contents(dirname(__FILE__).'/../data/ca.pem')); - -$channel1 = new Grpc\Channel('localhost:1', - ["credentials" => $creds1, - "grpc_target_persist_bound" => 3, - ]); -$channel2 = new Grpc\Channel('localhost:1', - ["credentials" => $creds2]); - -$state = $channel1->getConnectivityState(true); -waitUntilNotIdle($channel1); - -$state = $channel1->getConnectivityState(); -assertConnecting($state); -$state = $channel2->getConnectivityState(); -assertConnecting($state); - -$channel1->close(); -$channel2->close(); - -// Test PersistentChannelDifferentSecureChannelCredentials -$creds1 = Grpc\ChannelCredentials::createSsl(); -$creds2 = Grpc\ChannelCredentials::createInsecure(); - -$channel1 = new Grpc\Channel('localhost:1', - ["credentials" => $creds1, - "grpc_target_persist_bound" => 3, - ]); -$channel2 = new Grpc\Channel('localhost:1', - ["credentials" => $creds2]); - -$state = $channel1->getConnectivityState(true); -waitUntilNotIdle($channel1); - -$state = $channel1->getConnectivityState(); -assertConnecting($state); -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -$channel1->close(); -$channel2->close(); - -// Test PersistentChannelSharedChannelClose1 -$channel1 = new Grpc\Channel('localhost:1', [ - "grpc_target_persist_bound" => 3, -]); -$channel2 = new Grpc\Channel('localhost:1', []); - -$channel1->close(); - -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); -$channel2->close(); - -// Test PersistentChannelSharedChannelClose2 -$channel1 = new Grpc\Channel('localhost:1', [ - "grpc_target_persist_bound" => 3, -]); -$channel2 = new Grpc\Channel('localhost:1', []); - -$channel1->close(); - -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -try{ - $state = $channel1->getConnectivityState(); -} -catch(\Exception $e){ -} - -$channel2->close(); - -//Test PersistentChannelCreateAfterClose -$channel1 = new Grpc\Channel('localhost:1', [ - "grpc_target_persist_bound" => 3, -]); - -$channel1->close(); - -$channel2 = new Grpc\Channel('localhost:1', []); -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -$channel2->close(); - -//Test PersistentChannelSharedMoreThanTwo -$channel1 = new Grpc\Channel('localhost:1', [ - "grpc_target_persist_bound" => 3, -]); -$channel2 = new Grpc\Channel('localhost:1', []); -$channel3 = new Grpc\Channel('localhost:1', []); - -$state = $channel1->getConnectivityState(true); -waitUntilNotIdle($channel1); - -$state = $channel1->getConnectivityState(); -assertConnecting($state); -$state = $channel2->getConnectivityState(); -assertConnecting($state); -$state = $channel3->getConnectivityState(); -assertConnecting($state); - -$channel1->close(); - -//Test PersistentChannelWithCallCredentials -$creds = Grpc\ChannelCredentials::createSsl(); -$callCreds = Grpc\CallCredentials::createFromPlugin( - 'callbackFunc'); -$credsWithCallCreds = Grpc\ChannelCredentials::createComposite( - $creds, $callCreds); - -$channel1 = new Grpc\Channel('localhost:1', - ["credentials" => - $credsWithCallCreds, - "grpc_target_persist_bound" => 3, - ]); -$channel2 = new Grpc\Channel('localhost:1', - ["credentials" => - $credsWithCallCreds]); - -$state = $channel1->getConnectivityState(true); -waitUntilNotIdle($channel1); - -$state = $channel1->getConnectivityState(); -assertConnecting($state); -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -$channel1->close(); -$channel2->close(); - -// Test PersistentChannelWithDifferentCallCredentials -$callCreds1 = Grpc\CallCredentials::createFromPlugin('callbackFunc'); -$callCreds2 = Grpc\CallCredentials::createFromPlugin('callbackFunc2'); - -$creds1 = Grpc\ChannelCredentials::createSsl(); -$creds2 = Grpc\ChannelCredentials::createComposite( - $creds1, $callCreds1); -$creds3 = Grpc\ChannelCredentials::createComposite( - $creds1, $callCreds2); - -$channel1 = new Grpc\Channel('localhost:1', - ["credentials" => $creds1, - "grpc_target_persist_bound" => 3, - ]); -$channel2 = new Grpc\Channel('localhost:1', - ["credentials" => $creds2]); -$channel3 = new Grpc\Channel('localhost:1', - ["credentials" => $creds3]); - -$state = $channel1->getConnectivityState(true); -waitUntilNotIdle($channel1); - -$state = $channel1->getConnectivityState(); -assertConnecting($state); -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); -$state = $channel3->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -$channel1->close(); -$channel2->close(); -$channel3->close(); - -// Test PersistentChannelForceNew -$channel1 = new Grpc\Channel('localhost:1', [ - "grpc_target_persist_bound" => 2, -]); -$channel2 = new Grpc\Channel('localhost:1', - ["force_new" => true]); - -$state = $channel1->getConnectivityState(true); -waitUntilNotIdle($channel1); - -$state = $channel1->getConnectivityState(); -assertConnecting($state); -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -$channel1->close(); -$channel2->close(); - -// Test PersistentChannelForceNewOldChannelIdle1 -$channel1 = new Grpc\Channel('localhost:1', [ - "grpc_target_persist_bound" => 2, -]); -$channel2 = new Grpc\Channel('localhost:1', - ["force_new" => true]); -$channel3 = new Grpc\Channel('localhost:1', []); - -$state = $channel2->getConnectivityState(true); -waitUntilNotIdle($channel2); -$state = $channel1->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); -$state = $channel2->getConnectivityState(); -assertConnecting($state); -$state = $channel3->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -$channel1->close(); -$channel2->close(); - -// Test PersistentChannelForceNewOldChannelIdle2 -$channel1 = new Grpc\Channel('localhost:1', [ - "grpc_target_persist_bound" => 2, -]); -$channel2 = new Grpc\Channel('localhost:1', []); - -$state = $channel1->getConnectivityState(true); -waitUntilNotIdle($channel2); -$state = $channel1->getConnectivityState(); -assertConnecting($state); -$state = $channel2->getConnectivityState(); -assertConnecting($state); - -$channel1->close(); -$channel2->close(); - -// Test PersistentChannelForceNewOldChannelClose1 -$channel1 = new Grpc\Channel('localhost:1', [ - "grpc_target_persist_bound" => 2, -]); -$channel2 = new Grpc\Channel('localhost:1', - ["force_new" => true]); -$channel3 = new Grpc\Channel('localhost:1', []); - -$channel1->close(); - -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); -$state = $channel3->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -$channel2->close(); -$channel3->close(); - -// Test PersistentChannelForceNewOldChannelClose2 -$channel1 = new Grpc\Channel('localhost:1', [ - "grpc_target_persist_bound" => 2, -]); -$channel2 = new Grpc\Channel('localhost:1', - ["force_new" => true]); -// channel3 shares with channel1 -$channel3 = new Grpc\Channel('localhost:1', []); - -$channel1->close(); - -$state = $channel2->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -// channel3 is still usable -$state = $channel3->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -// channel 1 is closed -try{ - $channel1->getConnectivityState(); -} -catch(\Exception $e){ -} - -$channel2->close(); -$channel3->close(); - -// Test PersistentChannelForceNewNewChannelClose -$channel1 = new Grpc\Channel('localhost:1', [ - "grpc_target_persist_bound" => 2, -]); -$channel2 = new Grpc\Channel('localhost:1', - ["force_new" => true]); -$channel3 = new Grpc\Channel('localhost:1', []); - -$channel2->close(); - -$state = $channel1->getConnectivityState(); -assert(GRPC\CHANNEL_IDLE == $state); - -// can still connect on channel1 -$state = $channel1->getConnectivityState(true); -waitUntilNotIdle($channel1); - -$state = $channel1->getConnectivityState(); -assertConnecting($state); - -$channel1->close(); - -//============== Call Test ==================== -$server = new Grpc\Server([]); -$port = $server->addHttp2Port('0.0.0.0:53000'); -$channel = new Grpc\Channel('localhost:'.$port, []); -$call = new Grpc\Call($channel, - '/foo', - Grpc\Timeval::infFuture()); - -// Test AddEmptyMetadata -$batch = [ - Grpc\OP_SEND_INITIAL_METADATA => [], -]; -$result = $call->startBatch($batch); -assert($result->send_metadata == true); - -// Test testAddSingleMetadata -$batch = [ - Grpc\OP_SEND_INITIAL_METADATA => ['key' => ['value']], -]; -$call = new Grpc\Call($channel, - '/foo', - Grpc\Timeval::infFuture()); -$result = $call->startBatch($batch); -assert($result->send_metadata == true); - -// Test AddMultiValue -$batch = [ - Grpc\OP_SEND_INITIAL_METADATA => ['key' => ['value1', 'value2']], -]; -$call = new Grpc\Call($channel, - '/foo', - Grpc\Timeval::infFuture()); -$result = $call->startBatch($batch); -assert($result->send_metadata == true); - -// Test AddSingleAndMultiValueMetadata -$batch = [ - Grpc\OP_SEND_INITIAL_METADATA => ['key1' => ['value1'], - 'key2' => ['value2', - 'value3', ], ], -]; -$call = new Grpc\Call($channel, - '/foo', - Grpc\Timeval::infFuture()); -$result = $call->startBatch($batch); -assert($result->send_metadata == true); - -// Test AddMultiAndMultiValueMetadata -$batch = [ - Grpc\OP_SEND_INITIAL_METADATA => ['key1' => ['value1'], - 'key2' => ['value2', - 'value3', ], ], -]; -$call = new Grpc\Call($channel, - '/foo', - Grpc\Timeval::infFuture()); -$result = $call->startBatch($batch); -assert($result->send_metadata == true); - -// Test GetPeer -assert(is_string($call->getPeer()) == true); - -// Test Cancel -assert($call->cancel == NULL); - -// Test InvalidStartBatchKey -$batch = [ - 'invalid' => ['key1' => 'value1'], -]; -try{ - $result = $call->startBatch($batch); -} -catch(\Exception $e){ -} - -// Test InvalideMetadataStrKey -$batch = [ - Grpc\OP_SEND_INITIAL_METADATA => ['Key' => ['value1', 'value2']], -]; -$call = new Grpc\Call($channel, - '/foo', - Grpc\Timeval::infFuture()); -try{ - $result = $call->startBatch($batch); -} -catch(\Exception $e){ -} - -// Test InvalidMetadataIntKey -$batch = [ - Grpc\OP_SEND_INITIAL_METADATA => [1 => ['value1', 'value2']], -]; -$call = new Grpc\Call($channel, - '/foo', - Grpc\Timeval::infFuture()); -try{ - $result = $call->startBatch($batch); -} -catch(\Exception $e){ -} - -// Test InvalidMetadataInnerValue -$batch = [ - Grpc\OP_SEND_INITIAL_METADATA => ['key1' => 'value1'], -]; -$call = new Grpc\Call($channel, - '/foo', - Grpc\Timeval::infFuture()); -try{ - $result = $call->startBatch($batch); -} -catch(\Exception $e){ -} - -// Test InvalidConstuctor -try { - $call = new Grpc\Call(); -} catch (\Exception $e) {} - -// Test InvalidConstuctor2 -try { - $call = new Grpc\Call('hi', 'hi', 'hi'); -} catch (\Exception $e) {} - -// Test InvalidSetCredentials -try{ - $call->setCredentials('hi'); -} -catch(\Exception $e){ -} - -// Test InvalidSetCredentials2 -try { - $call->setCredentials([]); -} catch (\Exception $e) {} - - -//============== CallCredentials Test 2 ==================== -// Set Up -$credentials = Grpc\ChannelCredentials::createSsl( - file_get_contents(dirname(__FILE__).'/../data/ca.pem')); -$server_credentials = Grpc\ServerCredentials::createSsl( - null, - file_get_contents(dirname(__FILE__).'/../data/server1.key'), - file_get_contents(dirname(__FILE__).'/../data/server1.pem')); -$server = new Grpc\Server(); -$port = $server->addSecureHttp2Port('0.0.0.0:0', - $server_credentials); -$server->start(); -$host_override = 'foo.test.google.fr'; -$channel = new Grpc\Channel( - 'localhost:'.$port, - [ - 'grpc.ssl_target_name_override' => $host_override, - 'grpc.default_authority' => $host_override, - 'credentials' => $credentials, - ] -); -function callCredscallbackFunc($context) -{ - is_string($context->service_url); - is_string($context->method_name); - return ['k1' => ['v1'], 'k2' => ['v2']]; -} - -// Test CreateFromPlugin -$deadline = Grpc\Timeval::infFuture(); -$status_text = 'xyz'; -$call = new Grpc\Call($channel, - '/abc/dummy_method', - $deadline, - $host_override); - $call_credentials = Grpc\CallCredentials::createFromPlugin( - 'callCredscallbackFunc'); -$call->setCredentials($call_credentials); - $event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, -]); -assert($event->send_metadata == true); -assert($event->send_close == true); - -$event = $server->requestCall(); -assert(is_array($event->metadata) == true); - -$metadata = $event->metadata; -assert(array_key_exists('k1', $metadata) == true); -assert(array_key_exists('k2', $metadata) == true); -assert($metadata['k1'] == ['v1']); -assert($metadata['k2'] == ['v2']); -assert('/abc/dummy_method' == $event->method); - -$server_call = $event->call; -$event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => Grpc\STATUS_OK, - 'details' => $status_text, - ], - Grpc\OP_RECV_CLOSE_ON_SERVER => true, -]); -assert($event->send_metadata == true); -assert($event->send_status == true); -assert($event->cancelled == false); - -$event = $call->startBatch([ - Grpc\OP_RECV_INITIAL_METADATA => true, - Grpc\OP_RECV_STATUS_ON_CLIENT => true, -]); -assert([] == $event->metadata); - -$status = $event->status; -assert([] == $status->metadata); -assert(Grpc\STATUS_OK == $status->code); -assert($status_text == $status->details); - -unset($call); -unset($server_call); - -function invalidKeyCallbackFunc($context) -{ - is_string($context->service_url); - is_string($context->method_name); - return ['K1' => ['v1']]; -} - -// Test CallbackWithInvalidKey -$deadline = Grpc\Timeval::infFuture(); -$status_text = 'xyz'; -$call = new Grpc\Call($channel, - '/abc/dummy_method', - $deadline, - $host_override); - $call_credentials = Grpc\CallCredentials::createFromPlugin( - 'invalidKeyCallbackFunc'); -$call->setCredentials($call_credentials); -$event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_RECV_STATUS_ON_CLIENT => true, -]); -assert($event->send_metadata == true); -assert($event->send_close == true); -assert(($event->status->code == Grpc\STATUS_UNAVAILABLE) == true); - -function invalidReturnCallbackFunc($context) -{ - is_string($context->service_url); - is_string($context->method_name); - return 'a string'; -} - -// Test CallbackWithInvalidReturnValue -$deadline = Grpc\Timeval::infFuture(); -$status_text = 'xyz'; -$call = new Grpc\Call($channel, - '/abc/dummy_method', - $deadline, - $host_override); - $call_credentials = Grpc\CallCredentials::createFromPlugin( - 'invalidReturnCallbackFunc'); -$call->setCredentials($call_credentials); - $event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_RECV_STATUS_ON_CLIENT => true, -]); - -assert($event->send_metadata == true); -assert($event->send_close == true); -assert(($event->status->code == Grpc\STATUS_UNAVAILABLE) == true); - -unset($channel); -unset($server); - -//============== CallCredentials Test ==================== -//Set Up -$credentials = Grpc\ChannelCredentials::createSsl( - file_get_contents(dirname(__FILE__).'/../data/ca.pem')); -$call_credentials = Grpc\CallCredentials::createFromPlugin('callbackFunc'); -$credentials = Grpc\ChannelCredentials::createComposite( - $credentials, - $call_credentials -); -$server_credentials = Grpc\ServerCredentials::createSsl( - null, - file_get_contents(dirname(__FILE__).'/../data/server1.key'), - file_get_contents(dirname(__FILE__).'/../data/server1.pem')); -$server = new Grpc\Server(); -$port = $server->addSecureHttp2Port('0.0.0.0:0', - $server_credentials); -$server->start(); -$host_override = 'foo.test.google.fr'; -$channel = new Grpc\Channel( - 'localhost:'.$port, - [ - 'grpc.ssl_target_name_override' => $host_override, - 'grpc.default_authority' => $host_override, - 'credentials' => $credentials, - ] -); - -// Test CreateComposite -$call_credentials2 = Grpc\CallCredentials::createFromPlugin('callbackFunc'); -$call_credentials3 = Grpc\CallCredentials::createComposite( - $call_credentials, - $call_credentials2 -); -assert('Grpc\CallCredentials' == get_class($call_credentials3)); - -// Test CreateFromPluginInvalidParam -try{ - $call_credentials = Grpc\CallCredentials::createFromPlugin( - 'callbackFunc' - ); -} -catch(\Exception $e){} - -// Test CreateCompositeInvalidParam -try{ - $call_credentials3 = Grpc\CallCredentials::createComposite( - $call_credentials, - $credentials - ); -} -catch(\Exception $e){} - -unset($channel); -unset($server); - - -//============== EndToEnd Test ==================== -// Set Up -$server = new Grpc\Server([]); -$port = $server->addHttp2Port('0.0.0.0:0'); -$channel = new Grpc\Channel('localhost:'.$port, []); -$server->start(); - -// Test SimpleRequestBody -$deadline = Grpc\Timeval::infFuture(); -$status_text = 'xyz'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline); -$event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, -]); -assert($event->send_metadata == true); -assert($event->send_close == true); - -$event = $server->requestCall(); -assert('dummy_method' == $event->method); - -$server_call = $event->call; -$event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => Grpc\STATUS_OK, - 'details' => $status_text, - ], - Grpc\OP_RECV_CLOSE_ON_SERVER => true, -]); -assert($event->send_metadata == true); -assert($event->send_status == true); -assert($event->cancelled == false) -; - $event = $call->startBatch([ - Grpc\OP_RECV_INITIAL_METADATA => true, - Grpc\OP_RECV_STATUS_ON_CLIENT => true, -]); -$status = $event->status; -assert([] == $status->metadata); -assert(Grpc\STATUS_OK == $status->code); -assert($status_text == $status->details); - -unset($call); -unset($server_call); - -// Test MessageWriteFlags -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'message_write_flags_test'; -$status_text = 'xyz'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline); -$event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_MESSAGE => ['message' => $req_text, - 'flags' => Grpc\WRITE_NO_COMPRESS, ], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, -]); -assert($event->send_metadata == true); -assert($event->send_close == true); - -$event = $server->requestCall(); -assert('dummy_method' == $event->method); - -$server_call = $event->call; -$event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => Grpc\STATUS_OK, - 'details' => $status_text, - ], -]); -$event = $call->startBatch([ - Grpc\OP_RECV_INITIAL_METADATA => true, - Grpc\OP_RECV_STATUS_ON_CLIENT => true, -]); -$status = $event->status; - -assert([] == $status->metadata); -assert(Grpc\STATUS_OK == $status->code); -assert($status_text == $status->details); - -unset($call); -unset($server_call); - -// Test ClientServerFullRequestResponse -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'client_server_full_request_response'; -$reply_text = 'reply:client_server_full_request_response'; -$status_text = 'status:client_server_full_response_text'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline); - $event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_SEND_MESSAGE => ['message' => $req_text], -]); -assert($event->send_metadata == true); -assert($event->send_close == true); -assert($event->send_message == true); - -$event = $server->requestCall(); -assert('dummy_method' == $event->method); -$server_call = $event->call; - -$event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => Grpc\STATUS_OK, - 'details' => $status_text, - ], - Grpc\OP_RECV_MESSAGE => true, - Grpc\OP_RECV_CLOSE_ON_SERVER => true, -]); -assert($event->send_metadata == true); -assert($event->send_status == true); -assert($event->send_message == true); -assert($event->cancelled == false); -assert($req_text == $event->message); - -$event = $call->startBatch([ - Grpc\OP_RECV_INITIAL_METADATA => true, - Grpc\OP_RECV_MESSAGE => true, - Grpc\OP_RECV_STATUS_ON_CLIENT => true, -]); -assert([] == $event->metadata); -assert($reply_text == $event->message); -$status = $event->status; -assert([] == $status->metadata); -assert(Grpc\STATUS_OK == $status->code); -assert($status_text == $status->details); - -unset($call); -unset($server_call); - -// Test InvalidClientMessageArray -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'client_server_full_request_response'; -$reply_text = 'reply:client_server_full_request_response'; -$status_text = 'status:client_server_full_response_text'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline); -try { - $event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_SEND_MESSAGE => 'invalid', - ]); -} catch (\Exception $e) {} - -// Test InvalidClientMessageString -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'client_server_full_request_response'; -$reply_text = 'reply:client_server_full_request_response'; -$status_text = 'status:client_server_full_response_text'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline); -try{ - $event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_SEND_MESSAGE => ['message' => 0], - ]); -} catch (\Exception $e) {} - -// Test InvalidClientMessageFlags -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'client_server_full_request_response'; -$reply_text = 'reply:client_server_full_request_response'; -$status_text = 'status:client_server_full_response_text'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline); -try{ - $event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_SEND_MESSAGE => ['message' => 'abc', - 'flags' => 'invalid', - ], - ]); -} catch (\Exception $e) {} - -// Test InvalidServerStatusMetadata -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'client_server_full_request_response'; -$reply_text = 'reply:client_server_full_request_response'; -$status_text = 'status:client_server_full_response_text'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline); -$event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_SEND_MESSAGE => ['message' => $req_text], -]); -assert($event->send_metadata == true); -assert($event->send_close == true); -assert($event->send_message == true); - -$event = $server->requestCall(); -assert('dummy_method' == $event->method); -$server_call = $event->call; -try { - $event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => 'invalid', - 'code' => Grpc\STATUS_OK, - 'details' => $status_text, - ], - Grpc\OP_RECV_MESSAGE => true, - Grpc\OP_RECV_CLOSE_ON_SERVER => true, - ]); -} catch (\Exception $e) {} - -// Test InvalidServerStatusCode -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'client_server_full_request_response'; -$reply_text = 'reply:client_server_full_request_response'; -$status_text = 'status:client_server_full_response_text'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline); -$event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_SEND_MESSAGE => ['message' => $req_text], -]); -assert($event->send_metadata == true); -assert($event->send_close == true); -assert($event->send_message == true); - -$event = $server->requestCall(); -assert('dummy_method' == $event->method); -$server_call = $event->call; -try { - $event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => 'invalid', - 'details' => $status_text, - ], - Grpc\OP_RECV_MESSAGE => true, - Grpc\OP_RECV_CLOSE_ON_SERVER => true, - ]); -} catch (\Exception $e) {} - -// Test MissingServerStatusCode -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'client_server_full_request_response'; -$reply_text = 'reply:client_server_full_request_response'; -$status_text = 'status:client_server_full_response_text'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline); -$event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_SEND_MESSAGE => ['message' => $req_text], -]); -$event = $server->requestCall(); -$server_call = $event->call; -try { - $event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'details' => $status_text, - ], - Grpc\OP_RECV_MESSAGE => true, - Grpc\OP_RECV_CLOSE_ON_SERVER => true, - ]); -} catch (\Exception $e) {} - -// Test InvalidServerStatusDetails -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'client_server_full_request_response'; -$reply_text = 'reply:client_server_full_request_response'; -$status_text = 'status:client_server_full_response_text'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline); -$event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_SEND_MESSAGE => ['message' => $req_text], -]); -$event = $server->requestCall(); -$server_call = $event->call; -try { - $event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => Grpc\STATUS_OK, - 'details' => 0, - ], - Grpc\OP_RECV_MESSAGE => true, - Grpc\OP_RECV_CLOSE_ON_SERVER => true, - ]); -} catch (\Exception $e) {} - -// Test MissingServerStatusDetails -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'client_server_full_request_response'; -$reply_text = 'reply:client_server_full_request_response'; -$status_text = 'status:client_server_full_response_text'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline); -$event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_SEND_MESSAGE => ['message' => $req_text], -]); -$event = $server->requestCall(); -$server_call = $event->call; -try { - $event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => Grpc\STATUS_OK, - ], - Grpc\OP_RECV_MESSAGE => true, - Grpc\OP_RECV_CLOSE_ON_SERVER => true, - ]); -} catch (\Exception $e) {} - -// Test InvalidStartBatchKey -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'client_server_full_request_response'; -$reply_text = 'reply:client_server_full_request_response'; -$status_text = 'status:client_server_full_response_text'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline); -try { - $event = $call->startBatch([ - 9999999 => [], - ]); -} catch (\Exception $e) {} - -// Test InvalidStartBatch -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'client_server_full_request_response'; -$reply_text = 'reply:client_server_full_request_response'; -$status_text = 'status:client_server_full_response_text'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline); -try { - $event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_SEND_MESSAGE => ['message' => $req_text], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => Grpc\STATUS_OK, - 'details' => 'abc', - ], - ]); -} catch (\Exception $e) {} - -// Test GetTarget -assert(is_string($channel->getTarget()) == true); - -// Test GetConnectivityState -assert(($channel->getConnectivityState() == - Grpc\CHANNEL_IDLE) == true); - -// Test WatchConnectivityStateFailed -$idle_state = $channel->getConnectivityState(); -assert(($idle_state == Grpc\CHANNEL_IDLE) == true); - -$now = Grpc\Timeval::now(); -$delta = new Grpc\Timeval(50000); // should timeout -$deadline = $now->add($delta); -assert($channel->watchConnectivityState( - $idle_state, $deadline) == false); - -// Test WatchConnectivityStateSuccess() -$idle_state = $channel->getConnectivityState(true); -assert(($idle_state == Grpc\CHANNEL_IDLE) == true); - -$now = Grpc\Timeval::now(); -$delta = new Grpc\Timeval(3000000); // should finish well before -$deadline = $now->add($delta); -$new_state = $channel->getConnectivityState(); -assert($new_state != $idle_state); - -// Test WatchConnectivityStateDoNothing -$idle_state = $channel->getConnectivityState(); -$now = Grpc\Timeval::now(); -$delta = new Grpc\Timeval(50000); -$deadline = $now->add($delta); -assert(!$channel->watchConnectivityState( - $idle_state, $deadline)); - -$new_state = $channel->getConnectivityState(); -assert($new_state == Grpc\CHANNEL_IDLE); - -// Test GetConnectivityStateInvalidParam -try { - $channel->getConnectivityState(new Grpc\Timeval()); -} catch (\Exception $e) {} -// Test WatchConnectivityStateInvalidParam -try { - $channel->watchConnectivityState(0, 1000); -} catch (\Exception $e) {} -// Test ChannelConstructorInvalidParam -try { - $channel = new Grpc\Channel('localhost:'.$port, null); -} catch (\Exception $e) {} -// testClose() -$channel->close(); - - -//============== SecureEndToEnd Test ==================== -// Set Up - -$credentials = Grpc\ChannelCredentials::createSsl( - file_get_contents(dirname(__FILE__).'/../data/ca.pem')); -$server_credentials = Grpc\ServerCredentials::createSsl( - null, - file_get_contents(dirname(__FILE__).'/../data/server1.key'), - file_get_contents(dirname(__FILE__).'/../data/server1.pem')); -$server = new Grpc\Server(); -$port = $server->addSecureHttp2Port('0.0.0.0:0', - $server_credentials); -$server->start(); -$host_override = 'foo.test.google.fr'; -$channel = new Grpc\Channel( - 'localhost:'.$port, - [ - 'grpc.ssl_target_name_override' => $host_override, - 'grpc.default_authority' => $host_override, - 'credentials' => $credentials, - ] -); - -// Test SimpleRequestBody -$deadline = Grpc\Timeval::infFuture(); -$status_text = 'xyz'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline, - $host_override); - $event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, -]); -assert($event->send_metadata == true); -assert($event->send_close == true); - -$event = $server->requestCall(); -assert('dummy_method' == $event->method); - -$server_call = $event->call; -$event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => Grpc\STATUS_OK, - 'details' => $status_text, - ], - Grpc\OP_RECV_CLOSE_ON_SERVER => true, -]); -assert($event->send_metadata == true); -assert($event->send_status == true); -assert($event->cancelled == false); - -$event = $call->startBatch([ - Grpc\OP_RECV_INITIAL_METADATA => true, - Grpc\OP_RECV_STATUS_ON_CLIENT => true, -]); -assert([] == $event->metadata); -$status = $event->status; -assert([] == $status->metadata); -assert(Grpc\STATUS_OK == $status->code); -assert($status_text == $status->details); - -unset($call); -unset($server_call); - -// Test MessageWriteFlags -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'message_write_flags_test'; -$status_text = 'xyz'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline, - $host_override); - $event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_MESSAGE => ['message' => $req_text, - 'flags' => Grpc\WRITE_NO_COMPRESS, ], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, -]); -assert($event->send_metadata == true); -assert($event->send_close == true); - -$event = $server->requestCall(); -assert('dummy_method' == $event->method); - -$server_call = $event->call; -$event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => Grpc\STATUS_OK, - 'details' => $status_text, - ], -]); -$event = $call->startBatch([ - Grpc\OP_RECV_INITIAL_METADATA => true, - Grpc\OP_RECV_STATUS_ON_CLIENT => true, -]); -assert([] == $event->metadata); -$status = $event->status; -assert([] == $status->metadata); -assert(Grpc\STATUS_OK == $status->code); -assert($status_text == $status->details);unset($call); - -unset($call); -unset($server_call); - -// Test ClientServerFullRequestResponse -$deadline = Grpc\Timeval::infFuture(); -$req_text = 'client_server_full_request_response'; -$reply_text = 'reply:client_server_full_request_response'; -$status_text = 'status:client_server_full_response_text'; -$call = new Grpc\Call($channel, - 'dummy_method', - $deadline, - $host_override); -$event = $call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_SEND_MESSAGE => ['message' => $req_text], -]); -assert($event->send_metadata == true); -assert($event->send_close == true); -assert($event->send_message == true); - -$event = $server->requestCall(); -assert('dummy_method' == $event->method); - -$server_call = $event->call; -$event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => Grpc\STATUS_OK, - 'details' => $status_text, - ], - Grpc\OP_RECV_MESSAGE => true, - Grpc\OP_RECV_CLOSE_ON_SERVER => true, -]); -assert($event->send_metadata); -assert($event->send_status); -assert($event->send_message); -assert(!$event->cancelled); -assert($req_text == $event->message); - -$event = $call->startBatch([ - Grpc\OP_RECV_INITIAL_METADATA => true, - Grpc\OP_RECV_MESSAGE => true, - Grpc\OP_RECV_STATUS_ON_CLIENT => true, -]); -assert([] == $event->metadata); -assert($reply_text == $event->message); -$status = $event->status; -assert([] == $status->metadata); -assert(Grpc\STATUS_OK == $status->code); -assert($status_text == $status->details); - -unset($call); -unset($server_call); - -$channel->close(); - - -//============== Timeval Test ==================== -// Test ConstructorWithInt -$time = new Grpc\Timeval(1234); -assert($time != NULL); -assert('Grpc\Timeval' == get_class($time)); - -// Test ConstructorWithNegative -$time = new Grpc\Timeval(-123); -assert($time != NULL); -assert('Grpc\Timeval' == get_class($time)); - -// Test ConstructorWithZero -$time = new Grpc\Timeval(0); -assert($time != NULL); -assert('Grpc\Timeval' == get_class($time)); - -// Test ConstructorWithOct -$time = new Grpc\Timeval(0123); -assert($time != NULL); -assert('Grpc\Timeval' == get_class($time)); - -// Test ConstructorWithHex -$time = new Grpc\Timeval(0x1A); -assert($time != NULL); -assert('Grpc\Timeval' == get_class($time)); - -// Test ConstructorWithFloat -$time = new Grpc\Timeval(123.456); -assert($time != NULL); -assert('Grpc\Timeval' == get_class($time)); - -// Test CompareSame -$zero = Grpc\Timeval::zero(); -assert(0 == Grpc\Timeval::compare($zero, $zero)); - -// Test PastIsLessThanZero -$zero = Grpc\Timeval::zero(); -$past = Grpc\Timeval::infPast(); -assert(0 > Grpc\Timeval::compare($past, $zero)); -assert(0 < Grpc\Timeval::compare($zero, $past)); - -// Test FutureIsGreaterThanZero -$zero = Grpc\Timeval::zero(); -$future = Grpc\Timeval::infFuture(); -assert(0 > Grpc\Timeval::compare($zero, $future)); -assert(0 < Grpc\Timeval::compare($future, $zero)); - -// Test NowIsBetweenZeroAndFuture -$zero = Grpc\Timeval::zero(); -$future = Grpc\Timeval::infFuture(); -$now = Grpc\Timeval::now(); -assert(0 > Grpc\Timeval::compare($zero, $now)); -assert(0 > Grpc\Timeval::compare($now, $future)); - -// Test NowAndAdd -$now = Grpc\Timeval::now(); -assert($now != NULL); -$delta = new Grpc\Timeval(1000); -$deadline = $now->add($delta); -assert(0 < Grpc\Timeval::compare($deadline, $now)); - -// Test NowAndSubtract -$now = Grpc\Timeval::now(); -$delta = new Grpc\Timeval(1000); -$deadline = $now->subtract($delta); -assert(0 > Grpc\Timeval::compare($deadline, $now)); - -// Test AddAndSubtract -$now = Grpc\Timeval::now(); -$delta = new Grpc\Timeval(1000); -$deadline = $now->add($delta); -$back_to_now = $deadline->subtract($delta); -assert(0 == Grpc\Timeval::compare($back_to_now, $now)); - -// Test Similar -$a = Grpc\Timeval::now(); -$delta = new Grpc\Timeval(1000); -$b = $a->add($delta); -$thresh = new Grpc\Timeval(1100); -assert(Grpc\Timeval::similar($a, $b, $thresh)); -$thresh = new Grpc\Timeval(900); -assert(!Grpc\Timeval::similar($a, $b, $thresh)); - -// Test SleepUntil -$curr_microtime = microtime(true); -$now = Grpc\Timeval::now(); -$delta = new Grpc\Timeval(1000); -$deadline = $now->add($delta); -$deadline->sleepUntil(); -$done_microtime = microtime(true); -assert(($done_microtime - $curr_microtime) > 0.0009); - -// Test ConstructorInvalidParam -try { - $delta = new Grpc\Timeval('abc'); -} catch (\Exception $e) {} -// Test AddInvalidParam -$a = Grpc\Timeval::now(); -try { - $a->add(1000); -} catch (\Exception $e) {} -// Test SubtractInvalidParam -$a = Grpc\Timeval::now(); -try { - $a->subtract(1000); -} catch (\Exception $e) {} -// Test CompareInvalidParam -try { - $a = Grpc\Timeval::compare(1000, 1100); -} catch (\Exception $e) {} -// Test SimilarInvalidParam -try { - $a = Grpc\Timeval::similar(1000, 1100, 1200); -} catch (\Exception $e) {} - unset($time); - - //============== Server Test ==================== - //Set Up - $server = NULL; - - // Test ConstructorWithNull -$server = new Grpc\Server(); -assert($server != NULL); - -// Test ConstructorWithNullArray -$server = new Grpc\Server([]); -assert($server != NULL); - -// Test ConstructorWithArray -$server = new Grpc\Server(['ip' => '127.0.0.1', - 'port' => '8080', ]); -assert($server != NULL); - -// Test RequestCall -$server = new Grpc\Server(); -$port = $server->addHttp2Port('0.0.0.0:0'); -$server->start(); -$channel = new Grpc\Channel('localhost:'.$port, - [ - 'force_new' => true, - 'credentials' => Grpc\ChannelCredentials::createInsecure() - ]); - -$deadline = Grpc\Timeval::infFuture(); -$call = new Grpc\Call($channel, 'dummy_method', $deadline); - -$event = $call->startBatch([Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - ]); - -$c = $server->requestCall(); -assert('dummy_method' == $c->method); -assert(is_string($c->host)); - -unset($call); -unset($channel); - -// Test InvalidConstructorWithNumKeyOfArray -try{ - $server = new Grpc\Server([10 => '127.0.0.1', - 20 => '8080', ]); -} -catch(\Exception $e){} - -// Test Invalid ArgumentException -try{ - $server = new Grpc\Server(['127.0.0.1', '8080']); -} -catch(\Exception $e){} - -// Test InvalidAddHttp2Port -$server = new Grpc\Server([]); -try{ - $port = $server->addHttp2Port(['0.0.0.0:0']); -} -catch(\Exception $e){} - -// Test InvalidAddSecureHttp2Port -$server = new Grpc\Server([]); -try{ - $port = $server->addSecureHttp2Port(['0.0.0.0:0']); -} -catch(\Exception $e){} - -// Test InvalidAddSecureHttp2Port2 -$server = new Grpc\Server(); -try{ - $port = $server->addSecureHttp2Port('0.0.0.0:0'); -} -catch(\Exception $e){} - -// Test InvalidAddSecureHttp2Port3 -$server = new Grpc\Server(); -try{ - $port = $server->addSecureHttp2Port('0.0.0.0:0', 'invalid'); -} -catch(\Exception $e){} -unset($server); - - -//============== ChannelCredential Test ==================== -// Test CreateSslWith3Null -$channel_credentials = Grpc\ChannelCredentials::createSsl(null, null, - null); -assert($channel_credentials != NULL); - -// Test CreateSslWith3NullString -$channel_credentials = Grpc\ChannelCredentials::createSsl('', '', ''); -assert($channel_credentials != NULL); - -// Test CreateInsecure -$channel_credentials = Grpc\ChannelCredentials::createInsecure(); -assert($channel_credentials == NULL); - -// Test InvalidCreateSsl() -try { - $channel_credentials = Grpc\ChannelCredentials::createSsl([]); -} -catch (\Exception $e) { -} -try { - $channel_credentials = Grpc\ChannelCredentials::createComposite( - 'something', 'something'); -} -catch (\Exception $e) { -} - -//============== Interceptor Test ==================== -require_once(dirname(__FILE__).'/../../lib/Grpc/BaseStub.php'); -require_once(dirname(__FILE__).'/../../lib/Grpc/AbstractCall.php'); -require_once(dirname(__FILE__).'/../../lib/Grpc/UnaryCall.php'); -require_once(dirname(__FILE__).'/../../lib/Grpc/ClientStreamingCall.php'); -require_once(dirname(__FILE__).'/../../lib/Grpc/Interceptor.php'); -require_once(dirname(__FILE__).'/../../lib/Grpc/CallInvoker.php'); -require_once(dirname(__FILE__).'/../../lib/Grpc/DefaultCallInvoker.php'); -require_once(dirname(__FILE__).'/../../lib/Grpc/Internal/InterceptorChannel.php'); - -class SimpleRequest -{ - private $data; - public function __construct($data) - { - $this->data = $data; - } - public function setData($data) - { - $this->data = $data; - } - public function serializeToString() - { - return $this->data; - } -} - -class InterceptorClient extends Grpc\BaseStub -{ - - /** - * @param string $hostname hostname - * @param array $opts channel options - * @param Channel|InterceptorChannel $channel (optional) re-use channel object - */ - public function __construct($hostname, $opts, $channel = null) - { - parent::__construct($hostname, $opts, $channel); - } - - /** - * A simple RPC. - * @param SimpleRequest $argument input argument - * @param array $metadata metadata - * @param array $options call options - */ - public function UnaryCall( - SimpleRequest $argument, - $metadata = [], - $options = [] - ) { - return $this->_simpleRequest( - '/dummy_method', - $argument, - [], - $metadata, - $options - ); - } - - /** - * A client-to-server streaming RPC. - * @param array $metadata metadata - * @param array $options call options - */ - public function StreamCall( - $metadata = [], - $options = [] - ) { - return $this->_clientStreamRequest('/dummy_method', [], $metadata, $options); - } -} - -class ChangeMetadataInterceptor extends Grpc\Interceptor -{ - public function interceptUnaryUnary($method, - $argument, - $deserialize, - array $metadata = [], - array $options = [], - $continuation) - { - $metadata["foo"] = array('interceptor_from_unary_request'); - return $continuation($method, $argument, $deserialize, $metadata, $options); - } - public function interceptStreamUnary($method, $deserialize, array $metadata = [], array $options = [], $continuation) - { - $metadata["foo"] = array('interceptor_from_stream_request'); - return $continuation($method, $deserialize, $metadata, $options); - } -} - -class ChangeMetadataInterceptor2 extends Grpc\Interceptor -{ - public function interceptUnaryUnary($method, - $argument, - $deserialize, - array $metadata = [], - array $options = [], - $continuation) - { - if (array_key_exists('foo', $metadata)) { - $metadata['bar'] = array('ChangeMetadataInterceptor should be executed first'); - } else { - $metadata["bar"] = array('interceptor_from_unary_request'); - } - return $continuation($method, $argument, $deserialize, $metadata, $options); - } - public function interceptStreamUnary($method, - $deserialize, - array $metadata = [], - array $options = [], - $continuation) - { - if (array_key_exists('foo', $metadata)) { - $metadata['bar'] = array('ChangeMetadataInterceptor should be executed first'); - } else { - $metadata["bar"] = array('interceptor_from_stream_request'); - } - return $continuation($method, $deserialize, $metadata, $options); - } -} - -class ChangeRequestCall -{ - private $call; - - public function __construct($call) - { - $this->call = $call; - } - public function getCall() - { - return $this->call; - } - - public function write($request) - { - $request->setData('intercepted_stream_request'); - $this->getCall()->write($request); - } - - public function wait() - { - return $this->getCall()->wait(); - } -} - -class ChangeRequestInterceptor extends Grpc\Interceptor -{ - public function interceptUnaryUnary($method, - $argument, - $deserialize, - array $metadata = [], - array $options = [], - $continuation) - { - $argument->setData('intercepted_unary_request'); - return $continuation($method, $argument, $deserialize, $metadata, $options); - } - public function interceptStreamUnary($method, $deserialize, array $metadata = [], array $options = [], $continuation) - { - return new ChangeRequestCall( - $continuation($method, $deserialize, $metadata, $options) - ); - } -} - -class StopCallInterceptor extends Grpc\Interceptor -{ - public function interceptUnaryUnary($method, - $argument, - array $metadata = [], - array $options = [], - $continuation) - { - $metadata["foo"] = array('interceptor_from_request_response'); - } - public function interceptStreamUnary($method, - array $metadata = [], - array $options = [], - $continuation) - { - $metadata["foo"] = array('interceptor_from_request_response'); - } -} - -// Set Up -$server = new Grpc\Server([]); -$port = $server->addHttp2Port('0.0.0.0:0'); -$channel = new Grpc\Channel('localhost:'.$port, [ - 'force_new' => true, - 'credentials' => Grpc\ChannelCredentials::createInsecure()]); -$server->start(); - -// Test ClientChangeMetadataOneInterceptor -$req_text = 'client_request'; -$channel_matadata_interceptor = new ChangeMetadataInterceptor(); -$intercept_channel = Grpc\Interceptor::intercept($channel, $channel_matadata_interceptor); -$client = new InterceptorClient('localhost:'.$port, [ - 'force_new' => true, - 'credentials' => Grpc\ChannelCredentials::createInsecure(), -], $intercept_channel); -$req = new SimpleRequest($req_text); -$unary_call = $client->UnaryCall($req); -$event = $server->requestCall(); -assert('/dummy_method' == $event->method); -assert(['interceptor_from_unary_request'] == $event->metadata['foo']); - -$stream_call = $client->StreamCall(); -$stream_call->write($req); -$event = $server->requestCall(); -assert('/dummy_method' == $event->method); -assert(['interceptor_from_stream_request'] == $event->metadata['foo']); - -unset($unary_call); -unset($stream_call); -unset($server_call); - -// Test ClientChangeMetadataTwoInterceptor -$req_text = 'client_request'; -$channel_matadata_interceptor = new ChangeMetadataInterceptor(); -$channel_matadata_intercepto2 = new ChangeMetadataInterceptor2(); -// test intercept separately. -$intercept_channel1 = Grpc\Interceptor::intercept($channel, $channel_matadata_interceptor); -$intercept_channel2 = Grpc\Interceptor::intercept($intercept_channel1, $channel_matadata_intercepto2); -$client = new InterceptorClient('localhost:'.$port, [ - 'force_new' => true, - 'credentials' => Grpc\ChannelCredentials::createInsecure(), -], $intercept_channel2); - -$req = new SimpleRequest($req_text); -$unary_call = $client->UnaryCall($req); -$event = $server->requestCall(); -assert('/dummy_method' == $event->method); -assert(['interceptor_from_unary_request'] == $event->metadata['foo']); -assert(['interceptor_from_unary_request'] == $event->metadata['bar']); - -$stream_call = $client->StreamCall(); -$stream_call->write($req); -$event = $server->requestCall(); -assert('/dummy_method' == $event->method); -assert(['interceptor_from_stream_request'] == $event->metadata['foo']); -assert(['interceptor_from_stream_request'] == $event->metadata['bar']); - -unset($unary_call); -unset($stream_call); -unset($server_call); - -// test intercept by array. -$intercept_channel3 = Grpc\Interceptor::intercept($channel, - [$channel_matadata_intercepto2, $channel_matadata_interceptor]); -$client = new InterceptorClient('localhost:'.$port, [ - 'force_new' => true, - 'credentials' => Grpc\ChannelCredentials::createInsecure(), -], $intercept_channel3); - -$req = new SimpleRequest($req_text); -$unary_call = $client->UnaryCall($req); -$event = $server->requestCall(); -assert('/dummy_method' == $event->method); -assert(['interceptor_from_unary_request'] == $event->metadata['foo']); -assert(['interceptor_from_unary_request'] == $event->metadata['bar']); - -$stream_call = $client->StreamCall(); -$stream_call->write($req); -$event = $server->requestCall(); -assert('/dummy_method' == $event->method); -assert(['interceptor_from_stream_request'] == $event->metadata['foo']); -assert(['interceptor_from_stream_request'] == $event->metadata['bar']); - -unset($unary_call); -unset($stream_call); -unset($server_call); - - -// Test ClientChangeRequestInterceptor -$req_text = 'client_request'; -$change_request_interceptor = new ChangeRequestInterceptor(); -$intercept_channel = Grpc\Interceptor::intercept($channel, - $change_request_interceptor); -$client = new InterceptorClient('localhost:'.$port, [ - 'force_new' => true, - 'credentials' => Grpc\ChannelCredentials::createInsecure(), -], $intercept_channel); - -$req = new SimpleRequest($req_text); -$unary_call = $client->UnaryCall($req); - -$event = $server->requestCall(); -assert('/dummy_method' == $event->method); -$server_call = $event->call; -$event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => Grpc\STATUS_OK, - 'details' => '', - ], - Grpc\OP_RECV_MESSAGE => true, - Grpc\OP_RECV_CLOSE_ON_SERVER => true, -]); -assert('intercepted_unary_request' == $event->message); - -$stream_call = $client->StreamCall(); -$stream_call->write($req); -$event = $server->requestCall(); -assert('/dummy_method' == $event->method); -$server_call = $event->call; -$event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => Grpc\STATUS_OK, - 'details' => '', - ], - Grpc\OP_RECV_MESSAGE => true, - Grpc\OP_RECV_CLOSE_ON_SERVER => true, -]); -assert('intercepted_stream_request' == $event->message); - -unset($unary_call); -unset($stream_call); -unset($server_call); - -// Test ClientChangeStopCallInterceptor -$req_text = 'client_request'; -$channel_request_interceptor = new StopCallInterceptor(); -$intercept_channel = Grpc\Interceptor::intercept($channel, - $channel_request_interceptor); -$client = new InterceptorClient('localhost:'.$port, [ - 'force_new' => true, - 'credentials' => Grpc\ChannelCredentials::createInsecure(), -], $intercept_channel); - -$req = new SimpleRequest($req_text); -$unary_call = $client->UnaryCall($req); -assert($unary_call == NULL); - - -$stream_call = $client->StreamCall(); -assert($stream_call == NULL); - -unset($unary_call); -unset($stream_call); -unset($server_call); - -// Test GetInterceptorChannelConnectivityState -$channel = new Grpc\Channel( - 'localhost:0', - [ - 'force_new' => true, - 'credentials' => Grpc\ChannelCredentials::createInsecure() - ] -); -$interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor()); -$state = $interceptor_channel->getConnectivityState(); -assert(0 == $state); -$channel->close(); - -// Test InterceptorChannelWatchConnectivityState -$channel = new Grpc\Channel( - 'localhost:0', - [ - 'force_new' => true, - 'credentials' => Grpc\ChannelCredentials::createInsecure() - ] -); -$interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor()); -$now = Grpc\Timeval::now(); -$deadline = $now->add(new Grpc\Timeval(100*1000)); -$state = $interceptor_channel->watchConnectivityState(1, $deadline); -assert($state); -unset($time); -unset($deadline); -$channel->close(); - -// Test InterceptorChannelClose -$channel = new Grpc\Channel( - 'localhost:0', - [ - 'force_new' => true, - 'credentials' => Grpc\ChannelCredentials::createInsecure() - ] -); -$interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor()); -assert($interceptor_channel != NULL); -$channel->close(); - -// Test InterceptorChannelGetTarget -$channel = new Grpc\Channel( - 'localhost:8888', - [ - 'force_new' => true, - 'credentials' => Grpc\ChannelCredentials::createInsecure() - ] -); -$interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor()); -$target = $interceptor_channel->getTarget(); -assert(is_string($target)); - -$channel->close(); -unset($server); - - -//============== CallInvoker Test ==================== -class CallInvokerSimpleRequest -{ - private $data; - public function __construct($data) - { - $this->data = $data; - } - public function setData($data) - { - $this->data = $data; - } - public function serializeToString() - { - return $this->data; - } -} - -class CallInvokerClient extends Grpc\BaseStub -{ - - /** - * @param string $hostname hostname - * @param array $opts channel options - * @param Channel|InterceptorChannel $channel (optional) re-use channel object - */ - public function __construct($hostname, $opts, $channel = null) - { - parent::__construct($hostname, $opts, $channel); - } - - /** - * A simple RPC. - * @param SimpleRequest $argument input argument - * @param array $metadata metadata - * @param array $options call options - */ - public function UnaryCall( - CallInvokerSimpleRequest $argument, - $metadata = [], - $options = [] - ) { - return $this->_simpleRequest( - '/dummy_method', - $argument, - [], - $metadata, - $options - ); - } -} - -class CallInvokerUpdateChannel implements \Grpc\CallInvoker -{ - private $channel; - - public function getChannel() { - return $this->channel; - } - - public function createChannelFactory($hostname, $opts) { - $this->channel = new \Grpc\Channel('localhost:50050', $opts); - return $this->channel; - } - - public function UnaryCall($channel, $method, $deserialize, $options) { - return new UnaryCall($channel, $method, $deserialize, $options); - } - - public function ClientStreamingCall($channel, $method, $deserialize, $options) { - return new ClientStreamingCall($channel, $method, $deserialize, $options); - } - - public function ServerStreamingCall($channel, $method, $deserialize, $options) { - return new ServerStreamingCall($channel, $method, $deserialize, $options); - } - - public function BidiStreamingCall($channel, $method, $deserialize, $options) { - return new BidiStreamingCall($channel, $method, $deserialize, $options); - } -} - -class CallInvokerChangeRequest implements \Grpc\CallInvoker -{ - private $channel; - - public function getChannel() { - return $this->channel; - } - public function createChannelFactory($hostname, $opts) { - $this->channel = new \Grpc\Channel($hostname, $opts); - return $this->channel; - } - - public function UnaryCall($channel, $method, $deserialize, $options) { - return new CallInvokerChangeRequestCall($channel, $method, $deserialize, $options); - } - - public function ClientStreamingCall($channel, $method, $deserialize, $options) { - return new ClientStreamingCall($channel, $method, $deserialize, $options); - } - - public function ServerStreamingCall($channel, $method, $deserialize, $options) { - return new ServerStreamingCall($channel, $method, $deserialize, $options); - } - - public function BidiStreamingCall($channel, $method, $deserialize, $options) { - return new BidiStreamingCall($channel, $method, $deserialize, $options); - } -} - -class CallInvokerChangeRequestCall -{ - private $call; - - public function __construct($channel, $method, $deserialize, $options) - { - $this->call = new \Grpc\UnaryCall($channel, $method, $deserialize, $options); - } - - public function start($argument, $metadata, $options) { - $argument->setData('intercepted_unary_request'); - $this->call->start($argument, $metadata, $options); - } - - public function wait() - { - return $this->call->wait(); - } -} - -// Set Up -$server = new Grpc\Server([]); -$port = $server->addHttp2Port('0.0.0.0:0'); -$server->start(); - -// Test CreateDefaultCallInvoker -$call_invoker = new \Grpc\DefaultCallInvoker(); - -// Test CreateCallInvoker -$call_invoker = new CallInvokerUpdateChannel(); - -// Test CallInvokerAccessChannel -$call_invoker = new CallInvokerUpdateChannel(); -$stub = new \Grpc\BaseStub('localhost:50051', - ['credentials' => \Grpc\ChannelCredentials::createInsecure(), - 'grpc_call_invoker' => $call_invoker]); -assert($call_invoker->getChannel()->getTarget() == 'localhost:50050'); -$call_invoker->getChannel()->close(); - -// Test ClientChangeRequestCallInvoker -$req_text = 'client_request'; -$call_invoker = new CallInvokerChangeRequest(); -$client = new CallInvokerClient('localhost:'.$port, [ - 'force_new' => true, - 'credentials' => Grpc\ChannelCredentials::createInsecure(), - 'grpc_call_invoker' => $call_invoker, -]); - -$req = new CallInvokerSimpleRequest($req_text); -$unary_call = $client->UnaryCall($req); - -$event = $server->requestCall(); -assert('/dummy_method' == $event->method); -$server_call = $event->call; -$event = $server_call->startBatch([ - Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => Grpc\STATUS_OK, - 'details' => '', - ], - Grpc\OP_RECV_MESSAGE => true, - Grpc\OP_RECV_CLOSE_ON_SERVER => true, -]); -assert('intercepted_unary_request' == $event->message); -$call_invoker->getChannel()->close(); -unset($unary_call); -unset($server_call); - -unset($server); - -<<<<<<< HEAD -<<<<<<< HEAD -echo "Went Through All Unit Tests..............\r\n"; -======= -echo "Went Through All Unit Tests.............."; ->>>>>>> add MemoryLeakTest -======= -echo "Went Through All Unit Tests..............\r\n"; ->>>>>>> complete memory leak test - - diff --git a/src/php/tests/unit_tests/CallTest.php b/src/php/tests/unit_tests/CallTest.php index 28098c4016e..be1d77fe7ad 100644 --- a/src/php/tests/unit_tests/CallTest.php +++ b/src/php/tests/unit_tests/CallTest.php @@ -86,16 +86,6 @@ class CallTest extends PHPUnit_Framework_TestCase $this->assertTrue($result->send_metadata); } - public function testAddMultiAndMultiValueMetadata() - { - $batch = [ - Grpc\OP_SEND_INITIAL_METADATA => ['key1' => ['value1', 'value2'], - 'key2' => ['value3', 'value4'],], - ]; - $result = $this->call->startBatch($batch); - $this->assertTrue($result->send_metadata); - } - public function testGetPeer() { $this->assertTrue(is_string($this->call->getPeer())); diff --git a/templates/tools/dockerfile/php_valgrind.include b/templates/tools/dockerfile/php_valgrind.include deleted file mode 100644 index f1f3b67d826..00000000000 --- a/templates/tools/dockerfile/php_valgrind.include +++ /dev/null @@ -1,7 +0,0 @@ -#================= -# PHP Test dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y ${'\\'} - valgrind diff --git a/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template index 0b2290b741c..e7b6c0d5f9c 100644 --- a/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template @@ -19,7 +19,6 @@ <%include file="../../php7_deps.include"/> <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> - <%include file="../../php_valgrind.include"/> <%include file="../../run_tests_addons.include"/> # Define the default command. CMD ["bash"] diff --git a/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template index 329205363e3..fdbad53c391 100644 --- a/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template @@ -20,7 +20,6 @@ <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../php_deps.include"/> - <%include file="../../php_valgrind.include"/> <%include file="../../run_tests_addons.include"/> # Define the default command. CMD ["bash"] diff --git a/tools/dockerfile/test/php7_jessie_x64/Dockerfile b/tools/dockerfile/test/php7_jessie_x64/Dockerfile index 529ebb9127b..0dff8399047 100644 --- a/tools/dockerfile/test/php7_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/php7_jessie_x64/Dockerfile @@ -79,14 +79,6 @@ 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 -#================= -# PHP Test dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y \ - valgrind - RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/test/php_jessie_x64/Dockerfile b/tools/dockerfile/test/php_jessie_x64/Dockerfile index f69f7e65a20..ed59e569956 100644 --- a/tools/dockerfile/test/php_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/php_jessie_x64/Dockerfile @@ -76,14 +76,6 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t RUN apt-get update && apt-get install -y \ git php5 php5-dev phpunit unzip -#================= -# PHP Test dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y \ - valgrind - RUN mkdir /var/local/jenkins From 5198ccd89cf3d1d7970e6e5176cc308bf0c85ed1 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Tue, 29 Jan 2019 00:40:01 -0800 Subject: [PATCH 093/218] Revert "Add basic benchmark test for Python" --- src/proto/grpc/core/BUILD | 18 +-- src/proto/grpc/testing/BUILD | 94 +++------------- src/python/grpcio_tests/tests/qps/BUILD | 103 ------------------ src/python/grpcio_tests/tests/qps/README.md | 102 ----------------- .../tests/qps/basic_benchmark_test.sh | 45 -------- .../grpcio_tests/tests/qps/scenarios.json | 96 ---------------- test/cpp/qps/BUILD | 6 +- 7 files changed, 20 insertions(+), 444 deletions(-) delete mode 100644 src/python/grpcio_tests/tests/qps/BUILD delete mode 100644 src/python/grpcio_tests/tests/qps/README.md delete mode 100755 src/python/grpcio_tests/tests/qps/basic_benchmark_test.sh delete mode 100644 src/python/grpcio_tests/tests/qps/scenarios.json diff --git a/src/proto/grpc/core/BUILD b/src/proto/grpc/core/BUILD index 2543027821c..46de9fae187 100644 --- a/src/proto/grpc/core/BUILD +++ b/src/proto/grpc/core/BUILD @@ -14,25 +14,11 @@ licenses(["notice"]) # Apache v2 -load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library") -load("@grpc_python_dependencies//:requirements.bzl", "requirement") -load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_library") +load("//bazel:grpc_build_system.bzl", "grpc_proto_library", "grpc_package") -grpc_package( - name = "core", - visibility = "public", -) +grpc_package(name = "core", visibility = "public") grpc_proto_library( name = "stats_proto", srcs = ["stats.proto"], ) - -py_proto_library( - name = "py_stats_proto", - protos = ["stats.proto"], - with_grpc = True, - deps = [ - requirement("protobuf"), - ], -) diff --git a/src/proto/grpc/testing/BUILD b/src/proto/grpc/testing/BUILD index 0c658967942..9876d5160a1 100644 --- a/src/proto/grpc/testing/BUILD +++ b/src/proto/grpc/testing/BUILD @@ -14,14 +14,11 @@ licenses(["notice"]) # Apache v2 -load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library") +load("//bazel:grpc_build_system.bzl", "grpc_proto_library", "grpc_package") load("@grpc_python_dependencies//:requirements.bzl", "requirement") load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_library") -grpc_package( - name = "testing", - visibility = "public", -) +grpc_package(name = "testing", visibility = "public") exports_files([ "echo.proto", @@ -53,11 +50,9 @@ grpc_proto_library( grpc_proto_library( name = "echo_proto", srcs = ["echo.proto"], + deps = ["echo_messages_proto", + "simple_messages_proto"], generate_mocks = True, - deps = [ - "echo_messages_proto", - "simple_messages_proto", - ], ) grpc_proto_library( @@ -68,10 +63,10 @@ grpc_proto_library( py_proto_library( name = "py_empty_proto", - protos = ["empty.proto"], + protos = ["empty.proto",], with_grpc = True, deps = [ - requirement("protobuf"), + requirement('protobuf'), ], ) @@ -83,10 +78,10 @@ grpc_proto_library( py_proto_library( name = "py_messages_proto", - protos = ["messages.proto"], + protos = ["messages.proto",], with_grpc = True, deps = [ - requirement("protobuf"), + requirement('protobuf'), ], ) @@ -105,7 +100,7 @@ grpc_proto_library( name = "benchmark_service_proto", srcs = ["benchmark_service.proto"], deps = [ - "messages_proto", + "messages_proto", ], ) @@ -113,7 +108,7 @@ grpc_proto_library( name = "report_qps_scenario_service_proto", srcs = ["report_qps_scenario_service.proto"], deps = [ - "control_proto", + "control_proto", ], ) @@ -121,7 +116,7 @@ grpc_proto_library( name = "worker_service_proto", srcs = ["worker_service.proto"], deps = [ - "control_proto", + "control_proto", ], ) @@ -137,7 +132,7 @@ grpc_proto_library( has_services = False, deps = [ "//src/proto/grpc/core:stats_proto", - ], + ] ) grpc_proto_library( @@ -151,71 +146,14 @@ grpc_proto_library( py_proto_library( name = "py_test_proto", - proto_deps = [ - ":py_empty_proto", - ":py_messages_proto", - ], - protos = ["test.proto"], + protos = ["test.proto",], with_grpc = True, deps = [ - requirement("protobuf"), + requirement('protobuf'), ], -) - -py_proto_library( - name = "py_benchmark_service_proto", proto_deps = [ + ":py_empty_proto", ":py_messages_proto", - ], - protos = ["benchmark_service.proto"], - with_grpc = True, - deps = [ - requirement("protobuf"), - ], -) - -py_proto_library( - name = "py_payloads_proto", - protos = ["payloads.proto"], - with_grpc = True, - deps = [ - requirement("protobuf"), - ], + ] ) -py_proto_library( - name = "py_stats_proto", - proto_deps = [ - "//src/proto/grpc/core:py_stats_proto", - ], - protos = ["stats.proto"], - with_grpc = True, - deps = [ - requirement("protobuf"), - ], -) - -py_proto_library( - name = "py_control_proto", - proto_deps = [ - ":py_payloads_proto", - ":py_stats_proto", - ], - protos = ["control.proto"], - with_grpc = True, - deps = [ - requirement("protobuf"), - ], -) - -py_proto_library( - name = "py_worker_service_proto", - proto_deps = [ - ":py_control_proto", - ], - protos = ["worker_service.proto"], - with_grpc = True, - deps = [ - requirement("protobuf"), - ], -) diff --git a/src/python/grpcio_tests/tests/qps/BUILD b/src/python/grpcio_tests/tests/qps/BUILD deleted file mode 100644 index e1c7d138ef3..00000000000 --- a/src/python/grpcio_tests/tests/qps/BUILD +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright 2019 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. - -package(default_visibility = ["//visibility:public"]) - -load("@grpc_python_dependencies//:requirements.bzl", "requirement") - -py_library( - name = "benchmark_client", - srcs = ["benchmark_client.py"], - imports = ["../../"], - deps = [ - requirement("six"), - "//src/proto/grpc/testing:py_benchmark_service_proto", - "//src/proto/grpc/testing:py_messages_proto", - "//src/python/grpcio/grpc:grpcio", - "//src/python/grpcio_tests/tests/unit:resources", - "//src/python/grpcio_tests/tests/unit:test_common", - ], -) - -py_library( - name = "benchmark_server", - srcs = ["benchmark_server.py"], - imports = ["../../"], - deps = [ - "//src/proto/grpc/testing:py_benchmark_service_proto", - "//src/proto/grpc/testing:py_messages_proto", - ], -) - -py_library( - name = "client_runner", - srcs = ["client_runner.py"], - imports = ["../../"], -) - -py_library( - name = "histogram", - srcs = ["histogram.py"], - imports = ["../../"], - deps = [ - "//src/proto/grpc/testing:py_stats_proto", - ], -) - -py_library( - name = "worker_server", - srcs = ["worker_server.py"], - imports = ["../../"], - deps = [ - ":benchmark_client", - ":benchmark_server", - ":client_runner", - ":histogram", - "//src/proto/grpc/testing:py_benchmark_service_proto", - "//src/proto/grpc/testing:py_control_proto", - "//src/proto/grpc/testing:py_stats_proto", - "//src/proto/grpc/testing:py_worker_service_proto", - "//src/python/grpcio/grpc:grpcio", - "//src/python/grpcio_tests/tests/unit:resources", - "//src/python/grpcio_tests/tests/unit:test_common", - ], -) - -py_binary( - name = "qps_worker", - srcs = ["qps_worker.py"], - imports = ["../../"], - main = "qps_worker.py", - deps = [ - ":worker_server", - "//src/proto/grpc/testing:py_worker_service_proto", - "//src/python/grpcio/grpc:grpcio", - "//src/python/grpcio_tests/tests/unit:test_common", - ], -) - -filegroup( - name = "scenarios", - srcs = ["scenarios.json"], -) - -sh_test( - name = "basic_benchmark_test", - srcs = ["basic_benchmark_test.sh"], - data = [ - ":qps_worker", - ":scenarios", - "//test/cpp/qps:qps_json_driver", - ], -) diff --git a/src/python/grpcio_tests/tests/qps/README.md b/src/python/grpcio_tests/tests/qps/README.md deleted file mode 100644 index 8ae155a5b4b..00000000000 --- a/src/python/grpcio_tests/tests/qps/README.md +++ /dev/null @@ -1,102 +0,0 @@ -# Python Benchmark Tools - -## Scenarios - -In `src/proto/grpc/testing/control.proto`, it defines the fields of a scenario. -In `tools/run_tests/performance/scenario_config.py`, the script generates actual scenario content that usually in json format, or piped to another script. - -All Python related benchmark scenarios are: -* netperf -* python_generic_sync_streaming_ping_pong -* python_protobuf_sync_streaming_ping_pong -* python_protobuf_async_unary_ping_pong -* python_protobuf_sync_unary_ping_pong -* python_protobuf_sync_unary_qps_unconstrained -* python_protobuf_sync_streaming_qps_unconstrained -* python_protobuf_sync_unary_ping_pong_1MB - -Here we picked a small but representative subset, and reduce their benchmark duration from 30 seconds to 10 seconds: -* python_protobuf_async_unary_ping_pong -* python_protobuf_sync_streaming_ping_pong - -## Why keep the scenario file if it can be generated? - -Well... The `tools/run_tests/performance/scenario_config.py` is 1274 lines long. The intention of building these benchmark tools is reducing the complexity of existing infrastructure code. So, instead of calling layers of abstraction to generate the scenario file, keeping a valid static copy is preferable. - -Also, if the use case for this tool grows beyond simple static scenarios, we can incorporate automatic generation and selection of scenarios into the tool. - -## How to run it? - -```shell -bazel test --test_output=streamed src/python/grpcio_tests/tests/qps:basic_benchmark_test -``` - -## What does the output look like? - -``` -RUNNING SCENARIO: python_protobuf_async_unary_ping_pong -I0123 00:26:04.746195000 140736237159296 driver.cc:288] Starting server on localhost:10086 (worker #0) -D0123 00:26:04.747190000 140736237159296 ev_posix.cc:170] Using polling engine: poll -D0123 00:26:04.747264000 140736237159296 dns_resolver_ares.cc:488] Using ares dns resolver -I0123 00:26:04.748445000 140736237159296 subchannel.cc:869] Connect failed: {"created":"@1548203164.748403000","description":"Failed to connect to remote host: Connection refused","errno":61,"file":"src/core/lib/iomgr/tcp_client_posix.cc","file_line":207,"os_error":"Connection refused","syscall":"connect","target_address":"ipv6:[::1]:10086"} -I0123 00:26:04.748585000 140736237159296 subchannel.cc:869] Connect failed: {"created":"@1548203164.748564000","description":"Failed to connect to remote host: Connection refused","errno":61,"file":"src/core/lib/iomgr/tcp_client_posix.cc","file_line":207,"os_error":"Connection refused","syscall":"connect","target_address":"ipv4:127.0.0.1:10086"} -I0123 00:26:04.748596000 140736237159296 subchannel.cc:751] Subchannel 0x7fca43c19360: Retry in 999 milliseconds -I0123 00:26:05.751251000 123145571299328 subchannel.cc:710] Failed to connect to channel, retrying -I0123 00:26:05.752209000 140736237159296 subchannel.cc:832] New connected subchannel at 0x7fca45000060 for subchannel 0x7fca43c19360 -I0123 00:26:05.772291000 140736237159296 driver.cc:349] Starting client on localhost:10087 (worker #1) -D0123 00:26:05.772384000 140736237159296 driver.cc:373] Client 0 gets 1 channels -I0123 00:26:05.773286000 140736237159296 subchannel.cc:832] New connected subchannel at 0x7fca45004a80 for subchannel 0x7fca451034b0 -I0123 00:26:05.789797000 140736237159296 driver.cc:394] Initiating -I0123 00:26:05.790858000 140736237159296 driver.cc:415] Warming up -I0123 00:26:07.791078000 140736237159296 driver.cc:421] Starting -I0123 00:26:07.791860000 140736237159296 driver.cc:448] Running -I0123 00:26:17.790915000 140736237159296 driver.cc:462] Finishing clients -I0123 00:26:17.791821000 140736237159296 driver.cc:476] Received final status from client 0 -I0123 00:26:17.792148000 140736237159296 driver.cc:508] Finishing servers -I0123 00:26:17.792493000 140736237159296 driver.cc:522] Received final status from server 0 -I0123 00:26:17.795786000 140736237159296 report.cc:82] QPS: 2066.6 -I0123 00:26:17.795799000 140736237159296 report.cc:122] QPS: 2066.6 (258.3/server core) -I0123 00:26:17.795805000 140736237159296 report.cc:127] Latencies (50/90/95/99/99.9%-ile): 467.9/504.8/539.0/653.3/890.4 us -I0123 00:26:17.795811000 140736237159296 report.cc:137] Server system time: 100.00% -I0123 00:26:17.795815000 140736237159296 report.cc:139] Server user time: 100.00% -I0123 00:26:17.795818000 140736237159296 report.cc:141] Client system time: 100.00% -I0123 00:26:17.795821000 140736237159296 report.cc:143] Client user time: 100.00% -I0123 00:26:17.795825000 140736237159296 report.cc:148] Server CPU usage: 0.00% -I0123 00:26:17.795828000 140736237159296 report.cc:153] Client Polls per Request: 0.00 -I0123 00:26:17.795831000 140736237159296 report.cc:155] Server Polls per Request: 0.00 -I0123 00:26:17.795834000 140736237159296 report.cc:160] Server Queries/CPU-sec: 1033.19 -I0123 00:26:17.795837000 140736237159296 report.cc:162] Client Queries/CPU-sec: 1033.32 -RUNNING SCENARIO: python_protobuf_sync_streaming_ping_pong -I0123 00:26:17.795888000 140736237159296 driver.cc:288] Starting server on localhost:10086 (worker #0) -D0123 00:26:17.795964000 140736237159296 ev_posix.cc:170] Using polling engine: poll -D0123 00:26:17.795978000 140736237159296 dns_resolver_ares.cc:488] Using ares dns resolver -I0123 00:26:17.796613000 140736237159296 subchannel.cc:832] New connected subchannel at 0x7fca43c15820 for subchannel 0x7fca43d12140 -I0123 00:26:17.810911000 140736237159296 driver.cc:349] Starting client on localhost:10087 (worker #1) -D0123 00:26:17.811037000 140736237159296 driver.cc:373] Client 0 gets 1 channels -I0123 00:26:17.811892000 140736237159296 subchannel.cc:832] New connected subchannel at 0x7fca43d18f40 for subchannel 0x7fca43d16b80 -I0123 00:26:17.818902000 140736237159296 driver.cc:394] Initiating -I0123 00:26:17.820776000 140736237159296 driver.cc:415] Warming up -I0123 00:26:19.824685000 140736237159296 driver.cc:421] Starting -I0123 00:26:19.825970000 140736237159296 driver.cc:448] Running -I0123 00:26:29.821866000 140736237159296 driver.cc:462] Finishing clients -I0123 00:26:29.823259000 140736237159296 driver.cc:476] Received final status from client 0 -I0123 00:26:29.827195000 140736237159296 driver.cc:508] Finishing servers -I0123 00:26:29.827599000 140736237159296 driver.cc:522] Received final status from server 0 -I0123 00:26:29.828739000 140736237159296 report.cc:82] QPS: 619.5 -I0123 00:26:29.828752000 140736237159296 report.cc:122] QPS: 619.5 (77.4/server core) -I0123 00:26:29.828760000 140736237159296 report.cc:127] Latencies (50/90/95/99/99.9%-ile): 1589.8/1854.3/1920.4/2015.8/2204.8 us -I0123 00:26:29.828765000 140736237159296 report.cc:137] Server system time: 100.00% -I0123 00:26:29.828769000 140736237159296 report.cc:139] Server user time: 100.00% -I0123 00:26:29.828772000 140736237159296 report.cc:141] Client system time: 100.00% -I0123 00:26:29.828776000 140736237159296 report.cc:143] Client user time: 100.00% -I0123 00:26:29.828780000 140736237159296 report.cc:148] Server CPU usage: 0.00% -I0123 00:26:29.828784000 140736237159296 report.cc:153] Client Polls per Request: 0.00 -I0123 00:26:29.828788000 140736237159296 report.cc:155] Server Polls per Request: 0.00 -I0123 00:26:29.828792000 140736237159296 report.cc:160] Server Queries/CPU-sec: 309.58 -I0123 00:26:29.828795000 140736237159296 report.cc:162] Client Queries/CPU-sec: 309.75 -``` - -## Future Works (TODOs) - -1. Generate a target for each scenario. -2. Simplify the main entrance of our benchmark related code, or make it depends on Bazel. diff --git a/src/python/grpcio_tests/tests/qps/basic_benchmark_test.sh b/src/python/grpcio_tests/tests/qps/basic_benchmark_test.sh deleted file mode 100755 index fecb528396a..00000000000 --- a/src/python/grpcio_tests/tests/qps/basic_benchmark_test.sh +++ /dev/null @@ -1,45 +0,0 @@ -#! /bin/bash -# Copyright 2019 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. - -# This test benchmarks Python client/server. -set -ex - -declare -a DRIVER_PORTS=("10086" "10087") -SCENARIOS_FILE=src/python/grpcio_tests/tests/qps/scenarios.json - -function join { local IFS="$1"; shift; echo "$*"; } - -if [[ -e "${SCENARIOS_FILE}" ]]; then - echo "Running against ${SCENARIOS_FILE}:" - cat "${SCENARIOS_FILE}" -else - echo "Failed to find ${SCENARIOS_FILE}!" - exit 1 -fi - -echo "Starting Python qps workers..." -qps_workers=() -for DRIVER_PORT in "${DRIVER_PORTS[@]}" -do - echo -e "\tRunning Python qps worker listening at localhost:${DRIVER_PORT}..." - src/python/grpcio_tests/tests/qps/qps_worker \ - --driver_port="${DRIVER_PORT}" & - qps_workers+=("localhost:${DRIVER_PORT}") -done - -echo "Running qps json driver..." -QPS_WORKERS=$(join , ${qps_workers[@]}) -export QPS_WORKERS -test/cpp/qps/qps_json_driver --scenarios_file="${SCENARIOS_FILE}" diff --git a/src/python/grpcio_tests/tests/qps/scenarios.json b/src/python/grpcio_tests/tests/qps/scenarios.json deleted file mode 100644 index 03c91be1e71..00000000000 --- a/src/python/grpcio_tests/tests/qps/scenarios.json +++ /dev/null @@ -1,96 +0,0 @@ -{ - "scenarios": [ - { - "name": "python_protobuf_async_unary_ping_pong", - "clientConfig": { - "clientType": "ASYNC_CLIENT", - "securityParams": { - "useTestCa": true, - "serverHostOverride": "foo.test.google.fr" - }, - "outstandingRpcsPerChannel": 1, - "clientChannels": 1, - "asyncClientThreads": 1, - "loadParams": { - "closedLoop": {} - }, - "payloadConfig": { - "simpleParams": {} - }, - "histogramParams": { - "resolution": 0.01, - "maxPossible": 60000000000 - }, - "channelArgs": [ - { - "name": "grpc.optimization_target", - "strValue": "latency" - } - ] - }, - "numClients": 1, - "serverConfig": { - "serverType": "ASYNC_SERVER", - "securityParams": { - "useTestCa": true, - "serverHostOverride": "foo.test.google.fr" - }, - "channelArgs": [ - { - "name": "grpc.optimization_target", - "strValue": "latency" - } - ] - }, - "numServers": 1, - "warmupSeconds": 2, - "benchmarkSeconds": 10 - }, - { - "name": "python_protobuf_sync_streaming_ping_pong", - "clientConfig": { - "securityParams": { - "useTestCa": true, - "serverHostOverride": "foo.test.google.fr" - }, - "outstandingRpcsPerChannel": 1, - "clientChannels": 1, - "asyncClientThreads": 1, - "rpcType": "STREAMING", - "loadParams": { - "closedLoop": {} - }, - "payloadConfig": { - "simpleParams": {} - }, - "histogramParams": { - "resolution": 0.01, - "maxPossible": 60000000000 - }, - "channelArgs": [ - { - "name": "grpc.optimization_target", - "strValue": "latency" - } - ] - }, - "numClients": 1, - "serverConfig": { - "serverType": "ASYNC_SERVER", - "securityParams": { - "useTestCa": true, - "serverHostOverride": "foo.test.google.fr" - }, - "channelArgs": [ - { - "name": "grpc.optimization_target", - "strValue": "latency" - } - ] - }, - "numServers": 1, - "warmupSeconds": 2, - "benchmarkSeconds": 10 - } - ] -} diff --git a/test/cpp/qps/BUILD b/test/cpp/qps/BUILD index 41ae5d41e0c..8855a1c155d 100644 --- a/test/cpp/qps/BUILD +++ b/test/cpp/qps/BUILD @@ -14,10 +14,8 @@ licenses(["notice"]) # Apache v2 -package(default_visibility = ["//visibility:public"]) - -load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package") -load("//test/cpp/qps:qps_benchmark_script.bzl", "json_run_localhost_batch", "qps_json_driver_batch") +load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library", "grpc_cc_binary", "grpc_package") +load("//test/cpp/qps:qps_benchmark_script.bzl", "qps_json_driver_batch", "json_run_localhost_batch") grpc_package(name = "test/cpp/qps") From a3d997cbdc4dcf8f4aff7e380f9efdd041cf09d0 Mon Sep 17 00:00:00 2001 From: Yihua Zhang Date: Tue, 29 Jan 2019 10:04:28 -0800 Subject: [PATCH 094/218] Add a TLS credential surface API (experimental) --- BUILD | 2 + CMakeLists.txt | 2 + Makefile | 3 + build.yaml | 2 + config.m4 | 2 + config.w32 | 2 + gRPC-C++.podspec | 1 + gRPC-Core.podspec | 3 + grpc.def | 9 + grpc.gemspec | 2 + grpc.gyp | 1 + include/grpc/grpc_security.h | 195 ++++++++++++++++ package.xml | 2 + .../tls/grpc_tls_credentials_options.cc | 192 ++++++++++++++++ .../tls/grpc_tls_credentials_options.h | 213 ++++++++++++++++++ .../security/security_connector/ssl_utils.h | 33 +++ src/python/grpcio/grpc_core_dependencies.py | 1 + src/ruby/ext/grpc/rb_grpc_imports.generated.c | 18 ++ src/ruby/ext/grpc/rb_grpc_imports.generated.h | 27 +++ .../core/surface/public_headers_must_be_c89.c | 9 + tools/doxygen/Doxyfile.core.internal | 2 + .../generated/sources_and_headers.json | 3 + 22 files changed, 724 insertions(+) create mode 100644 src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc create mode 100644 src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h diff --git a/BUILD b/BUILD index 81272e27e97..ff066edaeaf 100644 --- a/BUILD +++ b/BUILD @@ -1614,6 +1614,7 @@ grpc_cc_library( "src/core/lib/security/credentials/oauth2/oauth2_credentials.cc", "src/core/lib/security/credentials/plugin/plugin_credentials.cc", "src/core/lib/security/credentials/ssl/ssl_credentials.cc", + "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc", "src/core/lib/security/security_connector/alts/alts_security_connector.cc", "src/core/lib/security/security_connector/fake/fake_security_connector.cc", "src/core/lib/security/security_connector/load_system_roots_fallback.cc", @@ -1648,6 +1649,7 @@ grpc_cc_library( "src/core/lib/security/credentials/oauth2/oauth2_credentials.h", "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h", + "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h", "src/core/lib/security/security_connector/alts/alts_security_connector.h", "src/core/lib/security/security_connector/fake/fake_security_connector.h", "src/core/lib/security/security_connector/load_system_roots.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index a36d06a703c..9813eec7062 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1151,6 +1151,7 @@ add_library(grpc src/core/lib/security/credentials/oauth2/oauth2_credentials.cc src/core/lib/security/credentials/plugin/plugin_credentials.cc src/core/lib/security/credentials/ssl/ssl_credentials.cc + src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc src/core/lib/security/security_connector/alts/alts_security_connector.cc src/core/lib/security/security_connector/fake/fake_security_connector.cc src/core/lib/security/security_connector/load_system_roots_fallback.cc @@ -1609,6 +1610,7 @@ add_library(grpc_cronet src/core/lib/security/credentials/oauth2/oauth2_credentials.cc src/core/lib/security/credentials/plugin/plugin_credentials.cc src/core/lib/security/credentials/ssl/ssl_credentials.cc + src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc src/core/lib/security/security_connector/alts/alts_security_connector.cc src/core/lib/security/security_connector/fake/fake_security_connector.cc src/core/lib/security/security_connector/load_system_roots_fallback.cc diff --git a/Makefile b/Makefile index fd76e8b7d72..b9b7ab4c254 100644 --- a/Makefile +++ b/Makefile @@ -3672,6 +3672,7 @@ LIBGRPC_SRC = \ src/core/lib/security/credentials/oauth2/oauth2_credentials.cc \ src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ + src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ src/core/lib/security/security_connector/alts/alts_security_connector.cc \ src/core/lib/security/security_connector/fake/fake_security_connector.cc \ src/core/lib/security/security_connector/load_system_roots_fallback.cc \ @@ -4124,6 +4125,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/security/credentials/oauth2/oauth2_credentials.cc \ src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ + src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ src/core/lib/security/security_connector/alts/alts_security_connector.cc \ src/core/lib/security/security_connector/fake/fake_security_connector.cc \ src/core/lib/security/security_connector/load_system_roots_fallback.cc \ @@ -25370,6 +25372,7 @@ src/core/lib/security/credentials/local/local_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/oauth2/oauth2_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/plugin/plugin_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/ssl/ssl_credentials.cc: $(OPENSSL_DEP) +src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc: $(OPENSSL_DEP) src/core/lib/security/security_connector/alts/alts_security_connector.cc: $(OPENSSL_DEP) src/core/lib/security/security_connector/fake/fake_security_connector.cc: $(OPENSSL_DEP) src/core/lib/security/security_connector/load_system_roots_fallback.cc: $(OPENSSL_DEP) diff --git a/build.yaml b/build.yaml index 3afe4a3e9ce..0946e853d1b 100644 --- a/build.yaml +++ b/build.yaml @@ -837,6 +837,7 @@ filegroups: - src/core/lib/security/credentials/oauth2/oauth2_credentials.h - src/core/lib/security/credentials/plugin/plugin_credentials.h - src/core/lib/security/credentials/ssl/ssl_credentials.h + - src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h - src/core/lib/security/security_connector/alts/alts_security_connector.h - src/core/lib/security/security_connector/fake/fake_security_connector.h - src/core/lib/security/security_connector/load_system_roots.h @@ -869,6 +870,7 @@ filegroups: - src/core/lib/security/credentials/oauth2/oauth2_credentials.cc - src/core/lib/security/credentials/plugin/plugin_credentials.cc - src/core/lib/security/credentials/ssl/ssl_credentials.cc + - src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc - src/core/lib/security/security_connector/alts/alts_security_connector.cc - src/core/lib/security/security_connector/fake/fake_security_connector.cc - src/core/lib/security/security_connector/load_system_roots_fallback.cc diff --git a/config.m4 b/config.m4 index 46597e6f0e3..1874f3ba1b0 100644 --- a/config.m4 +++ b/config.m4 @@ -283,6 +283,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/security/credentials/oauth2/oauth2_credentials.cc \ src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ + src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ src/core/lib/security/security_connector/alts/alts_security_connector.cc \ src/core/lib/security/security_connector/fake/fake_security_connector.cc \ src/core/lib/security/security_connector/load_system_roots_fallback.cc \ @@ -728,6 +729,7 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/oauth2) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/plugin) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/ssl) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/tls) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/security_connector) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/security_connector/alts) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/security_connector/fake) diff --git a/config.w32 b/config.w32 index 00b92e88a05..452e8fd18b1 100644 --- a/config.w32 +++ b/config.w32 @@ -258,6 +258,7 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\security\\credentials\\oauth2\\oauth2_credentials.cc " + "src\\core\\lib\\security\\credentials\\plugin\\plugin_credentials.cc " + "src\\core\\lib\\security\\credentials\\ssl\\ssl_credentials.cc " + + "src\\core\\lib\\security\\credentials\\tls\\grpc_tls_credentials_options.cc " + "src\\core\\lib\\security\\security_connector\\alts\\alts_security_connector.cc " + "src\\core\\lib\\security\\security_connector\\fake\\fake_security_connector.cc " + "src\\core\\lib\\security\\security_connector\\load_system_roots_fallback.cc " + @@ -743,6 +744,7 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\oauth2"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\plugin"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\ssl"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\tls"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\security_connector"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\security_connector\\alts"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\security_connector\\fake"); diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index d0544011e6e..e1b1cf1564e 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -300,6 +300,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/oauth2/oauth2_credentials.h', 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', + 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', 'src/core/lib/security/security_connector/alts/alts_security_connector.h', 'src/core/lib/security/security_connector/fake/fake_security_connector.h', 'src/core/lib/security/security_connector/load_system_roots.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index a13612250fa..da48fe7e953 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -294,6 +294,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/oauth2/oauth2_credentials.h', 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', + 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', 'src/core/lib/security/security_connector/alts/alts_security_connector.h', 'src/core/lib/security/security_connector/fake/fake_security_connector.h', 'src/core/lib/security/security_connector/load_system_roots.h', @@ -731,6 +732,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc', 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc', + 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc', 'src/core/lib/security/security_connector/alts/alts_security_connector.cc', 'src/core/lib/security/security_connector/fake/fake_security_connector.cc', 'src/core/lib/security/security_connector/load_system_roots_fallback.cc', @@ -923,6 +925,7 @@ Pod::Spec.new do |s| 'src/core/lib/security/credentials/oauth2/oauth2_credentials.h', 'src/core/lib/security/credentials/plugin/plugin_credentials.h', 'src/core/lib/security/credentials/ssl/ssl_credentials.h', + 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h', 'src/core/lib/security/security_connector/alts/alts_security_connector.h', 'src/core/lib/security/security_connector/fake/fake_security_connector.h', 'src/core/lib/security/security_connector/load_system_roots.h', diff --git a/grpc.def b/grpc.def index b3466c004d8..59e29e0d168 100644 --- a/grpc.def +++ b/grpc.def @@ -131,6 +131,15 @@ EXPORTS grpc_alts_server_credentials_create grpc_local_credentials_create grpc_local_server_credentials_create + grpc_tls_credentials_options_create + grpc_tls_credentials_options_set_cert_request_type + grpc_tls_credentials_options_set_key_materials_config + grpc_tls_credentials_options_set_credential_reload_config + grpc_tls_credentials_options_set_server_authorization_check_config + grpc_tls_key_materials_config_create + grpc_tls_key_materials_config_set_key_materials + grpc_tls_credential_reload_config_create + grpc_tls_server_authorization_check_config_create grpc_raw_byte_buffer_create grpc_raw_compressed_byte_buffer_create grpc_byte_buffer_copy diff --git a/grpc.gemspec b/grpc.gemspec index 5cefb524333..9a3c657cc85 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -224,6 +224,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/security/credentials/oauth2/oauth2_credentials.h ) s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h ) + s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h ) s.files += %w( src/core/lib/security/security_connector/alts/alts_security_connector.h ) s.files += %w( src/core/lib/security/security_connector/fake/fake_security_connector.h ) s.files += %w( src/core/lib/security/security_connector/load_system_roots.h ) @@ -665,6 +666,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/security/credentials/oauth2/oauth2_credentials.cc ) s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.cc ) s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.cc ) + s.files += %w( src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc ) s.files += %w( src/core/lib/security/security_connector/alts/alts_security_connector.cc ) s.files += %w( src/core/lib/security/security_connector/fake/fake_security_connector.cc ) s.files += %w( src/core/lib/security/security_connector/load_system_roots_fallback.cc ) diff --git a/grpc.gyp b/grpc.gyp index b925d63fbdf..6a0a2718c8e 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -465,6 +465,7 @@ 'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc', 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc', + 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc', 'src/core/lib/security/security_connector/alts/alts_security_connector.cc', 'src/core/lib/security/security_connector/fake/fake_security_connector.cc', 'src/core/lib/security/security_connector/load_system_roots_fallback.cc', diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index de90971cc55..f0323eb16a1 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -609,6 +609,201 @@ GRPCAPI grpc_channel_credentials* grpc_local_credentials_create( GRPCAPI grpc_server_credentials* grpc_local_server_credentials_create( grpc_local_connect_type type); +/** --- SPIFFE and HTTPS-based TLS channel/server credentials --- + * It is used for experimental purpose for now and subject to change. */ + +/** Config for TLS key materials. It is used for + * experimental purpose for now and subject to change. */ +typedef struct grpc_tls_key_materials_config grpc_tls_key_materials_config; + +/** Config for TLS credential reload. It is used for + * experimental purpose for now and subject to change. */ +typedef struct grpc_tls_credential_reload_config + grpc_tls_credential_reload_config; + +/** Config for TLS server authorization check. It is used for + * experimental purpose for now and subject to change. */ +typedef struct grpc_tls_server_authorization_check_config + grpc_tls_server_authorization_check_config; + +/** TLS credentials options. It is used for + * experimental purpose for now and subject to change. */ +typedef struct grpc_tls_credentials_options grpc_tls_credentials_options; + +/** Create an empty TLS credentials options. It is used for + * experimental purpose for now and subject to change. */ +GRPCAPI grpc_tls_credentials_options* grpc_tls_credentials_options_create(); + +/** Set grpc_ssl_client_certificate_request_type field in credentials options + with the provided type. options should not be NULL. + It returns 1 on success and 0 on failure. It is used for + experimental purpose for now and subject to change. */ +GRPCAPI int grpc_tls_credentials_options_set_cert_request_type( + grpc_tls_credentials_options* options, + grpc_ssl_client_certificate_request_type type); + +/** Set grpc_tls_key_materials_config field in credentials options + with the provided config struct whose ownership is transferred. + Both parameters should not be NULL. + It returns 1 on success and 0 on failure. It is used for + experimental purpose for now and subject to change. */ +GRPCAPI int grpc_tls_credentials_options_set_key_materials_config( + grpc_tls_credentials_options* options, + grpc_tls_key_materials_config* config); + +/** Set grpc_tls_credential_reload_config field in credentials options + with the provided config struct whose ownership is transferred. + Both parameters should not be NULL. + It returns 1 on success and 0 on failure. It is used for + experimental purpose for now and subject to change. */ +GRPCAPI int grpc_tls_credentials_options_set_credential_reload_config( + grpc_tls_credentials_options* options, + grpc_tls_credential_reload_config* config); + +/** Set grpc_tls_server_authorization_check_config field in credentials options + with the provided config struct whose ownership is transferred. + Both parameters should not be NULL. + It returns 1 on success and 0 on failure. It is used for + experimental purpose for now and subject to change. */ +GRPCAPI int grpc_tls_credentials_options_set_server_authorization_check_config( + grpc_tls_credentials_options* options, + grpc_tls_server_authorization_check_config* config); + +/** --- TLS key materials config. --- + It is used for experimental purpose for now and subject to change. */ + +/** Create an empty grpc_tls_key_materials_config instance. + * It is used for experimental purpose for now and subject to change. */ +GRPCAPI grpc_tls_key_materials_config* grpc_tls_key_materials_config_create(); + +/** Set grpc_tls_key_materials_config instance with provided a TLS certificate. + config will take the ownership of pem_root_certs and pem_key_cert_pairs. + It's valid for the caller to provide nullptr pem_root_certs, in which case + the gRPC-provided root cert will be used. pem_key_cert_pairs should not be + NULL. It returns 1 on success and 0 on failure. It is used for + experimental purpose for now and subject to change. + */ +GRPCAPI int grpc_tls_key_materials_config_set_key_materials( + grpc_tls_key_materials_config* config, const char* pem_root_certs, + const grpc_ssl_pem_key_cert_pair** pem_key_cert_pairs, + size_t num_key_cert_pairs); + +/** --- TLS credential reload config. --- + It is used for experimental purpose for now and subject to change.*/ + +typedef struct grpc_tls_credential_reload_arg grpc_tls_credential_reload_arg; + +/** A callback function provided by gRPC to handle the result of credential + reload. It is used when schedule API is implemented asynchronously and + serves to bring the control back to grpc C core. It is used for + experimental purpose for now and subject to change. */ +typedef void (*grpc_tls_on_credential_reload_done_cb)( + grpc_tls_credential_reload_arg* arg); + +/** A struct containing all information necessary to schedule/cancel + a credential reload request. cb and cb_user_data represent a gRPC-provided + callback and an argument passed to it. key_materials is an in/output + parameter containing currently used/newly reloaded credentials. status and + error_details are used to hold information about errors occurred when a + credential reload request is scheduled/cancelled. It is used for + experimental purpose for now and subject to change. */ +struct grpc_tls_credential_reload_arg { + grpc_tls_on_credential_reload_done_cb cb; + void* cb_user_data; + grpc_tls_key_materials_config* key_materials_config; + grpc_status_code status; + const char* error_details; +}; + +/** Create a grpc_tls_credential_reload_config instance. + - config_user_data is config-specific, read-only user data + that works for all channels created with a credential using the config. + - schedule is a pointer to an application-provided callback used to invoke + credential reload API. The implementation of this method has to be + non-blocking, but can be performed synchronously or asynchronously. + 1) If processing occurs synchronously, it populates arg->key_materials, + arg->status, and arg->error_details and returns zero. + 2) If processing occurs asynchronously, it returns a non-zero value. + The application then invokes arg->cb when processing is completed. Note + that arg->cb cannot be invoked before schedule API returns. + - cancel is a pointer to an application-provided callback used to cancel + a credential reload request scheduled via an asynchronous schedule API. + arg is used to pinpoint an exact reloading request to be cancelled. + The operation may not have any effect if the request has already been + processed. + - destruct is a pointer to an application-provided callback used to clean up + any data associated with the config. + It is used for experimental purpose for now and subject to change. +*/ +GRPCAPI grpc_tls_credential_reload_config* +grpc_tls_credential_reload_config_create( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_credential_reload_arg* arg), + void (*cancel)(void* config_user_data, grpc_tls_credential_reload_arg* arg), + void (*destruct)(void* config_user_data)); + +/** --- TLS server authorization check config. --- + * It is used for experimental purpose for now and subject to change. */ + +typedef struct grpc_tls_server_authorization_check_arg + grpc_tls_server_authorization_check_arg; + +/** callback function provided by gRPC used to handle the result of server + authorization check. It is used when schedule API is implemented + asynchronously, and serves to bring the control back to gRPC C core. It is + used for experimental purpose for now and subject to change. */ +typedef void (*grpc_tls_on_server_authorization_check_done_cb)( + grpc_tls_server_authorization_check_arg* arg); + +/** A struct containing all information necessary to schedule/cancel a server + authorization check request. cb and cb_user_data represent a gRPC-provided + callback and an argument passed to it. result will store the result of + server authorization check. target_name is the name of an endpoint the + channel is connecting to and certificate represents a complete certificate + chain including both signing and leaf certificates. status and error_details + contain information about errors occurred when a server authorization check + request is scheduled/cancelled. It is used for experimental purpose for now + and subject to change.*/ +struct grpc_tls_server_authorization_check_arg { + grpc_tls_on_server_authorization_check_done_cb cb; + void* cb_user_data; + int result; + const char* target_name; + const char* peer_cert; + grpc_status_code status; + const char* error_details; +}; + +/** Create a grpc_tls_server_authorization_check_config instance. + - config_user_data is config-specific, read-only user data + that works for all channels created with a credential using the config. + - schedule is a pointer to an application-provided callback used to invoke + server authorization check API. The implementation of this method has to + be non-blocking, but can be performed synchronously or asynchronously. + 1)If processing occurs synchronously, it populates arg->result, + arg->status, and arg->error_details and returns zero. + 2) If processing occurs asynchronously, it returns a non-zero value. The + application then invokes arg->cb when processing is completed. Note that + arg->cb cannot be invoked before schedule API returns. + - cancel is a pointer to an application-provided callback used to cancel a + server authorization check request scheduled via an asynchronous schedule + API. arg is used to pinpoint an exact check request to be cancelled. The + operation may not have any effect if the request has already been + processed. + - destruct is a pointer to an application-provided callback used to clean up + any data associated with the config. + It is used for experimental purpose for now and subject to change. +*/ +GRPCAPI grpc_tls_server_authorization_check_config* +grpc_tls_server_authorization_check_config_create( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*cancel)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*destruct)(void* config_user_data)); + #ifdef __cplusplus } #endif diff --git a/package.xml b/package.xml index cb036c81daf..69b6fdfa671 100644 --- a/package.xml +++ b/package.xml @@ -229,6 +229,7 @@ + @@ -670,6 +671,7 @@ + diff --git a/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc b/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc new file mode 100644 index 00000000000..a6169a1b586 --- /dev/null +++ b/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc @@ -0,0 +1,192 @@ +/* + * + * 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 "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h" + +#include +#include + +#include +#include +#include + +/** -- gRPC TLS key materials config API implementation. -- **/ +void grpc_tls_key_materials_config::set_key_materials( + grpc_core::UniquePtr pem_root_certs, + PemKeyCertPairList pem_key_cert_pair_list) { + pem_key_cert_pair_list_ = std::move(pem_key_cert_pair_list); + pem_root_certs_ = std::move(pem_root_certs); +} + +/** -- gRPC TLS credential reload config API implementation. -- **/ +grpc_tls_credential_reload_config::grpc_tls_credential_reload_config( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_credential_reload_arg* arg), + void (*cancel)(void* config_user_data, grpc_tls_credential_reload_arg* arg), + void (*destruct)(void* config_user_data)) + : config_user_data_(const_cast(config_user_data)), + schedule_(schedule), + cancel_(cancel), + destruct_(destruct) {} + +grpc_tls_credential_reload_config::~grpc_tls_credential_reload_config() { + if (destruct_ != nullptr) { + destruct_((void*)config_user_data_); + } +} + +/** -- gRPC TLS server authorization check API implementation. -- **/ +grpc_tls_server_authorization_check_config:: + grpc_tls_server_authorization_check_config( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*cancel)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*destruct)(void* config_user_data)) + : config_user_data_(const_cast(config_user_data)), + schedule_(schedule), + cancel_(cancel), + destruct_(destruct) {} + +grpc_tls_server_authorization_check_config:: + ~grpc_tls_server_authorization_check_config() { + if (destruct_ != nullptr) { + destruct_((void*)config_user_data_); + } +} + +/** -- Wrapper APIs declared in grpc_security.h -- **/ +grpc_tls_credentials_options* grpc_tls_credentials_options_create() { + return grpc_core::New(); +} + +int grpc_tls_credentials_options_set_cert_request_type( + grpc_tls_credentials_options* options, + grpc_ssl_client_certificate_request_type type) { + if (options == nullptr) { + gpr_log(GPR_ERROR, + "Invalid nullptr arguments to " + "grpc_tls_credentials_options_set_cert_request_type()"); + return 0; + } + options->set_cert_request_type(type); + return 1; +} + +int grpc_tls_credentials_options_set_key_materials_config( + grpc_tls_credentials_options* options, + grpc_tls_key_materials_config* config) { + if (options == nullptr || config == nullptr) { + gpr_log(GPR_ERROR, + "Invalid nullptr arguments to " + "grpc_tls_credentials_options_set_key_materials_config()"); + return 0; + } + options->set_key_materials_config(config->Ref()); + return 1; +} + +int grpc_tls_credentials_options_set_credential_reload_config( + grpc_tls_credentials_options* options, + grpc_tls_credential_reload_config* config) { + if (options == nullptr || config == nullptr) { + gpr_log(GPR_ERROR, + "Invalid nullptr arguments to " + "grpc_tls_credentials_options_set_credential_reload_config()"); + return 0; + } + options->set_credential_reload_config(config->Ref()); + return 1; +} + +int grpc_tls_credentials_options_set_server_authorization_check_config( + grpc_tls_credentials_options* options, + grpc_tls_server_authorization_check_config* config) { + if (options == nullptr || config == nullptr) { + gpr_log( + GPR_ERROR, + "Invalid nullptr arguments to " + "grpc_tls_credentials_options_set_server_authorization_check_config()"); + return 0; + } + options->set_server_authorization_check_config(config->Ref()); + return 1; +} + +grpc_tls_key_materials_config* grpc_tls_key_materials_config_create() { + return grpc_core::New(); +} + +int grpc_tls_key_materials_config_set_key_materials( + grpc_tls_key_materials_config* config, const char* root_certs, + const grpc_ssl_pem_key_cert_pair** key_cert_pairs, size_t num) { + if (config == nullptr || key_cert_pairs == nullptr || num == 0) { + gpr_log(GPR_ERROR, + "Invalid arguments to " + "grpc_tls_key_materials_config_set_key_materials()"); + return 0; + } + grpc_core::UniquePtr pem_root(const_cast(root_certs)); + grpc_tls_key_materials_config::PemKeyCertPairList cert_pair_list; + for (size_t i = 0; i < num; i++) { + grpc_core::PemKeyCertPair key_cert_pair( + const_cast(key_cert_pairs[i])); + cert_pair_list.emplace_back(std::move(key_cert_pair)); + } + config->set_key_materials(std::move(pem_root), std::move(cert_pair_list)); + gpr_free(key_cert_pairs); + return 1; +} + +grpc_tls_credential_reload_config* grpc_tls_credential_reload_config_create( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_credential_reload_arg* arg), + void (*cancel)(void* config_user_data, grpc_tls_credential_reload_arg* arg), + void (*destruct)(void* config_user_data)) { + if (schedule == nullptr) { + gpr_log( + GPR_ERROR, + "Schedule API is nullptr in creating TLS credential reload config."); + return nullptr; + } + return grpc_core::New( + config_user_data, schedule, cancel, destruct); +} + +grpc_tls_server_authorization_check_config* +grpc_tls_server_authorization_check_config_create( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*cancel)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*destruct)(void* config_user_data)) { + if (schedule == nullptr) { + gpr_log(GPR_ERROR, + "Schedule API is nullptr in creating TLS server authorization " + "check config."); + return nullptr; + } + return grpc_core::New( + config_user_data, schedule, cancel, destruct); +} diff --git a/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h b/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h new file mode 100644 index 00000000000..71410d20a8f --- /dev/null +++ b/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h @@ -0,0 +1,213 @@ +/* + * + * 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. + * + */ + +#ifndef GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CREDENTIALS_OPTIONS_H +#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CREDENTIALS_OPTIONS_H + +#include + +#include + +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/security/security_connector/ssl_utils.h" + +/** TLS key materials config. **/ +struct grpc_tls_key_materials_config + : public grpc_core::RefCounted { + public: + typedef grpc_core::InlinedVector + PemKeyCertPairList; + + /** Getters for member fields. **/ + const char* pem_root_certs() const { return pem_root_certs_.get(); } + const PemKeyCertPairList& pem_key_cert_pair_list() const { + return pem_key_cert_pair_list_; + } + + /** Setters for member fields. **/ + void set_key_materials(grpc_core::UniquePtr pem_root_certs, + PemKeyCertPairList pem_key_cert_pair_list); + + private: + PemKeyCertPairList pem_key_cert_pair_list_; + grpc_core::UniquePtr pem_root_certs_; +}; + +/** TLS credential reload config. **/ +struct grpc_tls_credential_reload_config + : public grpc_core::RefCounted { + public: + grpc_tls_credential_reload_config( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_credential_reload_arg* arg), + void (*cancel)(void* config_user_data, + grpc_tls_credential_reload_arg* arg), + void (*destruct)(void* config_user_data)); + ~grpc_tls_credential_reload_config(); + + int Schedule(grpc_tls_credential_reload_arg* arg) const { + return schedule_(config_user_data_, arg); + } + void Cancel(grpc_tls_credential_reload_arg* arg) const { + if (cancel_ == nullptr) { + gpr_log(GPR_ERROR, "cancel API is nullptr."); + return; + } + cancel_(config_user_data_, arg); + } + + private: + /** config-specific, read-only user data that works for all channels created + with a credential using the config. */ + void* config_user_data_; + /** callback function for invoking credential reload API. The implementation + of this method has to be non-blocking, but can be performed synchronously + or asynchronously. + If processing occurs synchronously, it populates \a arg->key_materials, \a + arg->status, and \a arg->error_details and returns zero. + If processing occurs asynchronously, it returns a non-zero value. + Application then invokes \a arg->cb when processing is completed. Note that + \a arg->cb cannot be invoked before \a schedule returns. + */ + int (*schedule_)(void* config_user_data, grpc_tls_credential_reload_arg* arg); + /** callback function for cancelling a credential reload request scheduled via + an asynchronous \a schedule. \a arg is used to pinpoint an exact reloading + request to be cancelled, and the operation may not have any effect if the + request has already been processed. */ + void (*cancel_)(void* config_user_data, grpc_tls_credential_reload_arg* arg); + /** callback function for cleaning up any data associated with credential + reload config. */ + void (*destruct_)(void* config_user_data); +}; + +/** TLS server authorization check config. **/ +struct grpc_tls_server_authorization_check_config + : public grpc_core::RefCounted { + public: + grpc_tls_server_authorization_check_config( + const void* config_user_data, + int (*schedule)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*cancel)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg), + void (*destruct)(void* config_user_data)); + ~grpc_tls_server_authorization_check_config(); + + int Schedule(grpc_tls_server_authorization_check_arg* arg) const { + return schedule_(config_user_data_, arg); + } + void Cancel(grpc_tls_server_authorization_check_arg* arg) const { + if (cancel_ == nullptr) { + gpr_log(GPR_ERROR, "cancel API is nullptr."); + return; + } + cancel_(config_user_data_, arg); + } + + private: + /** config-specific, read-only user data that works for all channels created + with a Credential using the config. */ + void* config_user_data_; + + /** callback function for invoking server authorization check. The + implementation of this method has to be non-blocking, but can be performed + synchronously or asynchronously. + If processing occurs synchronously, it populates \a arg->result, \a + arg->status, and \a arg->error_details, and returns zero. + If processing occurs asynchronously, it returns a non-zero value. + Application then invokes \a arg->cb when processing is completed. Note that + \a arg->cb cannot be invoked before \a schedule() returns. + */ + int (*schedule_)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg); + + /** callback function for canceling a server authorization check request. */ + void (*cancel_)(void* config_user_data, + grpc_tls_server_authorization_check_arg* arg); + + /** callback function for cleaning up any data associated with server + authorization check config. */ + void (*destruct_)(void* config_user_data); +}; + +/* TLS credentials options. */ +struct grpc_tls_credentials_options + : public grpc_core::RefCounted { + public: + ~grpc_tls_credentials_options() { + if (key_materials_config_.get() != nullptr) { + key_materials_config_.get()->Unref(); + } + if (credential_reload_config_.get() != nullptr) { + credential_reload_config_.get()->Unref(); + } + if (server_authorization_check_config_.get() != nullptr) { + server_authorization_check_config_.get()->Unref(); + } + } + + /* Getters for member fields. */ + grpc_ssl_client_certificate_request_type cert_request_type() const { + return cert_request_type_; + } + const grpc_tls_key_materials_config* key_materials_config() const { + return key_materials_config_.get(); + } + const grpc_tls_credential_reload_config* credential_reload_config() const { + return credential_reload_config_.get(); + } + const grpc_tls_server_authorization_check_config* + server_authorization_check_config() const { + return server_authorization_check_config_.get(); + } + grpc_tls_key_materials_config* mutable_key_materials_config() { + return key_materials_config_.get(); + } + + /* Setters for member fields. */ + void set_cert_request_type( + const grpc_ssl_client_certificate_request_type type) { + cert_request_type_ = type; + } + void set_key_materials_config( + grpc_core::RefCountedPtr config) { + key_materials_config_ = std::move(config); + } + void set_credential_reload_config( + grpc_core::RefCountedPtr config) { + credential_reload_config_ = std::move(config); + } + void set_server_authorization_check_config( + grpc_core::RefCountedPtr + config) { + server_authorization_check_config_ = std::move(config); + } + + private: + grpc_ssl_client_certificate_request_type cert_request_type_; + grpc_core::RefCountedPtr key_materials_config_; + grpc_core::RefCountedPtr + credential_reload_config_; + grpc_core::RefCountedPtr + server_authorization_check_config_; +}; + +#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CREDENTIALS_OPTIONS_H \ + */ diff --git a/src/core/lib/security/security_connector/ssl_utils.h b/src/core/lib/security/security_connector/ssl_utils.h index c9cd1a1d9c5..972ca439dea 100644 --- a/src/core/lib/security/security_connector/ssl_utils.h +++ b/src/core/lib/security/security_connector/ssl_utils.h @@ -89,6 +89,39 @@ class DefaultSslRootStore { static grpc_slice default_pem_root_certs_; }; +class PemKeyCertPair { + public: + // Construct from the C struct. We steal its members and then immediately + // free it. + explicit PemKeyCertPair(grpc_ssl_pem_key_cert_pair* pair) + : private_key_(const_cast(pair->private_key)), + cert_chain_(const_cast(pair->cert_chain)) { + gpr_free(pair); + } + + // Movable. + PemKeyCertPair(PemKeyCertPair&& other) { + private_key_ = std::move(other.private_key_); + cert_chain_ = std::move(other.cert_chain_); + } + PemKeyCertPair& operator=(PemKeyCertPair&& other) { + private_key_ = std::move(other.private_key_); + cert_chain_ = std::move(other.cert_chain_); + return *this; + } + + // Not copyable. + PemKeyCertPair(const PemKeyCertPair&) = delete; + PemKeyCertPair& operator=(const PemKeyCertPair&) = delete; + + char* private_key() const { return private_key_.get(); } + char* cert_chain() const { return cert_chain_.get(); } + + private: + grpc_core::UniquePtr private_key_; + grpc_core::UniquePtr cert_chain_; +}; + } // namespace grpc_core #endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SSL_UTILS_H \ diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 0272aae690d..19d27412205 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -257,6 +257,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc', 'src/core/lib/security/credentials/plugin/plugin_credentials.cc', 'src/core/lib/security/credentials/ssl/ssl_credentials.cc', + 'src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc', 'src/core/lib/security/security_connector/alts/alts_security_connector.cc', 'src/core/lib/security/security_connector/fake/fake_security_connector.cc', 'src/core/lib/security/security_connector/load_system_roots_fallback.cc', diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 18245e91073..47250ec7141 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -154,6 +154,15 @@ grpc_alts_credentials_create_type grpc_alts_credentials_create_import; grpc_alts_server_credentials_create_type grpc_alts_server_credentials_create_import; grpc_local_credentials_create_type grpc_local_credentials_create_import; grpc_local_server_credentials_create_type grpc_local_server_credentials_create_import; +grpc_tls_credentials_options_create_type grpc_tls_credentials_options_create_import; +grpc_tls_credentials_options_set_cert_request_type_type grpc_tls_credentials_options_set_cert_request_type_import; +grpc_tls_credentials_options_set_key_materials_config_type grpc_tls_credentials_options_set_key_materials_config_import; +grpc_tls_credentials_options_set_credential_reload_config_type grpc_tls_credentials_options_set_credential_reload_config_import; +grpc_tls_credentials_options_set_server_authorization_check_config_type grpc_tls_credentials_options_set_server_authorization_check_config_import; +grpc_tls_key_materials_config_create_type grpc_tls_key_materials_config_create_import; +grpc_tls_key_materials_config_set_key_materials_type grpc_tls_key_materials_config_set_key_materials_import; +grpc_tls_credential_reload_config_create_type grpc_tls_credential_reload_config_create_import; +grpc_tls_server_authorization_check_config_create_type grpc_tls_server_authorization_check_config_create_import; grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import; grpc_raw_compressed_byte_buffer_create_type grpc_raw_compressed_byte_buffer_create_import; grpc_byte_buffer_copy_type grpc_byte_buffer_copy_import; @@ -412,6 +421,15 @@ void grpc_rb_load_imports(HMODULE library) { grpc_alts_server_credentials_create_import = (grpc_alts_server_credentials_create_type) GetProcAddress(library, "grpc_alts_server_credentials_create"); grpc_local_credentials_create_import = (grpc_local_credentials_create_type) GetProcAddress(library, "grpc_local_credentials_create"); grpc_local_server_credentials_create_import = (grpc_local_server_credentials_create_type) GetProcAddress(library, "grpc_local_server_credentials_create"); + grpc_tls_credentials_options_create_import = (grpc_tls_credentials_options_create_type) GetProcAddress(library, "grpc_tls_credentials_options_create"); + grpc_tls_credentials_options_set_cert_request_type_import = (grpc_tls_credentials_options_set_cert_request_type_type) GetProcAddress(library, "grpc_tls_credentials_options_set_cert_request_type"); + grpc_tls_credentials_options_set_key_materials_config_import = (grpc_tls_credentials_options_set_key_materials_config_type) GetProcAddress(library, "grpc_tls_credentials_options_set_key_materials_config"); + grpc_tls_credentials_options_set_credential_reload_config_import = (grpc_tls_credentials_options_set_credential_reload_config_type) GetProcAddress(library, "grpc_tls_credentials_options_set_credential_reload_config"); + grpc_tls_credentials_options_set_server_authorization_check_config_import = (grpc_tls_credentials_options_set_server_authorization_check_config_type) GetProcAddress(library, "grpc_tls_credentials_options_set_server_authorization_check_config"); + grpc_tls_key_materials_config_create_import = (grpc_tls_key_materials_config_create_type) GetProcAddress(library, "grpc_tls_key_materials_config_create"); + grpc_tls_key_materials_config_set_key_materials_import = (grpc_tls_key_materials_config_set_key_materials_type) GetProcAddress(library, "grpc_tls_key_materials_config_set_key_materials"); + grpc_tls_credential_reload_config_create_import = (grpc_tls_credential_reload_config_create_type) GetProcAddress(library, "grpc_tls_credential_reload_config_create"); + grpc_tls_server_authorization_check_config_create_import = (grpc_tls_server_authorization_check_config_create_type) GetProcAddress(library, "grpc_tls_server_authorization_check_config_create"); grpc_raw_byte_buffer_create_import = (grpc_raw_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_byte_buffer_create"); grpc_raw_compressed_byte_buffer_create_import = (grpc_raw_compressed_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_compressed_byte_buffer_create"); grpc_byte_buffer_copy_import = (grpc_byte_buffer_copy_type) GetProcAddress(library, "grpc_byte_buffer_copy"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index e61a35d09fa..9437f6d3918 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -437,6 +437,33 @@ extern grpc_local_credentials_create_type grpc_local_credentials_create_import; typedef grpc_server_credentials*(*grpc_local_server_credentials_create_type)(grpc_local_connect_type type); extern grpc_local_server_credentials_create_type grpc_local_server_credentials_create_import; #define grpc_local_server_credentials_create grpc_local_server_credentials_create_import +typedef grpc_tls_credentials_options*(*grpc_tls_credentials_options_create_type)(); +extern grpc_tls_credentials_options_create_type grpc_tls_credentials_options_create_import; +#define grpc_tls_credentials_options_create grpc_tls_credentials_options_create_import +typedef int(*grpc_tls_credentials_options_set_cert_request_type_type)(grpc_tls_credentials_options* options, grpc_ssl_client_certificate_request_type type); +extern grpc_tls_credentials_options_set_cert_request_type_type grpc_tls_credentials_options_set_cert_request_type_import; +#define grpc_tls_credentials_options_set_cert_request_type grpc_tls_credentials_options_set_cert_request_type_import +typedef int(*grpc_tls_credentials_options_set_key_materials_config_type)(grpc_tls_credentials_options* options, grpc_tls_key_materials_config* config); +extern grpc_tls_credentials_options_set_key_materials_config_type grpc_tls_credentials_options_set_key_materials_config_import; +#define grpc_tls_credentials_options_set_key_materials_config grpc_tls_credentials_options_set_key_materials_config_import +typedef int(*grpc_tls_credentials_options_set_credential_reload_config_type)(grpc_tls_credentials_options* options, grpc_tls_credential_reload_config* config); +extern grpc_tls_credentials_options_set_credential_reload_config_type grpc_tls_credentials_options_set_credential_reload_config_import; +#define grpc_tls_credentials_options_set_credential_reload_config grpc_tls_credentials_options_set_credential_reload_config_import +typedef int(*grpc_tls_credentials_options_set_server_authorization_check_config_type)(grpc_tls_credentials_options* options, grpc_tls_server_authorization_check_config* config); +extern grpc_tls_credentials_options_set_server_authorization_check_config_type grpc_tls_credentials_options_set_server_authorization_check_config_import; +#define grpc_tls_credentials_options_set_server_authorization_check_config grpc_tls_credentials_options_set_server_authorization_check_config_import +typedef grpc_tls_key_materials_config*(*grpc_tls_key_materials_config_create_type)(); +extern grpc_tls_key_materials_config_create_type grpc_tls_key_materials_config_create_import; +#define grpc_tls_key_materials_config_create grpc_tls_key_materials_config_create_import +typedef int(*grpc_tls_key_materials_config_set_key_materials_type)(grpc_tls_key_materials_config* config, const char* pem_root_certs, const grpc_ssl_pem_key_cert_pair** pem_key_cert_pairs, size_t num_key_cert_pairs); +extern grpc_tls_key_materials_config_set_key_materials_type grpc_tls_key_materials_config_set_key_materials_import; +#define grpc_tls_key_materials_config_set_key_materials grpc_tls_key_materials_config_set_key_materials_import +typedef grpc_tls_credential_reload_config*(*grpc_tls_credential_reload_config_create_type)(const void* config_user_data, int (*schedule)(void* config_user_data, grpc_tls_credential_reload_arg* arg), void (*cancel)(void* config_user_data, grpc_tls_credential_reload_arg* arg), void (*destruct)(void* config_user_data)); +extern grpc_tls_credential_reload_config_create_type grpc_tls_credential_reload_config_create_import; +#define grpc_tls_credential_reload_config_create grpc_tls_credential_reload_config_create_import +typedef grpc_tls_server_authorization_check_config*(*grpc_tls_server_authorization_check_config_create_type)(const void* config_user_data, int (*schedule)(void* config_user_data, grpc_tls_server_authorization_check_arg* arg), void (*cancel)(void* config_user_data, grpc_tls_server_authorization_check_arg* arg), void (*destruct)(void* config_user_data)); +extern grpc_tls_server_authorization_check_config_create_type grpc_tls_server_authorization_check_config_create_import; +#define grpc_tls_server_authorization_check_config_create grpc_tls_server_authorization_check_config_create_import typedef grpc_byte_buffer*(*grpc_raw_byte_buffer_create_type)(grpc_slice* slices, size_t nslices); extern grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import; #define grpc_raw_byte_buffer_create grpc_raw_byte_buffer_create_import diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 426ef1e8b13..1c9b67027c5 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -191,6 +191,15 @@ int main(int argc, char **argv) { printf("%lx", (unsigned long) grpc_alts_server_credentials_create); printf("%lx", (unsigned long) grpc_local_credentials_create); printf("%lx", (unsigned long) grpc_local_server_credentials_create); + printf("%lx", (unsigned long) grpc_tls_credentials_options_create); + printf("%lx", (unsigned long) grpc_tls_credentials_options_set_cert_request_type); + printf("%lx", (unsigned long) grpc_tls_credentials_options_set_key_materials_config); + printf("%lx", (unsigned long) grpc_tls_credentials_options_set_credential_reload_config); + printf("%lx", (unsigned long) grpc_tls_credentials_options_set_server_authorization_check_config); + printf("%lx", (unsigned long) grpc_tls_key_materials_config_create); + printf("%lx", (unsigned long) grpc_tls_key_materials_config_set_key_materials); + printf("%lx", (unsigned long) grpc_tls_credential_reload_config_create); + printf("%lx", (unsigned long) grpc_tls_server_authorization_check_config_create); printf("%lx", (unsigned long) grpc_raw_byte_buffer_create); printf("%lx", (unsigned long) grpc_raw_compressed_byte_buffer_create); printf("%lx", (unsigned long) grpc_byte_buffer_copy); diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 041c7382be5..2aced414218 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1384,6 +1384,8 @@ src/core/lib/security/credentials/plugin/plugin_credentials.cc \ src/core/lib/security/credentials/plugin/plugin_credentials.h \ src/core/lib/security/credentials/ssl/ssl_credentials.cc \ src/core/lib/security/credentials/ssl/ssl_credentials.h \ +src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc \ +src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h \ src/core/lib/security/security_connector/alts/alts_security_connector.cc \ src/core/lib/security/security_connector/alts/alts_security_connector.h \ src/core/lib/security/security_connector/fake/fake_security_connector.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index b5992c219d9..9e07c548b69 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -10381,6 +10381,7 @@ "src/core/lib/security/credentials/oauth2/oauth2_credentials.h", "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.h", + "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h", "src/core/lib/security/security_connector/alts/alts_security_connector.h", "src/core/lib/security/security_connector/fake/fake_security_connector.h", "src/core/lib/security/security_connector/load_system_roots.h", @@ -10434,6 +10435,8 @@ "src/core/lib/security/credentials/plugin/plugin_credentials.h", "src/core/lib/security/credentials/ssl/ssl_credentials.cc", "src/core/lib/security/credentials/ssl/ssl_credentials.h", + "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc", + "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h", "src/core/lib/security/security_connector/alts/alts_security_connector.cc", "src/core/lib/security/security_connector/alts/alts_security_connector.h", "src/core/lib/security/security_connector/fake/fake_security_connector.cc", From 8fb2f4abea2b16a9c813a7ab4d87c9fb5dd42ce8 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Tue, 29 Jan 2019 10:04:43 -0800 Subject: [PATCH 095/218] Fix a common typo --- .../grpcio_tests/tests/reflection/_reflection_servicer_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c0d0e7cf34e..37a66ad52bb 100644 --- a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py +++ b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py @@ -52,7 +52,7 @@ class ReflectionServicerTest(unittest.TestCase): # TODO(https://github.com/grpc/grpc/issues/17844) # Bazel + Python 3 will result in creating two different instance of - # DESCRIPTOR for each message. So, the equal comparision between protobuf + # DESCRIPTOR for each message. So, the equal comparison between protobuf # returned by stub and manually crafted protobuf will always fail. def _assert_sequence_of_proto_equal(self, x, y): self.assertSequenceEqual( From 80a0488d3398f6761f1a915f4204bb63893075d2 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Tue, 29 Jan 2019 10:29:14 -0800 Subject: [PATCH 096/218] Make declaration match definition --- test/cpp/interop/interop_client.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cpp/interop/interop_client.h b/test/cpp/interop/interop_client.h index 8644844d952..22df688468b 100644 --- a/test/cpp/interop/interop_client.h +++ b/test/cpp/interop/interop_client.h @@ -89,8 +89,8 @@ class InteropClient { const grpc::string& oauth_scope); // username is a string containing the user email bool DoPerRpcCreds(const grpc::string& json_key); - // username is the GCE default service account email - bool DoGoogleDefaultCredentials(const grpc::string& username); + // default_service_account is the GCE default service account email + bool DoGoogleDefaultCredentials(const grpc::string& default_service_account); private: class ServiceStub { From 1d8f7647b00403c826bd1c2fa95bfd3fd6470144 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Tue, 29 Jan 2019 10:43:06 -0800 Subject: [PATCH 097/218] Fix broken mac to prod interop --- .../internal_ci/macos/grpc_interop_toprod.sh | 3 +- tools/run_tests/run_interop_tests.py | 32 ++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/tools/internal_ci/macos/grpc_interop_toprod.sh b/tools/internal_ci/macos/grpc_interop_toprod.sh index d1ab54fe01e..daca88c5c51 100755 --- a/tools/internal_ci/macos/grpc_interop_toprod.sh +++ b/tools/internal_ci/macos/grpc_interop_toprod.sh @@ -30,7 +30,8 @@ export GRPC_DEFAULT_SSL_ROOTS_FILE_PATH="$(pwd)/etc/roots.pem" # building all languages in the same working copy can also lead to conflicts # due to different compilation flags tools/run_tests/run_interop_tests.py -l c++ \ - --cloud_to_prod --cloud_to_prod_auth --on_gce=false \ + --cloud_to_prod --cloud_to_prod_auth \ + --google_default_creds_use_key_file=true \ --prod_servers default gateway_v4 \ --service_account_key_file="${KOKORO_GFILE_DIR}/GrpcTesting-726eb1347f15.json" \ --skip_compute_engine_creds --internal_ci -t -j 4 || FAILED="true" diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index 782393be1aa..603977545ce 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -723,7 +723,10 @@ def compute_engine_creds_required(language, test_case): return False -def auth_options(language, test_case, on_gce, service_account_key_file=None): +def auth_options(language, + test_case, + google_default_creds_use_key_file, + service_account_key_file=None): """Returns (cmdline, env) tuple with cloud_to_prod_auth test options.""" language = str(language) @@ -757,7 +760,7 @@ def auth_options(language, test_case, on_gce, service_account_key_file=None): cmdargs += [oauth_scope_arg, default_account_arg] if test_case == _GOOGLE_DEFAULT_CREDS_TEST_CASE: - if not on_gce: + if google_default_creds_use_key_file: env['GOOGLE_APPLICATION_CREDENTIALS'] = service_account_key_file cmdargs += [default_account_arg] @@ -778,7 +781,7 @@ def cloud_to_prod_jobspec(language, test_case, server_host_nickname, server_host, - on_gce, + google_default_creds_use_key_file, docker_image=None, auth=False, manual_cmd_log=None, @@ -804,7 +807,8 @@ def cloud_to_prod_jobspec(language, cmdargs = cmdargs + transport_security_options environ = dict(language.cloud_to_prod_env(), **language.global_env()) if auth: - auth_cmdargs, auth_env = auth_options(language, test_case, on_gce, + auth_cmdargs, auth_env = auth_options(language, test_case, + google_default_creds_use_key_file, service_account_key_file) cmdargs += auth_cmdargs environ.update(auth_env) @@ -1083,11 +1087,13 @@ argp.add_argument( const=True, help='Run cloud_to_prod_auth tests.') argp.add_argument( - '--on_gce', - default=True, + '--google_default_creds_use_key_file', + default=False, action='store_const', const=True, - help='Whether or not this test script is running on GCE.') + help=('Whether or not we should use a key file for the ' + 'google_default_credentials test case, e.g. by ' + 'setting env var GOOGLE_APPLICATION_CREDENTIALS.')) argp.add_argument( '--prod_servers', choices=prod_servers.keys(), @@ -1343,7 +1349,8 @@ try: test_case, server_host_nickname, prod_servers[server_host_nickname], - on_gce=args.on_gce, + google_default_creds_use_key_file=args. + google_default_creds_use_key_file, docker_image=docker_images.get(str(language)), manual_cmd_log=client_manual_cmd_log, service_account_key_file=args. @@ -1358,7 +1365,8 @@ try: test_case, server_host_nickname, prod_servers[server_host_nickname], - on_gce=args.on_gce, + google_default_creds_use_key_file=args. + google_default_creds_use_key_file, docker_image=docker_images.get( str(language)), manual_cmd_log=client_manual_cmd_log, @@ -1375,7 +1383,8 @@ try: test_case, server_host_nickname, prod_servers[server_host_nickname], - on_gce=args.on_gce, + google_default_creds_use_key_file=args. + google_default_creds_use_key_file, docker_image=docker_images.get(str(http2Interop)), manual_cmd_log=client_manual_cmd_log, service_account_key_file=args.service_account_key_file, @@ -1402,7 +1411,8 @@ try: test_case, server_host_nickname, prod_servers[server_host_nickname], - on_gce=args.on_gce, + google_default_creds_use_key_file=args. + google_default_creds_use_key_file, docker_image=docker_images.get(str(language)), auth=True, manual_cmd_log=client_manual_cmd_log, From b9804c30feb7b8e24b63e0e62de7568163bc6143 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 29 Jan 2019 11:04:37 -0800 Subject: [PATCH 098/218] Only log data at TCP level if flag is DEBUG --- src/core/lib/iomgr/tcp_posix.cc | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index e0b999ecea9..792ffd27385 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -408,13 +408,15 @@ static void call_read_cb(grpc_tcp* tcp, grpc_error* error) { gpr_log(GPR_INFO, "TCP:%p call_cb %p %p:%p", tcp, cb, cb->cb, cb->cb_arg); size_t i; const char* str = grpc_error_string(error); - gpr_log(GPR_INFO, "read: error=%s", str); - - for (i = 0; i < tcp->incoming_buffer->count; i++) { - char* dump = grpc_dump_slice(tcp->incoming_buffer->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); + gpr_log(GPR_INFO, "READ %p (peer=%s) error=%s", tcp, tcp->peer_string, str); + + if (gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { + for (i = 0; i < tcp->incoming_buffer->count; i++) { + char* dump = grpc_dump_slice(tcp->incoming_buffer->slices[i], + GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, "DATA: %s", dump); + gpr_free(dump); + } } } @@ -976,10 +978,13 @@ static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf, size_t i; for (i = 0; i < buf->count; i++) { - char* data = - grpc_dump_slice(buf->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); + gpr_log(GPR_INFO, "WRITE %p (peer=%s)", tcp, tcp->peer_string); + if (gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { + char* data = + grpc_dump_slice(buf->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, "DATA: %s", data); + gpr_free(data); + } } } From bf0d1d6bfc934d61af93d6a4d9458dd41e6522ec Mon Sep 17 00:00:00 2001 From: = Date: Tue, 29 Jan 2019 11:34:36 -0800 Subject: [PATCH 099/218] Remove previous BindService implementation --- src/compiler/csharp_generator.cc | 39 +---------- src/csharp/Grpc.Core/ServiceBinderBase.cs | 64 ------------------- src/csharp/Grpc.Examples/MathGrpc.cs | 12 ---- src/csharp/Grpc.HealthCheck/HealthGrpc.cs | 10 --- .../BenchmarkServiceGrpc.cs | 13 ---- .../EmptyServiceGrpc.cs | 8 --- .../Grpc.IntegrationTesting/MetricsGrpc.cs | 10 --- .../ReportQpsScenarioServiceGrpc.cs | 9 --- .../Grpc.IntegrationTesting/TestGrpc.cs | 35 ---------- .../WorkerServiceGrpc.cs | 12 ---- src/csharp/Grpc.Reflection/ReflectionGrpc.cs | 9 --- 11 files changed, 1 insertion(+), 220 deletions(-) diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index c1eaf971483..14ee535d071 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -609,43 +609,7 @@ void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor* service) { out->Print("\n"); } -void GenerateBindServiceWithBinderMethod(Printer* out, - const ServiceDescriptor* service) { - out->Print( - "/// Register service method implementations with a service " - "binder. Useful when customizing the service binding logic.\n" - "/// Note: this method is part of an experimental API that can change or " - "be " - "removed without any prior notice.\n"); - out->Print( - "/// Service methods will be bound by " - "calling AddMethod on this object." - "\n"); - out->Print( - "/// An object implementing the server-side" - " handling logic.\n"); - out->Print( - "public static void BindService(grpc::ServiceBinderBase serviceBinder, " - "$implclass$ " - "serviceImpl)\n", - "implclass", GetServerClassName(service)); - out->Print("{\n"); - out->Indent(); - - for (int i = 0; i < service->method_count(); i++) { - const MethodDescriptor* method = service->method(i); - out->Print( - "serviceBinder.AddMethod($methodfield$, serviceImpl.$methodname$);\n", - "methodfield", GetMethodFieldName(method), "methodname", - method->name()); - } - - out->Outdent(); - out->Print("}\n"); - out->Print("\n"); -} - -void GenerateBindServiceWithBinderMethodWithoutImplementation( +void GenerateBindServiceWithBinderMethod( Printer* out, const ServiceDescriptor* service) { out->Print( "/// Register service method with a service " @@ -704,7 +668,6 @@ void GenerateService(Printer* out, const ServiceDescriptor* service, if (generate_server) { GenerateBindServiceMethod(out, service); GenerateBindServiceWithBinderMethod(out, service); - GenerateBindServiceWithBinderMethodWithoutImplementation(out, service); } out->Outdent(); diff --git a/src/csharp/Grpc.Core/ServiceBinderBase.cs b/src/csharp/Grpc.Core/ServiceBinderBase.cs index 79267d8f3d1..318892cc5fb 100644 --- a/src/csharp/Grpc.Core/ServiceBinderBase.cs +++ b/src/csharp/Grpc.Core/ServiceBinderBase.cs @@ -34,70 +34,6 @@ namespace Grpc.Core /// public class ServiceBinderBase { - /// - /// Adds a definition for a single request - single response method. - /// - /// The request message class. - /// The response message class. - /// The method. - /// The method handler. - public virtual void AddMethod( - Method method, - UnaryServerMethod handler) - where TRequest : class - where TResponse : class - { - throw new NotImplementedException(); - } - - /// - /// Adds a definition for a client streaming method. - /// - /// The request message class. - /// The response message class. - /// The method. - /// The method handler. - public virtual void AddMethod( - Method method, - ClientStreamingServerMethod handler) - where TRequest : class - where TResponse : class - { - throw new NotImplementedException(); - } - - /// - /// Adds a definition for a server streaming method. - /// - /// The request message class. - /// The response message class. - /// The method. - /// The method handler. - public virtual void AddMethod( - Method method, - ServerStreamingServerMethod handler) - where TRequest : class - where TResponse : class - { - throw new NotImplementedException(); - } - - /// - /// Adds a definition for a bidirectional streaming method. - /// - /// The request message class. - /// The response message class. - /// The method. - /// The method handler. - public virtual void AddMethod( - Method method, - DuplexStreamingServerMethod handler) - where TRequest : class - where TResponse : class - { - throw new NotImplementedException(); - } - /// /// Adds a method without a handler. /// diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index 717f3fab5ea..85436ddc232 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -287,18 +287,6 @@ namespace Math { .AddMethod(__Method_Sum, serviceImpl.Sum).Build(); } - /// Register service method implementations with a service binder. Useful when customizing the service binding logic. - /// Note: this method is part of an experimental API that can change or be removed without any prior notice. - /// Service methods will be bound by calling AddMethod on this object. - /// An object implementing the server-side handling logic. - public static void BindService(grpc::ServiceBinderBase serviceBinder, MathBase serviceImpl) - { - serviceBinder.AddMethod(__Method_Div, serviceImpl.Div); - serviceBinder.AddMethod(__Method_DivMany, serviceImpl.DivMany); - serviceBinder.AddMethod(__Method_Fib, serviceImpl.Fib); - serviceBinder.AddMethod(__Method_Sum, serviceImpl.Sum); - } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs index f7002328acd..5492600da9b 100644 --- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs +++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs @@ -233,16 +233,6 @@ namespace Grpc.Health.V1 { .AddMethod(__Method_Watch, serviceImpl.Watch).Build(); } - /// Register service method implementations with a service binder. Useful when customizing the service binding logic. - /// Note: this method is part of an experimental API that can change or be removed without any prior notice. - /// Service methods will be bound by calling AddMethod on this object. - /// An object implementing the server-side handling logic. - public static void BindService(grpc::ServiceBinderBase serviceBinder, HealthBase serviceImpl) - { - serviceBinder.AddMethod(__Method_Check, serviceImpl.Check); - serviceBinder.AddMethod(__Method_Watch, serviceImpl.Watch); - } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs index 39a48f2bb38..fcd0e3f89b3 100644 --- a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs @@ -324,19 +324,6 @@ namespace Grpc.Testing { .AddMethod(__Method_StreamingBothWays, serviceImpl.StreamingBothWays).Build(); } - /// Register service method implementations with a service binder. Useful when customizing the service binding logic. - /// Note: this method is part of an experimental API that can change or be removed without any prior notice. - /// Service methods will be bound by calling AddMethod on this object. - /// An object implementing the server-side handling logic. - public static void BindService(grpc::ServiceBinderBase serviceBinder, BenchmarkServiceBase serviceImpl) - { - serviceBinder.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall); - serviceBinder.AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall); - serviceBinder.AddMethod(__Method_StreamingFromClient, serviceImpl.StreamingFromClient); - serviceBinder.AddMethod(__Method_StreamingFromServer, serviceImpl.StreamingFromServer); - serviceBinder.AddMethod(__Method_StreamingBothWays, serviceImpl.StreamingBothWays); - } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. diff --git a/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs index 965d08d8a36..ba74c3a6016 100644 --- a/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs @@ -80,14 +80,6 @@ namespace Grpc.Testing { return grpc::ServerServiceDefinition.CreateBuilder().Build(); } - /// Register service method implementations with a service binder. Useful when customizing the service binding logic. - /// Note: this method is part of an experimental API that can change or be removed without any prior notice. - /// Service methods will be bound by calling AddMethod on this object. - /// An object implementing the server-side handling logic. - public static void BindService(grpc::ServiceBinderBase serviceBinder, EmptyServiceBase serviceImpl) - { - } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. diff --git a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs index 64db5b3ad08..bc6ddf21f70 100644 --- a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs @@ -193,16 +193,6 @@ namespace Grpc.Testing { .AddMethod(__Method_GetGauge, serviceImpl.GetGauge).Build(); } - /// Register service method implementations with a service binder. Useful when customizing the service binding logic. - /// Note: this method is part of an experimental API that can change or be removed without any prior notice. - /// Service methods will be bound by calling AddMethod on this object. - /// An object implementing the server-side handling logic. - public static void BindService(grpc::ServiceBinderBase serviceBinder, MetricsServiceBase serviceImpl) - { - serviceBinder.AddMethod(__Method_GetAllGauges, serviceImpl.GetAllGauges); - serviceBinder.AddMethod(__Method_GetGauge, serviceImpl.GetGauge); - } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. diff --git a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs index 81787892c32..096eb7e1d4b 100644 --- a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs @@ -143,15 +143,6 @@ namespace Grpc.Testing { .AddMethod(__Method_ReportScenario, serviceImpl.ReportScenario).Build(); } - /// Register service method implementations with a service binder. Useful when customizing the service binding logic. - /// Note: this method is part of an experimental API that can change or be removed without any prior notice. - /// Service methods will be bound by calling AddMethod on this object. - /// An object implementing the server-side handling logic. - public static void BindService(grpc::ServiceBinderBase serviceBinder, ReportQpsScenarioServiceBase serviceImpl) - { - serviceBinder.AddMethod(__Method_ReportScenario, serviceImpl.ReportScenario); - } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index 049cb65d7de..c8760583177 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -539,22 +539,6 @@ namespace Grpc.Testing { .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build(); } - /// Register service method implementations with a service binder. Useful when customizing the service binding logic. - /// Note: this method is part of an experimental API that can change or be removed without any prior notice. - /// Service methods will be bound by calling AddMethod on this object. - /// An object implementing the server-side handling logic. - public static void BindService(grpc::ServiceBinderBase serviceBinder, TestServiceBase serviceImpl) - { - serviceBinder.AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall); - serviceBinder.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall); - serviceBinder.AddMethod(__Method_CacheableUnaryCall, serviceImpl.CacheableUnaryCall); - serviceBinder.AddMethod(__Method_StreamingOutputCall, serviceImpl.StreamingOutputCall); - serviceBinder.AddMethod(__Method_StreamingInputCall, serviceImpl.StreamingInputCall); - serviceBinder.AddMethod(__Method_FullDuplexCall, serviceImpl.FullDuplexCall); - serviceBinder.AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall); - serviceBinder.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall); - } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. @@ -692,15 +676,6 @@ namespace Grpc.Testing { .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build(); } - /// Register service method implementations with a service binder. Useful when customizing the service binding logic. - /// Note: this method is part of an experimental API that can change or be removed without any prior notice. - /// Service methods will be bound by calling AddMethod on this object. - /// An object implementing the server-side handling logic. - public static void BindService(grpc::ServiceBinderBase serviceBinder, UnimplementedServiceBase serviceImpl) - { - serviceBinder.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall); - } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. @@ -827,16 +802,6 @@ namespace Grpc.Testing { .AddMethod(__Method_Stop, serviceImpl.Stop).Build(); } - /// Register service method implementations with a service binder. Useful when customizing the service binding logic. - /// Note: this method is part of an experimental API that can change or be removed without any prior notice. - /// Service methods will be bound by calling AddMethod on this object. - /// An object implementing the server-side handling logic. - public static void BindService(grpc::ServiceBinderBase serviceBinder, ReconnectServiceBase serviceImpl) - { - serviceBinder.AddMethod(__Method_Start, serviceImpl.Start); - serviceBinder.AddMethod(__Method_Stop, serviceImpl.Stop); - } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs index b58d71a784d..7b2a9e8d481 100644 --- a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs @@ -321,18 +321,6 @@ namespace Grpc.Testing { .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build(); } - /// Register service method implementations with a service binder. Useful when customizing the service binding logic. - /// Note: this method is part of an experimental API that can change or be removed without any prior notice. - /// Service methods will be bound by calling AddMethod on this object. - /// An object implementing the server-side handling logic. - public static void BindService(grpc::ServiceBinderBase serviceBinder, WorkerServiceBase serviceImpl) - { - serviceBinder.AddMethod(__Method_RunServer, serviceImpl.RunServer); - serviceBinder.AddMethod(__Method_RunClient, serviceImpl.RunClient); - serviceBinder.AddMethod(__Method_CoreCount, serviceImpl.CoreCount); - serviceBinder.AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker); - } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. diff --git a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs index 51ef8ace5cc..6c391361bc5 100644 --- a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs +++ b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs @@ -123,15 +123,6 @@ namespace Grpc.Reflection.V1Alpha { .AddMethod(__Method_ServerReflectionInfo, serviceImpl.ServerReflectionInfo).Build(); } - /// Register service method implementations with a service binder. Useful when customizing the service binding logic. - /// Note: this method is part of an experimental API that can change or be removed without any prior notice. - /// Service methods will be bound by calling AddMethod on this object. - /// An object implementing the server-side handling logic. - public static void BindService(grpc::ServiceBinderBase serviceBinder, ServerReflectionBase serviceImpl) - { - serviceBinder.AddMethod(__Method_ServerReflectionInfo, serviceImpl.ServerReflectionInfo); - } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. From 25dc2ffed69f62823bc1f8a19a22971cf53ab357 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Tue, 29 Jan 2019 11:21:51 -0800 Subject: [PATCH 100/218] C++-ify subchannel --- .../filters/client_channel/client_channel.cc | 114 +- .../filters/client_channel/client_channel.h | 4 +- .../client_channel/client_channel_channelz.cc | 11 +- .../client_channel/client_channel_channelz.h | 9 +- .../client_channel/client_channel_factory.cc | 2 +- .../client_channel/client_channel_factory.h | 6 +- .../client_channel/global_subchannel_pool.cc | 19 +- .../client_channel/global_subchannel_pool.h | 6 +- .../health/health_check_client.cc | 18 +- .../health/health_check_client.h | 2 +- .../lb_policy/pick_first/pick_first.cc | 2 +- .../lb_policy/round_robin/round_robin.cc | 2 +- .../lb_policy/subchannel_list.h | 37 +- .../client_channel/local_subchannel_pool.cc | 14 +- .../client_channel/local_subchannel_pool.h | 6 +- .../ext/filters/client_channel/subchannel.cc | 1436 ++++++++--------- .../ext/filters/client_channel/subchannel.h | 331 ++-- .../subchannel_pool_interface.h | 10 +- .../chttp2/client/chttp2_connector.cc | 3 +- .../chttp2/client/insecure/channel_create.cc | 4 +- .../client/secure/secure_channel_create.cc | 7 +- test/core/util/debugger_macros.cc | 5 +- test/cpp/microbenchmarks/bm_call_create.cc | 4 +- 23 files changed, 1025 insertions(+), 1027 deletions(-) diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 35c3efab6aa..38525dbf97e 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -394,7 +394,7 @@ struct subchannel_batch_data { gpr_refcount refs; grpc_call_element* elem; - grpc_subchannel_call* subchannel_call; // Holds a ref. + grpc_core::RefCountedPtr subchannel_call; // The batch to use in the subchannel call. // Its payload field points to subchannel_call_retry_state.batch_payload. grpc_transport_stream_op_batch batch; @@ -478,7 +478,7 @@ struct pending_batch { bool send_ops_cached; }; -/** Call data. Holds a pointer to grpc_subchannel_call and the +/** Call data. Holds a pointer to SubchannelCall and the associated machinery to create such a pointer. Handles queueing of stream ops until a call object is ready, waiting for initial metadata before trying to create a call object, @@ -504,10 +504,6 @@ struct call_data { last_attempt_got_server_pushback(false) {} ~call_data() { - if (GPR_LIKELY(subchannel_call != nullptr)) { - GRPC_SUBCHANNEL_CALL_UNREF(subchannel_call, - "client_channel_destroy_call"); - } grpc_slice_unref_internal(path); GRPC_ERROR_UNREF(cancel_error); for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches); ++i) { @@ -536,7 +532,7 @@ struct call_data { grpc_core::RefCountedPtr retry_throttle_data; grpc_core::RefCountedPtr method_params; - grpc_subchannel_call* subchannel_call = nullptr; + grpc_core::RefCountedPtr subchannel_call; // Set when we get a cancel_stream op. grpc_error* cancel_error = GRPC_ERROR_NONE; @@ -807,8 +803,8 @@ static void pending_batches_add(grpc_call_element* elem, calld->subchannel_call == nullptr ? nullptr : static_cast( - grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)); + + calld->subchannel_call->GetParentData()); retry_commit(elem, retry_state); // If we are not going to retry and have not yet started, pretend // retries are disabled so that we don't bother with retry overhead. @@ -896,10 +892,10 @@ static void resume_pending_batch_in_call_combiner(void* arg, grpc_error* ignored) { grpc_transport_stream_op_batch* batch = static_cast(arg); - grpc_subchannel_call* subchannel_call = - static_cast(batch->handler_private.extra_arg); + grpc_core::SubchannelCall* subchannel_call = + static_cast(batch->handler_private.extra_arg); // Note: This will release the call combiner. - grpc_subchannel_call_process_op(subchannel_call, batch); + subchannel_call->StartTransportStreamOpBatch(batch); } // This is called via the call combiner, so access to calld is synchronized. @@ -919,7 +915,7 @@ static void pending_batches_resume(grpc_call_element* elem) { gpr_log(GPR_INFO, "chand=%p calld=%p: starting %" PRIuPTR " pending batches on subchannel_call=%p", - chand, calld, num_batches, calld->subchannel_call); + chand, calld, num_batches, calld->subchannel_call.get()); } grpc_core::CallCombinerClosureList closures; for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) { @@ -930,7 +926,7 @@ static void pending_batches_resume(grpc_call_element* elem) { maybe_inject_recv_trailing_metadata_ready_for_lb( *calld->request->pick(), batch); } - batch->handler_private.extra_arg = calld->subchannel_call; + batch->handler_private.extra_arg = calld->subchannel_call.get(); GRPC_CLOSURE_INIT(&batch->handler_private.closure, resume_pending_batch_in_call_combiner, batch, grpc_schedule_on_exec_ctx); @@ -1019,12 +1015,7 @@ static void do_retry(grpc_call_element* elem, const ClientChannelMethodParams::RetryPolicy* retry_policy = calld->method_params->retry_policy(); GPR_ASSERT(retry_policy != nullptr); - // Reset subchannel call and connected subchannel. - if (calld->subchannel_call != nullptr) { - GRPC_SUBCHANNEL_CALL_UNREF(calld->subchannel_call, - "client_channel_call_retry"); - calld->subchannel_call = nullptr; - } + calld->subchannel_call.reset(); if (calld->have_request) { calld->have_request = false; calld->request.Destroy(); @@ -1078,8 +1069,7 @@ static bool maybe_retry(grpc_call_element* elem, subchannel_call_retry_state* retry_state = nullptr; if (batch_data != nullptr) { retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); if (retry_state->retry_dispatched) { if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: retry already dispatched", chand, @@ -1180,13 +1170,10 @@ namespace { subchannel_batch_data::subchannel_batch_data(grpc_call_element* elem, call_data* calld, int refcount, bool set_on_complete) - : elem(elem), - subchannel_call(GRPC_SUBCHANNEL_CALL_REF(calld->subchannel_call, - "batch_data_create")) { + : elem(elem), subchannel_call(calld->subchannel_call) { subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)); + calld->subchannel_call->GetParentData()); batch.payload = &retry_state->batch_payload; gpr_ref_init(&refs, refcount); if (set_on_complete) { @@ -1200,7 +1187,7 @@ subchannel_batch_data::subchannel_batch_data(grpc_call_element* elem, void subchannel_batch_data::destroy() { subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data(subchannel_call)); + subchannel_call->GetParentData()); if (batch.send_initial_metadata) { grpc_metadata_batch_destroy(&retry_state->send_initial_metadata); } @@ -1213,7 +1200,7 @@ void subchannel_batch_data::destroy() { if (batch.recv_trailing_metadata) { grpc_metadata_batch_destroy(&retry_state->recv_trailing_metadata); } - GRPC_SUBCHANNEL_CALL_UNREF(subchannel_call, "batch_data_unref"); + subchannel_call.reset(); call_data* calld = static_cast(elem->call_data); GRPC_CALL_STACK_UNREF(calld->owning_call, "batch_data"); } @@ -1260,8 +1247,7 @@ static void invoke_recv_initial_metadata_callback(void* arg, // Return metadata. subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); grpc_metadata_batch_move( &retry_state->recv_initial_metadata, pending->batch->payload->recv_initial_metadata.recv_initial_metadata); @@ -1293,8 +1279,7 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); retry_state->completed_recv_initial_metadata = true; // If a retry was already dispatched, then we're not going to use the // result of this recv_initial_metadata op, so do nothing. @@ -1355,8 +1340,7 @@ static void invoke_recv_message_callback(void* arg, grpc_error* error) { // Return payload. subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); *pending->batch->payload->recv_message.recv_message = std::move(retry_state->recv_message); // Update bookkeeping. @@ -1384,8 +1368,7 @@ static void recv_message_ready(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); ++retry_state->completed_recv_message_count; // If a retry was already dispatched, then we're not going to use the // result of this recv_message op, so do nothing. @@ -1473,8 +1456,7 @@ static void add_closure_for_recv_trailing_metadata_ready( // Return metadata. subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); grpc_metadata_batch_move( &retry_state->recv_trailing_metadata, pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata); @@ -1576,8 +1558,7 @@ static void run_closures_for_completed_call(subchannel_batch_data* batch_data, call_data* calld = static_cast(elem->call_data); subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); // Construct list of closures to execute. grpc_core::CallCombinerClosureList closures; // First, add closure for recv_trailing_metadata_ready. @@ -1611,8 +1592,7 @@ static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); retry_state->completed_recv_trailing_metadata = true; // Get the call's status and check for server pushback metadata. grpc_status_code status = GRPC_STATUS_OK; @@ -1735,8 +1715,7 @@ static void on_complete(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); // Update bookkeeping in retry_state. if (batch_data->batch.send_initial_metadata) { retry_state->completed_send_initial_metadata = true; @@ -1792,10 +1771,10 @@ static void on_complete(void* arg, grpc_error* error) { static void start_batch_in_call_combiner(void* arg, grpc_error* ignored) { grpc_transport_stream_op_batch* batch = static_cast(arg); - grpc_subchannel_call* subchannel_call = - static_cast(batch->handler_private.extra_arg); + grpc_core::SubchannelCall* subchannel_call = + static_cast(batch->handler_private.extra_arg); // Note: This will release the call combiner. - grpc_subchannel_call_process_op(subchannel_call, batch); + subchannel_call->StartTransportStreamOpBatch(batch); } // Adds a closure to closures that will execute batch in the call combiner. @@ -1804,7 +1783,7 @@ static void add_closure_for_subchannel_batch( grpc_core::CallCombinerClosureList* closures) { channel_data* chand = static_cast(elem->channel_data); call_data* calld = static_cast(elem->call_data); - batch->handler_private.extra_arg = calld->subchannel_call; + batch->handler_private.extra_arg = calld->subchannel_call.get(); GRPC_CLOSURE_INIT(&batch->handler_private.closure, start_batch_in_call_combiner, batch, grpc_schedule_on_exec_ctx); @@ -1978,8 +1957,7 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)); + calld->subchannel_call->GetParentData()); // Create batch_data with 2 refs, since this batch will be unreffed twice: // once for the recv_trailing_metadata_ready callback when the subchannel // batch returns, and again when we actually get a recv_trailing_metadata @@ -1989,7 +1967,7 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem) { add_retriable_recv_trailing_metadata_op(calld, retry_state, batch_data); retry_state->recv_trailing_metadata_internal_batch = batch_data; // Note: This will release the call combiner. - grpc_subchannel_call_process_op(calld->subchannel_call, &batch_data->batch); + calld->subchannel_call->StartTransportStreamOpBatch(&batch_data->batch); } // If there are any cached send ops that need to be replayed on the @@ -2196,8 +2174,7 @@ static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)); + calld->subchannel_call->GetParentData()); // Construct list of closures to execute, one for each pending batch. grpc_core::CallCombinerClosureList closures; // Replay previously-returned send_* ops if needed. @@ -2220,7 +2197,7 @@ static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored) { gpr_log(GPR_INFO, "chand=%p calld=%p: starting %" PRIuPTR " retriable batches on subchannel_call=%p", - chand, calld, closures.size(), calld->subchannel_call); + chand, calld, closures.size(), calld->subchannel_call.get()); } // Note: This will yield the call combiner. closures.RunClosures(calld->call_combiner); @@ -2245,22 +2222,22 @@ static void create_subchannel_call(grpc_call_element* elem, grpc_error* error) { calld->call_combiner, // call_combiner parent_data_size // parent_data_size }; - grpc_error* new_error = - calld->request->pick()->connected_subchannel->CreateCall( - call_args, &calld->subchannel_call); + grpc_error* new_error = GRPC_ERROR_NONE; + calld->subchannel_call = + calld->request->pick()->connected_subchannel->CreateCall(call_args, + &new_error); if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: create subchannel_call=%p: error=%s", - chand, calld, calld->subchannel_call, grpc_error_string(new_error)); + chand, calld, calld->subchannel_call.get(), + grpc_error_string(new_error)); } if (GPR_UNLIKELY(new_error != GRPC_ERROR_NONE)) { new_error = grpc_error_add_child(new_error, error); pending_batches_fail(elem, new_error, true /* yield_call_combiner */); } else { if (parent_data_size > 0) { - new (grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)) - subchannel_call_retry_state( - calld->request->pick()->subchannel_call_context); + new (calld->subchannel_call->GetParentData()) subchannel_call_retry_state( + calld->request->pick()->subchannel_call_context); } pending_batches_resume(elem); } @@ -2488,7 +2465,7 @@ static void cc_start_transport_stream_op_batch( batch, GRPC_ERROR_REF(calld->cancel_error), calld->call_combiner); } else { // Note: This will release the call combiner. - grpc_subchannel_call_process_op(calld->subchannel_call, batch); + calld->subchannel_call->StartTransportStreamOpBatch(batch); } return; } @@ -2502,7 +2479,7 @@ static void cc_start_transport_stream_op_batch( if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: starting batch on subchannel_call=%p", chand, - calld, calld->subchannel_call); + calld, calld->subchannel_call.get()); } pending_batches_resume(elem); return; @@ -2545,8 +2522,7 @@ static void cc_destroy_call_elem(grpc_call_element* elem, grpc_closure* then_schedule_closure) { call_data* calld = static_cast(elem->call_data); if (GPR_LIKELY(calld->subchannel_call != nullptr)) { - grpc_subchannel_call_set_cleanup_closure(calld->subchannel_call, - then_schedule_closure); + calld->subchannel_call->SetAfterCallStackDestroy(then_schedule_closure); then_schedule_closure = nullptr; } calld->~call_data(); @@ -2752,8 +2728,8 @@ void grpc_client_channel_watch_connectivity_state( GRPC_ERROR_NONE); } -grpc_subchannel_call* grpc_client_channel_get_subchannel_call( - grpc_call_element* elem) { +grpc_core::RefCountedPtr +grpc_client_channel_get_subchannel_call(grpc_call_element* elem) { call_data* calld = static_cast(elem->call_data); return calld->subchannel_call; } diff --git a/src/core/ext/filters/client_channel/client_channel.h b/src/core/ext/filters/client_channel/client_channel.h index 4935fd24d87..5bfff4df9cd 100644 --- a/src/core/ext/filters/client_channel/client_channel.h +++ b/src/core/ext/filters/client_channel/client_channel.h @@ -60,7 +60,7 @@ void grpc_client_channel_watch_connectivity_state( grpc_closure* watcher_timer_init); /* Debug helper: pull the subchannel call from a call stack element */ -grpc_subchannel_call* grpc_client_channel_get_subchannel_call( - grpc_call_element* elem); +grpc_core::RefCountedPtr +grpc_client_channel_get_subchannel_call(grpc_call_element* elem); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H */ diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 8e5426081c4..76c5a786240 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -113,12 +113,11 @@ RefCountedPtr ClientChannelNode::MakeClientChannelNode( is_top_level_channel); } -SubchannelNode::SubchannelNode(grpc_subchannel* subchannel, +SubchannelNode::SubchannelNode(Subchannel* subchannel, size_t channel_tracer_max_nodes) : BaseNode(EntityType::kSubchannel), subchannel_(subchannel), - target_( - UniquePtr(gpr_strdup(grpc_subchannel_get_target(subchannel_)))), + target_(UniquePtr(gpr_strdup(subchannel_->GetTargetAddress()))), trace_(channel_tracer_max_nodes) {} SubchannelNode::~SubchannelNode() {} @@ -128,8 +127,8 @@ void SubchannelNode::PopulateConnectivityState(grpc_json* json) { if (subchannel_ == nullptr) { state = GRPC_CHANNEL_SHUTDOWN; } else { - state = grpc_subchannel_check_connectivity( - subchannel_, nullptr, true /* inhibit_health_checking */); + state = subchannel_->CheckConnectivity(nullptr, + true /* inhibit_health_checking */); } json = grpc_json_create_child(nullptr, json, "state", nullptr, GRPC_JSON_OBJECT, false); @@ -170,7 +169,7 @@ grpc_json* SubchannelNode::RenderJson() { call_counter_.PopulateCallCounts(json); json = top_level_json; // populate the child socket. - intptr_t socket_uuid = grpc_subchannel_get_child_socket_uuid(subchannel_); + intptr_t socket_uuid = subchannel_->GetChildSocketUuid(); if (socket_uuid != 0) { grpc_json* array_parent = grpc_json_create_child( nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index 8a5c3e7e5e5..1dc1bf595be 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -26,9 +26,10 @@ #include "src/core/lib/channel/channel_trace.h" #include "src/core/lib/channel/channelz.h" -typedef struct grpc_subchannel grpc_subchannel; - namespace grpc_core { + +class Subchannel; + namespace channelz { // Subtype of ChannelNode that overrides and provides client_channel specific @@ -59,7 +60,7 @@ class ClientChannelNode : public ChannelNode { // Handles channelz bookkeeping for sockets class SubchannelNode : public BaseNode { public: - SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes); + SubchannelNode(Subchannel* subchannel, size_t channel_tracer_max_nodes); ~SubchannelNode() override; void MarkSubchannelDestroyed() { @@ -84,7 +85,7 @@ class SubchannelNode : public BaseNode { void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } private: - grpc_subchannel* subchannel_; + Subchannel* subchannel_; UniquePtr target_; CallCountingHelper call_counter_; ChannelTrace trace_; 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 130bbe04180..8c558382fdf 100644 --- a/src/core/ext/filters/client_channel/client_channel_factory.cc +++ b/src/core/ext/filters/client_channel/client_channel_factory.cc @@ -29,7 +29,7 @@ void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory) { factory->vtable->unref(factory); } -grpc_subchannel* grpc_client_channel_factory_create_subchannel( +grpc_core::Subchannel* grpc_client_channel_factory_create_subchannel( 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 91dec12282f..4b72aa46499 100644 --- a/src/core/ext/filters/client_channel/client_channel_factory.h +++ b/src/core/ext/filters/client_channel/client_channel_factory.h @@ -48,8 +48,8 @@ struct grpc_client_channel_factory { 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_channel_args* args); + grpc_core::Subchannel* (*create_subchannel)( + grpc_client_channel_factory* factory, const grpc_channel_args* args); grpc_channel* (*create_client_channel)(grpc_client_channel_factory* factory, const char* target, grpc_client_channel_type type, @@ -60,7 +60,7 @@ void grpc_client_channel_factory_ref(grpc_client_channel_factory* factory); 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_core::Subchannel* grpc_client_channel_factory_create_subchannel( grpc_client_channel_factory* factory, const grpc_channel_args* args); /** Create a new grpc_channel */ diff --git a/src/core/ext/filters/client_channel/global_subchannel_pool.cc b/src/core/ext/filters/client_channel/global_subchannel_pool.cc index a41d993fe66..ee6e58159a0 100644 --- a/src/core/ext/filters/client_channel/global_subchannel_pool.cc +++ b/src/core/ext/filters/client_channel/global_subchannel_pool.cc @@ -54,9 +54,9 @@ RefCountedPtr GlobalSubchannelPool::instance() { return *instance_; } -grpc_subchannel* GlobalSubchannelPool::RegisterSubchannel( - SubchannelKey* key, grpc_subchannel* constructed) { - grpc_subchannel* c = nullptr; +Subchannel* GlobalSubchannelPool::RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) { + Subchannel* c = nullptr; // Compare and swap (CAS) loop: while (c == nullptr) { // Ref the shared map to have a local copy. @@ -64,7 +64,7 @@ grpc_subchannel* GlobalSubchannelPool::RegisterSubchannel( grpc_avl old_map = grpc_avl_ref(subchannel_map_, nullptr); gpr_mu_unlock(&mu_); // Check to see if a subchannel already exists. - c = static_cast(grpc_avl_get(old_map, key, nullptr)); + c = static_cast(grpc_avl_get(old_map, key, nullptr)); if (c != nullptr) { // The subchannel already exists. Reuse it. c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "subchannel_register+reuse"); @@ -121,15 +121,14 @@ void GlobalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) { } } -grpc_subchannel* GlobalSubchannelPool::FindSubchannel(SubchannelKey* key) { +Subchannel* GlobalSubchannelPool::FindSubchannel(SubchannelKey* key) { // Lock, and take a reference to the subchannel map. // We don't need to do the search under a lock as AVL's are immutable. gpr_mu_lock(&mu_); grpc_avl index = grpc_avl_ref(subchannel_map_, nullptr); gpr_mu_unlock(&mu_); - grpc_subchannel* c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF( - static_cast(grpc_avl_get(index, key, nullptr)), - "found_from_pool"); + Subchannel* c = static_cast(grpc_avl_get(index, key, nullptr)); + if (c != nullptr) GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "found_from_pool"); grpc_avl_unref(index, nullptr); return c; } @@ -156,11 +155,11 @@ long sck_avl_compare(void* a, void* b, void* unused) { } void scv_avl_destroy(void* p, void* user_data) { - GRPC_SUBCHANNEL_WEAK_UNREF((grpc_subchannel*)p, "global_subchannel_pool"); + GRPC_SUBCHANNEL_WEAK_UNREF((Subchannel*)p, "global_subchannel_pool"); } void* scv_avl_copy(void* p, void* unused) { - GRPC_SUBCHANNEL_WEAK_REF((grpc_subchannel*)p, "global_subchannel_pool"); + GRPC_SUBCHANNEL_WEAK_REF((Subchannel*)p, "global_subchannel_pool"); return p; } diff --git a/src/core/ext/filters/client_channel/global_subchannel_pool.h b/src/core/ext/filters/client_channel/global_subchannel_pool.h index 0deb3769360..96dc8d7b3a4 100644 --- a/src/core/ext/filters/client_channel/global_subchannel_pool.h +++ b/src/core/ext/filters/client_channel/global_subchannel_pool.h @@ -45,10 +45,10 @@ class GlobalSubchannelPool final : public SubchannelPoolInterface { static RefCountedPtr instance(); // Implements interface methods. - grpc_subchannel* RegisterSubchannel(SubchannelKey* key, - grpc_subchannel* constructed) override; + Subchannel* RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) override; void UnregisterSubchannel(SubchannelKey* key) override; - grpc_subchannel* FindSubchannel(SubchannelKey* key) override; + Subchannel* FindSubchannel(SubchannelKey* key) override; private: // The singleton instance. (It's a pointer to RefCountedPtr so that this diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc index 2232c57120e..e845d63d295 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -295,7 +295,9 @@ HealthCheckClient::CallState::~CallState() { gpr_log(GPR_INFO, "HealthCheckClient %p: destroying CallState %p", health_check_client_.get(), this); } - if (call_ != nullptr) GRPC_SUBCHANNEL_CALL_UNREF(call_, "call_ended"); + // The subchannel call is in the arena, so reset the pointer before we destroy + // the arena. + call_.reset(); for (size_t i = 0; i < GRPC_CONTEXT_COUNT; i++) { if (context_[i].destroy != nullptr) { context_[i].destroy(context_[i].value); @@ -329,8 +331,8 @@ void HealthCheckClient::CallState::StartCall() { &call_combiner_, 0, // parent_data_size }; - grpc_error* error = - health_check_client_->connected_subchannel_->CreateCall(args, &call_); + grpc_error* error = GRPC_ERROR_NONE; + call_ = health_check_client_->connected_subchannel_->CreateCall(args, &error); if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "HealthCheckClient %p CallState %p: error creating health " @@ -423,14 +425,14 @@ void HealthCheckClient::CallState::StartBatchInCallCombiner(void* arg, grpc_error* error) { grpc_transport_stream_op_batch* batch = static_cast(arg); - grpc_subchannel_call* call = - static_cast(batch->handler_private.extra_arg); - grpc_subchannel_call_process_op(call, batch); + SubchannelCall* call = + static_cast(batch->handler_private.extra_arg); + call->StartTransportStreamOpBatch(batch); } void HealthCheckClient::CallState::StartBatch( grpc_transport_stream_op_batch* batch) { - batch->handler_private.extra_arg = call_; + batch->handler_private.extra_arg = call_.get(); GRPC_CLOSURE_INIT(&batch->handler_private.closure, StartBatchInCallCombiner, batch, grpc_schedule_on_exec_ctx); GRPC_CALL_COMBINER_START(&call_combiner_, &batch->handler_private.closure, @@ -452,7 +454,7 @@ void HealthCheckClient::CallState::StartCancel(void* arg, grpc_error* error) { GRPC_CLOSURE_CREATE(OnCancelComplete, self, grpc_schedule_on_exec_ctx)); batch->cancel_stream = true; batch->payload->cancel_stream.cancel_error = GRPC_ERROR_CANCELLED; - grpc_subchannel_call_process_op(self->call_, batch); + self->call_->StartTransportStreamOpBatch(batch); } void HealthCheckClient::CallState::Cancel() { diff --git a/src/core/ext/filters/client_channel/health/health_check_client.h b/src/core/ext/filters/client_channel/health/health_check_client.h index 2369b73feac..7af88a54cfc 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.h +++ b/src/core/ext/filters/client_channel/health/health_check_client.h @@ -99,7 +99,7 @@ class HealthCheckClient : public InternallyRefCounted { grpc_call_context_element context_[GRPC_CONTEXT_COUNT] = {}; // The streaming call to the backend. Always non-NULL. - grpc_subchannel_call* call_; + RefCountedPtr call_; grpc_transport_stream_op_batch_payload payload_; grpc_transport_stream_op_batch batch_; diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index ec5c782c469..dc716a6adac 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -79,7 +79,7 @@ class PickFirst : public LoadBalancingPolicy { PickFirstSubchannelData( SubchannelList* subchannel_list, - const ServerAddress& address, grpc_subchannel* subchannel, + const ServerAddress& address, Subchannel* subchannel, grpc_combiner* combiner) : SubchannelData(subchannel_list, address, subchannel, combiner) {} diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index 30316689ea7..aab6dd68216 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -94,7 +94,7 @@ class RoundRobin : public LoadBalancingPolicy { RoundRobinSubchannelData( SubchannelList* subchannel_list, - const ServerAddress& address, grpc_subchannel* subchannel, + const ServerAddress& address, Subchannel* subchannel, grpc_combiner* combiner) : SubchannelData(subchannel_list, address, subchannel, combiner) {} 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 2eb92b7ead0..0174a98a73d 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 @@ -88,7 +88,7 @@ class SubchannelData { } // Returns a pointer to the subchannel. - grpc_subchannel* subchannel() const { return subchannel_; } + Subchannel* subchannel() const { return subchannel_; } // Returns the connected subchannel. Will be null if the subchannel // is not connected. @@ -103,8 +103,8 @@ class SubchannelData { // ProcessConnectivityChangeLocked()). grpc_connectivity_state CheckConnectivityStateLocked(grpc_error** error) { GPR_ASSERT(!connectivity_notification_pending_); - pending_connectivity_state_unsafe_ = grpc_subchannel_check_connectivity( - subchannel(), error, subchannel_list_->inhibit_health_checking()); + pending_connectivity_state_unsafe_ = subchannel()->CheckConnectivity( + error, subchannel_list_->inhibit_health_checking()); UpdateConnectedSubchannelLocked(); return pending_connectivity_state_unsafe_; } @@ -142,7 +142,7 @@ class SubchannelData { protected: SubchannelData( SubchannelList* subchannel_list, - const ServerAddress& address, grpc_subchannel* subchannel, + const ServerAddress& address, Subchannel* subchannel, grpc_combiner* combiner); virtual ~SubchannelData(); @@ -170,7 +170,7 @@ class SubchannelData { SubchannelList* subchannel_list_; // The subchannel and connected subchannel. - grpc_subchannel* subchannel_; + Subchannel* subchannel_; RefCountedPtr connected_subchannel_; // Notification that connectivity has changed on subchannel. @@ -203,7 +203,7 @@ class SubchannelList : public InternallyRefCounted { for (size_t i = 0; i < subchannels_.size(); ++i) { if (subchannels_[i].subchannel() != nullptr) { grpc_core::channelz::SubchannelNode* subchannel_node = - grpc_subchannel_get_channelz_node(subchannels_[i].subchannel()); + subchannels_[i].subchannel()->channelz_node(); if (subchannel_node != nullptr) { refs_list->push_back(subchannel_node->uuid()); } @@ -276,7 +276,7 @@ class SubchannelList : public InternallyRefCounted { template SubchannelData::SubchannelData( SubchannelList* subchannel_list, - const ServerAddress& address, grpc_subchannel* subchannel, + const ServerAddress& address, Subchannel* subchannel, grpc_combiner* combiner) : subchannel_list_(subchannel_list), subchannel_(subchannel), @@ -317,7 +317,7 @@ template void SubchannelData::ResetBackoffLocked() { if (subchannel_ != nullptr) { - grpc_subchannel_reset_backoff(subchannel_); + subchannel_->ResetBackoff(); } } @@ -337,8 +337,8 @@ void SubchannelDataRef(DEBUG_LOCATION, "connectivity_watch").release(); - grpc_subchannel_notify_on_state_change( - subchannel_, subchannel_list_->policy()->interested_parties(), + subchannel_->NotifyOnStateChange( + subchannel_list_->policy()->interested_parties(), &pending_connectivity_state_unsafe_, &connectivity_changed_closure_, subchannel_list_->inhibit_health_checking()); } @@ -357,8 +357,8 @@ void SubchannelDatapolicy()->interested_parties(), + subchannel_->NotifyOnStateChange( + subchannel_list_->policy()->interested_parties(), &pending_connectivity_state_unsafe_, &connectivity_changed_closure_, subchannel_list_->inhibit_health_checking()); } @@ -391,9 +391,9 @@ void SubchannelData:: subchannel_, reason); } GPR_ASSERT(connectivity_notification_pending_); - grpc_subchannel_notify_on_state_change( - subchannel_, nullptr, nullptr, &connectivity_changed_closure_, - subchannel_list_->inhibit_health_checking()); + subchannel_->NotifyOnStateChange(nullptr, nullptr, + &connectivity_changed_closure_, + subchannel_list_->inhibit_health_checking()); } template @@ -401,8 +401,7 @@ bool SubchannelData::UpdateConnectedSubchannelLocked() { // If the subchannel is READY, take a ref to the connected subchannel. if (pending_connectivity_state_unsafe_ == GRPC_CHANNEL_READY) { - connected_subchannel_ = - grpc_subchannel_get_connected_subchannel(subchannel_); + connected_subchannel_ = subchannel_->connected_subchannel(); // If the subchannel became disconnected between the time that READY // was reported and the time we got here (e.g., between when a // notification callback is scheduled and when it was actually run in @@ -518,7 +517,7 @@ SubchannelList::SubchannelList( SubchannelPoolInterface::CreateChannelArg(policy_->subchannel_pool())); const size_t subchannel_address_arg_index = args_to_add.size(); args_to_add.emplace_back( - grpc_create_subchannel_address_arg(&addresses[i].address())); + Subchannel::CreateSubchannelAddressArg(&addresses[i].address())); if (addresses[i].args() != nullptr) { for (size_t j = 0; j < addresses[i].args()->num_args; ++j) { args_to_add.emplace_back(addresses[i].args()->args[j]); @@ -528,7 +527,7 @@ 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[subchannel_address_arg_index].value.string); - grpc_subchannel* subchannel = grpc_client_channel_factory_create_subchannel( + Subchannel* subchannel = grpc_client_channel_factory_create_subchannel( client_channel_factory, new_args); grpc_channel_args_destroy(new_args); if (subchannel == nullptr) { diff --git a/src/core/ext/filters/client_channel/local_subchannel_pool.cc b/src/core/ext/filters/client_channel/local_subchannel_pool.cc index 145fa4e0374..d1c1cacb441 100644 --- a/src/core/ext/filters/client_channel/local_subchannel_pool.cc +++ b/src/core/ext/filters/client_channel/local_subchannel_pool.cc @@ -32,11 +32,11 @@ LocalSubchannelPool::~LocalSubchannelPool() { grpc_avl_unref(subchannel_map_, nullptr); } -grpc_subchannel* LocalSubchannelPool::RegisterSubchannel( - SubchannelKey* key, grpc_subchannel* constructed) { +Subchannel* LocalSubchannelPool::RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) { // Check to see if a subchannel already exists. - grpc_subchannel* c = static_cast( - grpc_avl_get(subchannel_map_, key, nullptr)); + Subchannel* c = + static_cast(grpc_avl_get(subchannel_map_, key, nullptr)); if (c != nullptr) { // The subchannel already exists. Reuse it. c = GRPC_SUBCHANNEL_REF(c, "subchannel_register+reuse"); @@ -54,9 +54,9 @@ void LocalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) { subchannel_map_ = grpc_avl_remove(subchannel_map_, key, nullptr); } -grpc_subchannel* LocalSubchannelPool::FindSubchannel(SubchannelKey* key) { - grpc_subchannel* c = static_cast( - grpc_avl_get(subchannel_map_, key, nullptr)); +Subchannel* LocalSubchannelPool::FindSubchannel(SubchannelKey* key) { + Subchannel* c = + static_cast(grpc_avl_get(subchannel_map_, key, nullptr)); return c == nullptr ? c : GRPC_SUBCHANNEL_REF(c, "found_from_pool"); } diff --git a/src/core/ext/filters/client_channel/local_subchannel_pool.h b/src/core/ext/filters/client_channel/local_subchannel_pool.h index 9929cdb3627..a6b7e259fbb 100644 --- a/src/core/ext/filters/client_channel/local_subchannel_pool.h +++ b/src/core/ext/filters/client_channel/local_subchannel_pool.h @@ -39,10 +39,10 @@ class LocalSubchannelPool final : public SubchannelPoolInterface { // Implements interface methods. // Thread-unsafe. Intended to be invoked within the client_channel combiner. - grpc_subchannel* RegisterSubchannel(SubchannelKey* key, - grpc_subchannel* constructed) override; + Subchannel* RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) override; void UnregisterSubchannel(SubchannelKey* key) override; - grpc_subchannel* FindSubchannel(SubchannelKey* key) override; + Subchannel* FindSubchannel(SubchannelKey* key) override; private: // The vtable for subchannel operations in an AVL tree. diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index d77bb3c286b..70285659aad 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -44,7 +44,6 @@ #include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" -#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/channel.h" @@ -55,153 +54,256 @@ #include "src/core/lib/transport/status_metadata.h" #include "src/core/lib/uri/uri_parser.h" +// Strong and weak refs. #define INTERNAL_REF_BITS 16 #define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1)) +// Backoff parameters. #define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1 #define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6 #define GRPC_SUBCHANNEL_RECONNECT_MIN_TIMEOUT_SECONDS 20 #define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120 #define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2 -typedef struct external_state_watcher { - grpc_subchannel* subchannel; - grpc_pollset_set* pollset_set; - grpc_closure* notify; - grpc_closure closure; - struct external_state_watcher* next; - struct external_state_watcher* prev; -} external_state_watcher; +// Conversion between subchannel call and call stack. +#define SUBCHANNEL_CALL_TO_CALL_STACK(call) \ + (grpc_call_stack*)((char*)(call) + \ + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall))) +#define CALL_STACK_TO_SUBCHANNEL_CALL(callstack) \ + (SubchannelCall*)(((char*)(call_stack)) - \ + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall))) namespace grpc_core { -class ConnectedSubchannelStateWatcher; - -} // namespace grpc_core +// +// ConnectedSubchannel +// -struct grpc_subchannel { - /** The subchannel pool this subchannel is in */ - grpc_core::RefCountedPtr subchannel_pool; +ConnectedSubchannel::ConnectedSubchannel( + grpc_channel_stack* channel_stack, const grpc_channel_args* args, + RefCountedPtr channelz_subchannel, + intptr_t socket_uuid) + : RefCounted(&grpc_trace_stream_refcount), + channel_stack_(channel_stack), + args_(grpc_channel_args_copy(args)), + channelz_subchannel_(std::move(channelz_subchannel)), + socket_uuid_(socket_uuid) {} - grpc_connector* connector; +ConnectedSubchannel::~ConnectedSubchannel() { + grpc_channel_args_destroy(args_); + GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor"); +} - /** refcount - - lower INTERNAL_REF_BITS bits are for internal references: - these do not keep the subchannel open. - - upper remaining bits are for public references: these do - keep the subchannel open */ - gpr_atm ref_pair; +void ConnectedSubchannel::NotifyOnStateChange( + grpc_pollset_set* interested_parties, grpc_connectivity_state* state, + grpc_closure* closure) { + grpc_transport_op* op = grpc_make_transport_op(nullptr); + grpc_channel_element* elem; + op->connectivity_state = state; + op->on_connectivity_state_change = closure; + op->bind_pollset_set = interested_parties; + elem = grpc_channel_stack_element(channel_stack_, 0); + elem->filter->start_transport_op(elem, op); +} - /** channel arguments */ - grpc_channel_args* args; +void ConnectedSubchannel::Ping(grpc_closure* on_initiate, + grpc_closure* on_ack) { + grpc_transport_op* op = grpc_make_transport_op(nullptr); + grpc_channel_element* elem; + op->send_ping.on_initiate = on_initiate; + op->send_ping.on_ack = on_ack; + elem = grpc_channel_stack_element(channel_stack_, 0); + elem->filter->start_transport_op(elem, op); +} - grpc_core::SubchannelKey* key; +namespace { - /** set during connection */ - grpc_connect_out_args connecting_result; +void SubchannelCallDestroy(void* arg, grpc_error* error) { + GPR_TIMER_SCOPE("subchannel_call_destroy", 0); + SubchannelCall* call = static_cast(arg); + grpc_closure* after_call_stack_destroy = call->after_call_stack_destroy(); + call->~SubchannelCall(); + // This should be the last step to destroy the subchannel call, because + // call->after_call_stack_destroy(), if not null, will free the call arena. + grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(call), nullptr, + after_call_stack_destroy); +} - /** callback for connection finishing */ - grpc_closure on_connected; +} // namespace - /** callback for our alarm */ - grpc_closure on_alarm; +RefCountedPtr ConnectedSubchannel::CreateCall( + const CallArgs& args, grpc_error** error) { + const size_t allocation_size = + GetInitialCallSizeEstimate(args.parent_data_size); + RefCountedPtr call( + new (gpr_arena_alloc(args.arena, allocation_size)) + SubchannelCall(Ref(DEBUG_LOCATION, "subchannel_call"), args)); + grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call.get()); + const grpc_call_element_args call_args = { + callstk, /* call_stack */ + nullptr, /* server_transport_data */ + args.context, /* context */ + args.path, /* path */ + args.start_time, /* start_time */ + args.deadline, /* deadline */ + args.arena, /* arena */ + args.call_combiner /* call_combiner */ + }; + *error = grpc_call_stack_init(channel_stack_, 1, SubchannelCallDestroy, + call.get(), &call_args); + if (GPR_UNLIKELY(*error != GRPC_ERROR_NONE)) { + const char* error_string = grpc_error_string(*error); + gpr_log(GPR_ERROR, "error: %s", error_string); + return call; + } + grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); + if (channelz_subchannel_ != nullptr) { + channelz_subchannel_->RecordCallStarted(); + } + return call; +} - /** pollset_set tracking who's interested in a connection - being setup */ - grpc_pollset_set* pollset_set; +size_t ConnectedSubchannel::GetInitialCallSizeEstimate( + size_t parent_data_size) const { + size_t allocation_size = + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)); + if (parent_data_size > 0) { + allocation_size += + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) + + parent_data_size; + } else { + allocation_size += channel_stack_->call_stack_size; + } + return allocation_size; +} - grpc_core::UniquePtr health_check_service_name; +// +// SubchannelCall +// - /** mutex protecting remaining elements */ - gpr_mu mu; +void SubchannelCall::StartTransportStreamOpBatch( + grpc_transport_stream_op_batch* batch) { + GPR_TIMER_SCOPE("subchannel_call_process_op", 0); + MaybeInterceptRecvTrailingMetadata(batch); + grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(this); + grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0); + GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch); + top_elem->filter->start_transport_stream_op_batch(top_elem, batch); +} - /** active connection, or null */ - grpc_core::RefCountedPtr connected_subchannel; - grpc_core::OrphanablePtr - connected_subchannel_watcher; +void* SubchannelCall::GetParentData() { + grpc_channel_stack* chanstk = connected_subchannel_->channel_stack(); + return (char*)this + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)) + + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(chanstk->call_stack_size); +} - /** have we seen a disconnection? */ - bool disconnected; - /** are we connecting */ - bool connecting; +grpc_call_stack* SubchannelCall::GetCallStack() { + return SUBCHANNEL_CALL_TO_CALL_STACK(this); +} - /** connectivity state tracking */ - grpc_connectivity_state_tracker state_tracker; - grpc_connectivity_state_tracker state_and_health_tracker; +void SubchannelCall::SetAfterCallStackDestroy(grpc_closure* closure) { + GPR_ASSERT(after_call_stack_destroy_ == nullptr); + GPR_ASSERT(closure != nullptr); + after_call_stack_destroy_ = closure; +} - external_state_watcher root_external_state_watcher; +RefCountedPtr SubchannelCall::Ref() { + IncrementRefCount(); + return RefCountedPtr(this); +} - /** backoff state */ - grpc_core::ManualConstructor backoff; - grpc_millis next_attempt_deadline; - grpc_millis min_connect_timeout_ms; +RefCountedPtr SubchannelCall::Ref( + const grpc_core::DebugLocation& location, const char* reason) { + IncrementRefCount(location, reason); + return RefCountedPtr(this); +} - /** do we have an active alarm? */ - bool have_alarm; - /** have we started the backoff loop */ - bool backoff_begun; - // reset_backoff() was called while alarm was pending - bool retry_immediately; - /** our alarm */ - grpc_timer alarm; +void SubchannelCall::Unref() { + GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), ""); +} - grpc_core::RefCountedPtr - channelz_subchannel; -}; +void SubchannelCall::Unref(const DebugLocation& location, const char* reason) { + GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason); +} -struct grpc_subchannel_call { - grpc_subchannel_call(grpc_core::ConnectedSubchannel* connection, - const grpc_core::ConnectedSubchannel::CallArgs& args) - : connection(connection), deadline(args.deadline) {} - - grpc_core::ConnectedSubchannel* connection; - grpc_closure* schedule_closure_after_destroy = nullptr; - // state needed to support channelz interception of recv trailing metadata. - grpc_closure recv_trailing_metadata_ready; - grpc_closure* original_recv_trailing_metadata; - grpc_metadata_batch* recv_trailing_metadata = nullptr; - grpc_millis deadline; -}; +void SubchannelCall::MaybeInterceptRecvTrailingMetadata( + grpc_transport_stream_op_batch* batch) { + // only intercept payloads with recv trailing. + if (!batch->recv_trailing_metadata) { + return; + } + // only add interceptor is channelz is enabled. + if (connected_subchannel_->channelz_subchannel() == nullptr) { + return; + } + GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready_, RecvTrailingMetadataReady, + this, grpc_schedule_on_exec_ctx); + // save some state needed for the interception callback. + GPR_ASSERT(recv_trailing_metadata_ == nullptr); + recv_trailing_metadata_ = + batch->payload->recv_trailing_metadata.recv_trailing_metadata; + original_recv_trailing_metadata_ = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &recv_trailing_metadata_ready_; +} -static void maybe_start_connecting_locked(grpc_subchannel* c); +namespace { -static const char* subchannel_connectivity_state_change_string( - grpc_connectivity_state state) { - switch (state) { - case GRPC_CHANNEL_IDLE: - return "Subchannel state change to IDLE"; - case GRPC_CHANNEL_CONNECTING: - return "Subchannel state change to CONNECTING"; - case GRPC_CHANNEL_READY: - return "Subchannel state change to READY"; - case GRPC_CHANNEL_TRANSIENT_FAILURE: - return "Subchannel state change to TRANSIENT_FAILURE"; - case GRPC_CHANNEL_SHUTDOWN: - return "Subchannel state change to SHUTDOWN"; +// Sets *status based on the rest of the parameters. +void GetCallStatus(grpc_status_code* status, grpc_millis deadline, + grpc_metadata_batch* md_batch, grpc_error* error) { + if (error != GRPC_ERROR_NONE) { + grpc_error_get_status(error, deadline, status, nullptr, nullptr, nullptr); + } else { + if (md_batch->idx.named.grpc_status != nullptr) { + *status = grpc_get_status_code_from_metadata( + md_batch->idx.named.grpc_status->md); + } else { + *status = GRPC_STATUS_UNKNOWN; + } } - GPR_UNREACHABLE_CODE(return "UNKNOWN"); + GRPC_ERROR_UNREF(error); } -static void set_subchannel_connectivity_state_locked( - grpc_subchannel* c, grpc_connectivity_state state, grpc_error* error, - const char* reason) { - if (c->channelz_subchannel != nullptr) { - c->channelz_subchannel->AddTraceEvent( - grpc_core::channelz::ChannelTrace::Severity::Info, - grpc_slice_from_static_string( - subchannel_connectivity_state_change_string(state))); +} // namespace + +void SubchannelCall::RecvTrailingMetadataReady(void* arg, grpc_error* error) { + SubchannelCall* call = static_cast(arg); + GPR_ASSERT(call->recv_trailing_metadata_ != nullptr); + grpc_status_code status = GRPC_STATUS_OK; + GetCallStatus(&status, call->deadline_, call->recv_trailing_metadata_, + GRPC_ERROR_REF(error)); + channelz::SubchannelNode* channelz_subchannel = + call->connected_subchannel_->channelz_subchannel(); + GPR_ASSERT(channelz_subchannel != nullptr); + if (status == GRPC_STATUS_OK) { + channelz_subchannel->RecordCallSucceeded(); + } else { + channelz_subchannel->RecordCallFailed(); } - grpc_connectivity_state_set(&c->state_tracker, state, error, reason); + GRPC_CLOSURE_RUN(call->original_recv_trailing_metadata_, + GRPC_ERROR_REF(error)); } -namespace grpc_core { +void SubchannelCall::IncrementRefCount() { + GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(this), ""); +} + +void SubchannelCall::IncrementRefCount(const grpc_core::DebugLocation& location, + const char* reason) { + GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason); +} + +// +// Subchannel::ConnectedSubchannelStateWatcher +// -class ConnectedSubchannelStateWatcher +class Subchannel::ConnectedSubchannelStateWatcher : public InternallyRefCounted { public: // Must be instantiated while holding c->mu. - explicit ConnectedSubchannelStateWatcher(grpc_subchannel* c) - : subchannel_(c) { + explicit ConnectedSubchannelStateWatcher(Subchannel* c) : subchannel_(c) { // Steal subchannel ref for connecting. GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "state_watcher"); GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "connecting"); @@ -209,15 +311,15 @@ class ConnectedSubchannelStateWatcher // Callback uses initial ref to this. GRPC_CLOSURE_INIT(&on_connectivity_changed_, OnConnectivityChanged, this, grpc_schedule_on_exec_ctx); - c->connected_subchannel->NotifyOnStateChange(c->pollset_set, - &pending_connectivity_state_, - &on_connectivity_changed_); + c->connected_subchannel_->NotifyOnStateChange(c->pollset_set_, + &pending_connectivity_state_, + &on_connectivity_changed_); // Start health check if needed. grpc_connectivity_state health_state = GRPC_CHANNEL_READY; - if (c->health_check_service_name != nullptr) { - health_check_client_ = grpc_core::MakeOrphanable( - c->health_check_service_name.get(), c->connected_subchannel, - c->pollset_set, c->channelz_subchannel); + if (c->health_check_service_name_ != nullptr) { + health_check_client_ = MakeOrphanable( + c->health_check_service_name_.get(), c->connected_subchannel_, + c->pollset_set_, c->channelz_node_); GRPC_CLOSURE_INIT(&on_health_changed_, OnHealthChanged, this, grpc_schedule_on_exec_ctx); Ref().release(); // Ref for health callback tracked manually. @@ -226,9 +328,9 @@ class ConnectedSubchannelStateWatcher health_state = GRPC_CHANNEL_CONNECTING; } // Report initial state. - set_subchannel_connectivity_state_locked( - c, GRPC_CHANNEL_READY, GRPC_ERROR_NONE, "subchannel_connected"); - grpc_connectivity_state_set(&c->state_and_health_tracker, health_state, + c->SetConnectivityStateLocked(GRPC_CHANNEL_READY, GRPC_ERROR_NONE, + "subchannel_connected"); + grpc_connectivity_state_set(&c->state_and_health_tracker_, health_state, GRPC_ERROR_NONE, "subchannel_connected"); } @@ -242,33 +344,33 @@ class ConnectedSubchannelStateWatcher private: static void OnConnectivityChanged(void* arg, grpc_error* error) { auto* self = static_cast(arg); - grpc_subchannel* c = self->subchannel_; + Subchannel* c = self->subchannel_; { - MutexLock lock(&c->mu); + MutexLock lock(&c->mu_); switch (self->pending_connectivity_state_) { case GRPC_CHANNEL_TRANSIENT_FAILURE: case GRPC_CHANNEL_SHUTDOWN: { - if (!c->disconnected && c->connected_subchannel != nullptr) { + if (!c->disconnected_ && c->connected_subchannel_ != nullptr) { if (grpc_trace_stream_refcount.enabled()) { gpr_log(GPR_INFO, "Connected subchannel %p of subchannel %p has gone into " "%s. Attempting to reconnect.", - c->connected_subchannel.get(), c, + c->connected_subchannel_.get(), c, grpc_connectivity_state_name( self->pending_connectivity_state_)); } - c->connected_subchannel.reset(); - c->connected_subchannel_watcher.reset(); + c->connected_subchannel_.reset(); + c->connected_subchannel_watcher_.reset(); self->last_connectivity_state_ = GRPC_CHANNEL_TRANSIENT_FAILURE; - set_subchannel_connectivity_state_locked( - c, GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), - "reflect_child"); - grpc_connectivity_state_set(&c->state_and_health_tracker, + c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, + GRPC_ERROR_REF(error), + "reflect_child"); + grpc_connectivity_state_set(&c->state_and_health_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), "reflect_child"); - c->backoff_begun = false; - c->backoff->Reset(); - maybe_start_connecting_locked(c); + c->backoff_begun_ = false; + c->backoff_.Reset(); + c->MaybeStartConnectingLocked(); } else { self->last_connectivity_state_ = GRPC_CHANNEL_SHUTDOWN; } @@ -281,15 +383,14 @@ class ConnectedSubchannelStateWatcher // this watch from. And a connected subchannel should never go // from READY to CONNECTING or IDLE. self->last_connectivity_state_ = self->pending_connectivity_state_; - set_subchannel_connectivity_state_locked( - c, self->pending_connectivity_state_, GRPC_ERROR_REF(error), - "reflect_child"); + c->SetConnectivityStateLocked(self->pending_connectivity_state_, + GRPC_ERROR_REF(error), "reflect_child"); if (self->pending_connectivity_state_ != GRPC_CHANNEL_READY) { - grpc_connectivity_state_set(&c->state_and_health_tracker, + grpc_connectivity_state_set(&c->state_and_health_tracker_, self->pending_connectivity_state_, GRPC_ERROR_REF(error), "reflect_child"); } - c->connected_subchannel->NotifyOnStateChange( + c->connected_subchannel_->NotifyOnStateChange( nullptr, &self->pending_connectivity_state_, &self->on_connectivity_changed_); self = nullptr; // So we don't unref below. @@ -303,14 +404,14 @@ class ConnectedSubchannelStateWatcher static void OnHealthChanged(void* arg, grpc_error* error) { auto* self = static_cast(arg); - grpc_subchannel* c = self->subchannel_; - MutexLock lock(&c->mu); + Subchannel* c = self->subchannel_; + MutexLock lock(&c->mu_); if (self->health_state_ == GRPC_CHANNEL_SHUTDOWN) { self->Unref(); return; } if (self->last_connectivity_state_ == GRPC_CHANNEL_READY) { - grpc_connectivity_state_set(&c->state_and_health_tracker, + grpc_connectivity_state_set(&c->state_and_health_tracker_, self->health_state_, GRPC_ERROR_REF(error), "health_changed"); } @@ -318,163 +419,63 @@ class ConnectedSubchannelStateWatcher &self->on_health_changed_); } - grpc_subchannel* subchannel_; + Subchannel* subchannel_; grpc_closure on_connectivity_changed_; grpc_connectivity_state pending_connectivity_state_ = GRPC_CHANNEL_READY; grpc_connectivity_state last_connectivity_state_ = GRPC_CHANNEL_READY; - grpc_core::OrphanablePtr health_check_client_; + OrphanablePtr health_check_client_; grpc_closure on_health_changed_; grpc_connectivity_state health_state_ = GRPC_CHANNEL_CONNECTING; }; -} // namespace grpc_core - -#define SUBCHANNEL_CALL_TO_CALL_STACK(call) \ - (grpc_call_stack*)((char*)(call) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \ - sizeof(grpc_subchannel_call))) -#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \ - (grpc_subchannel_call*)(((char*)(call_stack)) - \ - GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \ - sizeof(grpc_subchannel_call))) - -static void on_subchannel_connected(void* subchannel, grpc_error* error); - -#ifndef NDEBUG -#define REF_REASON reason -#define REF_MUTATE_EXTRA_ARGS \ - GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char* purpose -#define REF_MUTATE_PURPOSE(x) , file, line, reason, x -#else -#define REF_REASON "" -#define REF_MUTATE_EXTRA_ARGS -#define REF_MUTATE_PURPOSE(x) -#endif - -/* - * connection implementation - */ - -static void connection_destroy(void* arg, grpc_error* error) { - grpc_channel_stack* stk = static_cast(arg); - grpc_channel_stack_destroy(stk); - gpr_free(stk); -} - -/* - * grpc_subchannel implementation - */ - -static void subchannel_destroy(void* arg, grpc_error* error) { - grpc_subchannel* c = static_cast(arg); - if (c->channelz_subchannel != nullptr) { - c->channelz_subchannel->AddTraceEvent( - grpc_core::channelz::ChannelTrace::Severity::Info, - grpc_slice_from_static_string("Subchannel destroyed")); - c->channelz_subchannel->MarkSubchannelDestroyed(); - c->channelz_subchannel.reset(); - } - c->health_check_service_name.reset(); - grpc_channel_args_destroy(c->args); - grpc_connectivity_state_destroy(&c->state_tracker); - grpc_connectivity_state_destroy(&c->state_and_health_tracker); - grpc_connector_unref(c->connector); - grpc_pollset_set_destroy(c->pollset_set); - grpc_core::Delete(c->key); - gpr_mu_destroy(&c->mu); - gpr_free(c); -} +// +// Subchannel::ExternalStateWatcher +// -static gpr_atm ref_mutate(grpc_subchannel* c, gpr_atm delta, - int barrier REF_MUTATE_EXTRA_ARGS) { - gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta) - : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta); -#ifndef NDEBUG - if (grpc_trace_stream_refcount.enabled()) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", c, - purpose, old_val, old_val + delta, reason); +struct Subchannel::ExternalStateWatcher { + ExternalStateWatcher(Subchannel* subchannel, grpc_pollset_set* pollset_set, + grpc_closure* notify) + : subchannel(subchannel), pollset_set(pollset_set), notify(notify) { + GRPC_SUBCHANNEL_WEAK_REF(subchannel, "external_state_watcher+init"); + GRPC_CLOSURE_INIT(&on_state_changed, OnStateChanged, this, + grpc_schedule_on_exec_ctx); } -#endif - return old_val; -} - -grpc_subchannel* grpc_subchannel_ref( - grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = ref_mutate(c, (1 << INTERNAL_REF_BITS), - 0 REF_MUTATE_PURPOSE("STRONG_REF")); - GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0); - return c; -} - -grpc_subchannel* grpc_subchannel_weak_ref( - grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = ref_mutate(c, 1, 0 REF_MUTATE_PURPOSE("WEAK_REF")); - GPR_ASSERT(old_refs != 0); - return c; -} -grpc_subchannel* grpc_subchannel_ref_from_weak_ref( - grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - if (!c) return nullptr; - for (;;) { - gpr_atm old_refs = gpr_atm_acq_load(&c->ref_pair); - if (old_refs >= (1 << INTERNAL_REF_BITS)) { - gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS); - if (gpr_atm_rel_cas(&c->ref_pair, old_refs, new_refs)) { - return c; - } - } else { - return nullptr; + static void OnStateChanged(void* arg, grpc_error* error) { + ExternalStateWatcher* w = static_cast(arg); + grpc_closure* follow_up = w->notify; + if (w->pollset_set != nullptr) { + grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set_, + w->pollset_set); } + gpr_mu_lock(&w->subchannel->mu_); + if (w->subchannel->external_state_watcher_list_ == w) { + w->subchannel->external_state_watcher_list_ = w->next; + } + if (w->next != nullptr) w->next->prev = w->prev; + if (w->prev != nullptr) w->prev->next = w->next; + gpr_mu_unlock(&w->subchannel->mu_); + GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher+done"); + Delete(w); + GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); } -} -static void disconnect(grpc_subchannel* c) { - // The subchannel_pool is only used once here in this subchannel, so the - // access can be outside of the lock. - if (c->subchannel_pool != nullptr) { - c->subchannel_pool->UnregisterSubchannel(c->key); - c->subchannel_pool.reset(); - } - gpr_mu_lock(&c->mu); - GPR_ASSERT(!c->disconnected); - c->disconnected = true; - grpc_connector_shutdown(c->connector, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Subchannel disconnected")); - c->connected_subchannel.reset(); - c->connected_subchannel_watcher.reset(); - gpr_mu_unlock(&c->mu); -} + Subchannel* subchannel; + grpc_pollset_set* pollset_set; + grpc_closure* notify; + grpc_closure on_state_changed; + ExternalStateWatcher* next = nullptr; + ExternalStateWatcher* prev = nullptr; +}; -void grpc_subchannel_unref(grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - // add a weak ref and subtract a strong ref (atomically) - old_refs = ref_mutate( - c, static_cast(1) - static_cast(1 << INTERNAL_REF_BITS), - 1 REF_MUTATE_PURPOSE("STRONG_UNREF")); - if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) { - disconnect(c); - } - GRPC_SUBCHANNEL_WEAK_UNREF(c, "strong-unref"); -} +// +// Subchannel +// -void grpc_subchannel_weak_unref( - grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = ref_mutate(c, -static_cast(1), - 1 REF_MUTATE_PURPOSE("WEAK_UNREF")); - if (old_refs == 1) { - GRPC_CLOSURE_SCHED( - GRPC_CLOSURE_CREATE(subchannel_destroy, c, grpc_schedule_on_exec_ctx), - GRPC_ERROR_NONE); - } -} +namespace { -static void parse_args_for_backoff_values( - const grpc_channel_args* args, grpc_core::BackOff::Options* backoff_options, - grpc_millis* min_connect_timeout_ms) { +BackOff::Options ParseArgsForBackoffValues( + const grpc_channel_args* args, grpc_millis* min_connect_timeout_ms) { grpc_millis initial_backoff_ms = GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000; *min_connect_timeout_ms = @@ -511,7 +512,8 @@ static void parse_args_for_backoff_values( } } } - backoff_options->set_initial_backoff(initial_backoff_ms) + return BackOff::Options() + .set_initial_backoff(initial_backoff_ms) .set_multiplier(fixed_reconnect_backoff ? 1.0 : GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER) @@ -520,9 +522,6 @@ static void parse_args_for_backoff_values( .set_max_backoff(max_backoff_ms); } -namespace grpc_core { -namespace { - struct HealthCheckParams { UniquePtr service_name; @@ -543,31 +542,19 @@ struct HealthCheckParams { }; } // namespace -} // namespace grpc_core -grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, - const grpc_channel_args* args) { - grpc_core::SubchannelKey* key = - grpc_core::New(args); - grpc_core::SubchannelPoolInterface* subchannel_pool = - grpc_core::SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs( - args); - GPR_ASSERT(subchannel_pool != nullptr); - grpc_subchannel* c = subchannel_pool->FindSubchannel(key); - if (c != nullptr) { - grpc_core::Delete(key); - return c; - } +Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector, + const grpc_channel_args* args) + : key_(key), + connector_(connector), + backoff_(ParseArgsForBackoffValues(args, &min_connect_timeout_ms_)) { GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED(); - c = static_cast(gpr_zalloc(sizeof(*c))); - c->key = key; - gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS); - c->connector = connector; - grpc_connector_ref(c->connector); - c->pollset_set = grpc_pollset_set_create(); + gpr_atm_no_barrier_store(&ref_pair_, 1 << INTERNAL_REF_BITS); + grpc_connector_ref(connector_); + pollset_set_ = grpc_pollset_set_create(); grpc_resolved_address* addr = static_cast(gpr_malloc(sizeof(*addr))); - grpc_get_subchannel_address_arg(args, addr); + GetAddressFromSubchannelAddressArg(args, addr); grpc_resolved_address* new_address = nullptr; grpc_channel_args* new_args = nullptr; if (grpc_proxy_mappers_map_address(addr, args, &new_address, &new_args)) { @@ -576,569 +563,492 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, addr = new_address; } static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS}; - grpc_arg new_arg = grpc_create_subchannel_address_arg(addr); + grpc_arg new_arg = CreateSubchannelAddressArg(addr); gpr_free(addr); - c->args = grpc_channel_args_copy_and_add_and_remove( + args_ = grpc_channel_args_copy_and_add_and_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); - c->root_external_state_watcher.next = c->root_external_state_watcher.prev = - &c->root_external_state_watcher; - GRPC_CLOSURE_INIT(&c->on_connected, on_subchannel_connected, c, + GRPC_CLOSURE_INIT(&on_connecting_finished_, OnConnectingFinished, this, grpc_schedule_on_exec_ctx); - grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE, + grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE, "subchannel"); - grpc_connectivity_state_init(&c->state_and_health_tracker, GRPC_CHANNEL_IDLE, + grpc_connectivity_state_init(&state_and_health_tracker_, GRPC_CHANNEL_IDLE, "subchannel"); - grpc_core::BackOff::Options 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); - + gpr_mu_init(&mu_); // Check whether we should enable health checking. const char* service_config_json = grpc_channel_arg_get_string( - grpc_channel_args_find(c->args, GRPC_ARG_SERVICE_CONFIG)); + grpc_channel_args_find(args_, GRPC_ARG_SERVICE_CONFIG)); if (service_config_json != nullptr) { - grpc_core::UniquePtr service_config = - grpc_core::ServiceConfig::Create(service_config_json); + UniquePtr service_config = + ServiceConfig::Create(service_config_json); if (service_config != nullptr) { - grpc_core::HealthCheckParams params; - service_config->ParseGlobalParams(grpc_core::HealthCheckParams::Parse, - ¶ms); - c->health_check_service_name = std::move(params.service_name); + HealthCheckParams params; + service_config->ParseGlobalParams(HealthCheckParams::Parse, ¶ms); + health_check_service_name_ = std::move(params.service_name); } } - - const grpc_arg* arg = - grpc_channel_args_find(c->args, GRPC_ARG_ENABLE_CHANNELZ); - bool channelz_enabled = + const grpc_arg* arg = grpc_channel_args_find(args_, GRPC_ARG_ENABLE_CHANNELZ); + const bool channelz_enabled = grpc_channel_arg_get_bool(arg, GRPC_ENABLE_CHANNELZ_DEFAULT); arg = grpc_channel_args_find( - c->args, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE); + args_, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE); const grpc_integer_options options = { GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT, 0, INT_MAX}; size_t channel_tracer_max_memory = (size_t)grpc_channel_arg_get_integer(arg, options); if (channelz_enabled) { - c->channelz_subchannel = - grpc_core::MakeRefCounted( - c, channel_tracer_max_memory); - c->channelz_subchannel->AddTraceEvent( - grpc_core::channelz::ChannelTrace::Severity::Info, - grpc_slice_from_static_string("Subchannel created")); + channelz_node_ = MakeRefCounted( + this, channel_tracer_max_memory); + channelz_node_->AddTraceEvent( + channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("subchannel created")); + } +} + +Subchannel::~Subchannel() { + if (channelz_node_ != nullptr) { + channelz_node_->AddTraceEvent( + channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Subchannel destroyed")); + channelz_node_->MarkSubchannelDestroyed(); + } + grpc_channel_args_destroy(args_); + grpc_connectivity_state_destroy(&state_tracker_); + grpc_connectivity_state_destroy(&state_and_health_tracker_); + grpc_connector_unref(connector_); + grpc_pollset_set_destroy(pollset_set_); + Delete(key_); + gpr_mu_destroy(&mu_); +} + +Subchannel* Subchannel::Create(grpc_connector* connector, + const grpc_channel_args* args) { + SubchannelKey* key = New(args); + SubchannelPoolInterface* subchannel_pool = + SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs(args); + GPR_ASSERT(subchannel_pool != nullptr); + Subchannel* c = subchannel_pool->FindSubchannel(key); + if (c != nullptr) { + Delete(key); + return c; } + c = New(key, connector, args); // Try to register the subchannel before setting the subchannel pool. // Otherwise, in case of a registration race, unreffing c in - // RegisterSubchannel() will cause c to be tried to be unregistered, while its - // key maps to a different subchannel. - grpc_subchannel* registered = subchannel_pool->RegisterSubchannel(key, c); - if (registered == c) c->subchannel_pool = subchannel_pool->Ref(); + // RegisterSubchannel() will cause c to be tried to be unregistered, while + // its key maps to a different subchannel. + Subchannel* registered = subchannel_pool->RegisterSubchannel(key, c); + if (registered == c) c->subchannel_pool_ = subchannel_pool->Ref(); return registered; } -grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node( - grpc_subchannel* subchannel) { - return subchannel->channelz_subchannel.get(); +Subchannel* Subchannel::Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + old_refs = RefMutate((1 << INTERNAL_REF_BITS), + 0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_REF")); + GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0); + return this; } -intptr_t grpc_subchannel_get_child_socket_uuid(grpc_subchannel* subchannel) { - if (subchannel->connected_subchannel != nullptr) { - return subchannel->connected_subchannel->socket_uuid(); - } else { - return 0; +void Subchannel::Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + // add a weak ref and subtract a strong ref (atomically) + old_refs = RefMutate( + static_cast(1) - static_cast(1 << INTERNAL_REF_BITS), + 1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_UNREF")); + if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) { + Disconnect(); } + GRPC_SUBCHANNEL_WEAK_UNREF(this, "strong-unref"); } -static void continue_connect_locked(grpc_subchannel* c) { - grpc_connect_in_args args; - args.interested_parties = c->pollset_set; - const grpc_millis min_deadline = - c->min_connect_timeout_ms + grpc_core::ExecCtx::Get()->Now(); - c->next_attempt_deadline = c->backoff->NextAttemptTime(); - args.deadline = std::max(c->next_attempt_deadline, min_deadline); - args.channel_args = c->args; - set_subchannel_connectivity_state_locked(c, GRPC_CHANNEL_CONNECTING, - GRPC_ERROR_NONE, "connecting"); - grpc_connectivity_state_set(&c->state_and_health_tracker, - GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, - "connecting"); - grpc_connector_connect(c->connector, &args, &c->connecting_result, - &c->on_connected); +Subchannel* Subchannel::WeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + old_refs = RefMutate(1, 0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_REF")); + GPR_ASSERT(old_refs != 0); + return this; } -grpc_connectivity_state grpc_subchannel_check_connectivity( - grpc_subchannel* c, grpc_error** error, bool inhibit_health_checks) { - gpr_mu_lock(&c->mu); - grpc_connectivity_state_tracker* tracker = - inhibit_health_checks ? &c->state_tracker : &c->state_and_health_tracker; - grpc_connectivity_state state = grpc_connectivity_state_get(tracker, error); - gpr_mu_unlock(&c->mu); - return state; -} +namespace { -static void on_external_state_watcher_done(void* arg, grpc_error* error) { - external_state_watcher* w = static_cast(arg); - grpc_closure* follow_up = w->notify; - if (w->pollset_set != nullptr) { - grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set, - w->pollset_set); - } - gpr_mu_lock(&w->subchannel->mu); - w->next->prev = w->prev; - w->prev->next = w->next; - gpr_mu_unlock(&w->subchannel->mu); - GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher"); - gpr_free(w); - GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); +void subchannel_destroy(void* arg, grpc_error* error) { + Subchannel* self = static_cast(arg); + Delete(self); } -static void on_alarm(void* arg, grpc_error* error) { - grpc_subchannel* c = static_cast(arg); - gpr_mu_lock(&c->mu); - c->have_alarm = false; - if (c->disconnected) { - error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", - &error, 1); - } else if (c->retry_immediately) { - c->retry_immediately = false; - error = GRPC_ERROR_NONE; - } else { - GRPC_ERROR_REF(error); - } - if (error == GRPC_ERROR_NONE) { - gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); - continue_connect_locked(c); - gpr_mu_unlock(&c->mu); - } else { - gpr_mu_unlock(&c->mu); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); +} // namespace + +void Subchannel::WeakUnref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + old_refs = RefMutate(-static_cast(1), + 1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_UNREF")); + if (old_refs == 1) { + GRPC_CLOSURE_SCHED(GRPC_CLOSURE_CREATE(subchannel_destroy, this, + grpc_schedule_on_exec_ctx), + GRPC_ERROR_NONE); } - GRPC_ERROR_UNREF(error); } -static void maybe_start_connecting_locked(grpc_subchannel* c) { - if (c->disconnected) { - /* Don't try to connect if we're already disconnected */ - return; - } - if (c->connecting) { - /* Already connecting: don't restart */ - return; - } - if (c->connected_subchannel != nullptr) { - /* Already connected: don't restart */ - return; - } - if (!grpc_connectivity_state_has_watchers(&c->state_tracker) && - !grpc_connectivity_state_has_watchers(&c->state_and_health_tracker)) { - /* Nobody is interested in connecting: so don't just yet */ - return; - } - c->connecting = true; - GRPC_SUBCHANNEL_WEAK_REF(c, "connecting"); - if (!c->backoff_begun) { - c->backoff_begun = true; - continue_connect_locked(c); - } else { - GPR_ASSERT(!c->have_alarm); - c->have_alarm = true; - const grpc_millis time_til_next = - c->next_attempt_deadline - grpc_core::ExecCtx::Get()->Now(); - if (time_til_next <= 0) { - gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", c); +Subchannel* Subchannel::RefFromWeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + for (;;) { + gpr_atm old_refs = gpr_atm_acq_load(&ref_pair_); + if (old_refs >= (1 << INTERNAL_REF_BITS)) { + gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS); + if (gpr_atm_rel_cas(&ref_pair_, old_refs, new_refs)) { + return this; + } } else { - gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRId64 " milliseconds", c, - time_til_next); + return nullptr; } - GRPC_CLOSURE_INIT(&c->on_alarm, on_alarm, c, grpc_schedule_on_exec_ctx); - grpc_timer_init(&c->alarm, c->next_attempt_deadline, &c->on_alarm); } } -void grpc_subchannel_notify_on_state_change( - grpc_subchannel* c, grpc_pollset_set* interested_parties, - grpc_connectivity_state* state, grpc_closure* notify, - bool inhibit_health_checks) { +intptr_t Subchannel::GetChildSocketUuid() { + if (connected_subchannel_ != nullptr) { + return connected_subchannel_->socket_uuid(); + } else { + return 0; + } +} + +const char* Subchannel::GetTargetAddress() { + const grpc_arg* addr_arg = + grpc_channel_args_find(args_, GRPC_ARG_SUBCHANNEL_ADDRESS); + const char* addr_str = grpc_channel_arg_get_string(addr_arg); + GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. + return addr_str; +} + +RefCountedPtr Subchannel::connected_subchannel() { + MutexLock lock(&mu_); + return connected_subchannel_; +} + +channelz::SubchannelNode* Subchannel::channelz_node() { + return channelz_node_.get(); +} + +grpc_connectivity_state Subchannel::CheckConnectivity( + grpc_error** error, bool inhibit_health_checks) { + MutexLock lock(&mu_); + grpc_connectivity_state_tracker* tracker = + inhibit_health_checks ? &state_tracker_ : &state_and_health_tracker_; + grpc_connectivity_state state = grpc_connectivity_state_get(tracker, error); + return state; +} + +void Subchannel::NotifyOnStateChange(grpc_pollset_set* interested_parties, + grpc_connectivity_state* state, + grpc_closure* notify, + bool inhibit_health_checks) { grpc_connectivity_state_tracker* tracker = - inhibit_health_checks ? &c->state_tracker : &c->state_and_health_tracker; - external_state_watcher* w; + inhibit_health_checks ? &state_tracker_ : &state_and_health_tracker_; + ExternalStateWatcher* w; if (state == nullptr) { - gpr_mu_lock(&c->mu); - for (w = c->root_external_state_watcher.next; - w != &c->root_external_state_watcher; w = w->next) { + MutexLock lock(&mu_); + for (w = external_state_watcher_list_; w != nullptr; w = w->next) { if (w->notify == notify) { grpc_connectivity_state_notify_on_state_change(tracker, nullptr, - &w->closure); + &w->on_state_changed); } } - gpr_mu_unlock(&c->mu); } else { - w = static_cast(gpr_malloc(sizeof(*w))); - w->subchannel = c; - w->pollset_set = interested_parties; - w->notify = notify; - GRPC_CLOSURE_INIT(&w->closure, on_external_state_watcher_done, w, - grpc_schedule_on_exec_ctx); + w = New(this, interested_parties, notify); if (interested_parties != nullptr) { - grpc_pollset_set_add_pollset_set(c->pollset_set, interested_parties); + grpc_pollset_set_add_pollset_set(pollset_set_, interested_parties); } - GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher"); - gpr_mu_lock(&c->mu); - w->next = &c->root_external_state_watcher; - w->prev = w->next->prev; - w->next->prev = w->prev->next = w; - grpc_connectivity_state_notify_on_state_change(tracker, state, &w->closure); - maybe_start_connecting_locked(c); - gpr_mu_unlock(&c->mu); + MutexLock lock(&mu_); + if (external_state_watcher_list_ != nullptr) { + w->next = external_state_watcher_list_; + w->next->prev = w; + } + external_state_watcher_list_ = w; + grpc_connectivity_state_notify_on_state_change(tracker, state, + &w->on_state_changed); + MaybeStartConnectingLocked(); } } -static bool publish_transport_locked(grpc_subchannel* c) { - /* construct channel stack */ - grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create(); - grpc_channel_stack_builder_set_channel_arguments( - builder, c->connecting_result.channel_args); - grpc_channel_stack_builder_set_transport(builder, - c->connecting_result.transport); - - if (!grpc_channel_init_create_stack(builder, GRPC_CLIENT_SUBCHANNEL)) { - grpc_channel_stack_builder_destroy(builder); - return false; - } - grpc_channel_stack* stk; - grpc_error* error = grpc_channel_stack_builder_finish( - builder, 0, 1, connection_destroy, nullptr, - reinterpret_cast(&stk)); - if (error != GRPC_ERROR_NONE) { - grpc_transport_destroy(c->connecting_result.transport); - gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", - grpc_error_string(error)); - GRPC_ERROR_UNREF(error); - return false; - } - intptr_t socket_uuid = c->connecting_result.socket_uuid; - memset(&c->connecting_result, 0, sizeof(c->connecting_result)); - - if (c->disconnected) { - grpc_channel_stack_destroy(stk); - gpr_free(stk); - return false; +void Subchannel::ResetBackoff() { + MutexLock lock(&mu_); + backoff_.Reset(); + if (have_retry_alarm_) { + retry_immediately_ = true; + grpc_timer_cancel(&retry_alarm_); + } else { + backoff_begun_ = false; + MaybeStartConnectingLocked(); } - - /* publish */ - c->connected_subchannel.reset(grpc_core::New( - stk, c->args, c->channelz_subchannel, socket_uuid)); - gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p", - c->connected_subchannel.get(), c); - - // Instantiate state watcher. Will clean itself up. - c->connected_subchannel_watcher = - grpc_core::MakeOrphanable(c); - - return true; } -static void on_subchannel_connected(void* arg, grpc_error* error) { - grpc_subchannel* c = static_cast(arg); - grpc_channel_args* delete_channel_args = c->connecting_result.channel_args; - - GRPC_SUBCHANNEL_WEAK_REF(c, "on_subchannel_connected"); - gpr_mu_lock(&c->mu); - c->connecting = false; - if (c->connecting_result.transport != nullptr && - publish_transport_locked(c)) { - /* do nothing, transport was published */ - } else if (c->disconnected) { - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); - } else { - set_subchannel_connectivity_state_locked( - c, GRPC_CHANNEL_TRANSIENT_FAILURE, - grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Connect Failed", &error, 1), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), - "connect_failed"); - grpc_connectivity_state_set( - &c->state_and_health_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, - grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Connect Failed", &error, 1), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), - "connect_failed"); - - const char* errmsg = grpc_error_string(error); - gpr_log(GPR_INFO, "Connect failed: %s", errmsg); - - maybe_start_connecting_locked(c); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); - } - gpr_mu_unlock(&c->mu); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connected"); - grpc_channel_args_destroy(delete_channel_args); +grpc_arg Subchannel::CreateSubchannelAddressArg( + const grpc_resolved_address* addr) { + return grpc_channel_arg_string_create( + (char*)GRPC_ARG_SUBCHANNEL_ADDRESS, + addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup("")); } -void grpc_subchannel_reset_backoff(grpc_subchannel* subchannel) { - gpr_mu_lock(&subchannel->mu); - subchannel->backoff->Reset(); - if (subchannel->have_alarm) { - subchannel->retry_immediately = true; - grpc_timer_cancel(&subchannel->alarm); - } else { - subchannel->backoff_begun = false; - maybe_start_connecting_locked(subchannel); - } - gpr_mu_unlock(&subchannel->mu); +const char* Subchannel::GetUriFromSubchannelAddressArg( + const grpc_channel_args* args) { + const grpc_arg* addr_arg = + grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); + const char* addr_str = grpc_channel_arg_get_string(addr_arg); + GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. + return addr_str; } -/* - * grpc_subchannel_call implementation - */ +namespace { -static void subchannel_call_destroy(void* call, grpc_error* error) { - GPR_TIMER_SCOPE("grpc_subchannel_call_unref.destroy", 0); - grpc_subchannel_call* c = static_cast(call); - grpc_core::ConnectedSubchannel* connection = c->connection; - grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(c), nullptr, - c->schedule_closure_after_destroy); - connection->Unref(DEBUG_LOCATION, "subchannel_call"); - c->~grpc_subchannel_call(); +void UriToSockaddr(const char* uri_str, grpc_resolved_address* addr) { + grpc_uri* uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */); + GPR_ASSERT(uri != nullptr); + if (!grpc_parse_uri(uri, addr)) memset(addr, 0, sizeof(*addr)); + grpc_uri_destroy(uri); } -void grpc_subchannel_call_set_cleanup_closure(grpc_subchannel_call* call, - grpc_closure* closure) { - GPR_ASSERT(call->schedule_closure_after_destroy == nullptr); - GPR_ASSERT(closure != nullptr); - call->schedule_closure_after_destroy = closure; -} +} // namespace -grpc_subchannel_call* grpc_subchannel_call_ref( - grpc_subchannel_call* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON); - return c; +void Subchannel::GetAddressFromSubchannelAddressArg( + const grpc_channel_args* args, grpc_resolved_address* addr) { + const char* addr_uri_str = GetUriFromSubchannelAddressArg(args); + memset(addr, 0, sizeof(*addr)); + if (*addr_uri_str != '\0') { + UriToSockaddr(addr_uri_str, addr); + } } -void grpc_subchannel_call_unref( - grpc_subchannel_call* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON); -} +namespace { -// Sets *status based on md_batch and error. -static void get_call_status(grpc_subchannel_call* call, - grpc_metadata_batch* md_batch, grpc_error* error, - grpc_status_code* status) { - if (error != GRPC_ERROR_NONE) { - grpc_error_get_status(error, call->deadline, status, nullptr, nullptr, - nullptr); - } else { - if (md_batch->idx.named.grpc_status != nullptr) { - *status = grpc_get_status_code_from_metadata( - md_batch->idx.named.grpc_status->md); - } else { - *status = GRPC_STATUS_UNKNOWN; - } +// Returns a string indicating the subchannel's connectivity state change to +// \a state. +const char* SubchannelConnectivityStateChangeString( + grpc_connectivity_state state) { + switch (state) { + case GRPC_CHANNEL_IDLE: + return "Subchannel state change to IDLE"; + case GRPC_CHANNEL_CONNECTING: + return "Subchannel state change to CONNECTING"; + case GRPC_CHANNEL_READY: + return "Subchannel state change to READY"; + case GRPC_CHANNEL_TRANSIENT_FAILURE: + return "Subchannel state change to TRANSIENT_FAILURE"; + case GRPC_CHANNEL_SHUTDOWN: + return "Subchannel state change to SHUTDOWN"; } - GRPC_ERROR_UNREF(error); + GPR_UNREACHABLE_CODE(return "UNKNOWN"); } -static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { - grpc_subchannel_call* call = static_cast(arg); - GPR_ASSERT(call->recv_trailing_metadata != nullptr); - grpc_status_code status = GRPC_STATUS_OK; - grpc_metadata_batch* md_batch = call->recv_trailing_metadata; - get_call_status(call, md_batch, GRPC_ERROR_REF(error), &status); - grpc_core::channelz::SubchannelNode* channelz_subchannel = - call->connection->channelz_subchannel(); - GPR_ASSERT(channelz_subchannel != nullptr); - if (status == GRPC_STATUS_OK) { - channelz_subchannel->RecordCallSucceeded(); - } else { - channelz_subchannel->RecordCallFailed(); +} // namespace + +void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state, + grpc_error* error, + const char* reason) { + if (channelz_node_ != nullptr) { + channelz_node_->AddTraceEvent( + channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string( + SubchannelConnectivityStateChangeString(state))); } - GRPC_CLOSURE_RUN(call->original_recv_trailing_metadata, - GRPC_ERROR_REF(error)); + grpc_connectivity_state_set(&state_tracker_, state, error, reason); } -// If channelz is enabled, intercept recv_trailing so that we may check the -// status and associate it to a subchannel. -static void maybe_intercept_recv_trailing_metadata( - grpc_subchannel_call* call, grpc_transport_stream_op_batch* batch) { - // only intercept payloads with recv trailing. - if (!batch->recv_trailing_metadata) { +void Subchannel::MaybeStartConnectingLocked() { + if (disconnected_) { + // Don't try to connect if we're already disconnected. return; } - // only add interceptor is channelz is enabled. - if (call->connection->channelz_subchannel() == nullptr) { + if (connecting_) { + // Already connecting: don't restart. return; } - GRPC_CLOSURE_INIT(&call->recv_trailing_metadata_ready, - recv_trailing_metadata_ready, call, - grpc_schedule_on_exec_ctx); - // save some state needed for the interception callback. - GPR_ASSERT(call->recv_trailing_metadata == nullptr); - call->recv_trailing_metadata = - batch->payload->recv_trailing_metadata.recv_trailing_metadata; - call->original_recv_trailing_metadata = - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = - &call->recv_trailing_metadata_ready; -} - -void grpc_subchannel_call_process_op(grpc_subchannel_call* call, - grpc_transport_stream_op_batch* batch) { - GPR_TIMER_SCOPE("grpc_subchannel_call_process_op", 0); - maybe_intercept_recv_trailing_metadata(call, batch); - grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call); - grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0); - GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch); - top_elem->filter->start_transport_stream_op_batch(top_elem, batch); + if (connected_subchannel_ != nullptr) { + // Already connected: don't restart. + return; + } + if (!grpc_connectivity_state_has_watchers(&state_tracker_) && + !grpc_connectivity_state_has_watchers(&state_and_health_tracker_)) { + // Nobody is interested in connecting: so don't just yet. + return; + } + connecting_ = true; + GRPC_SUBCHANNEL_WEAK_REF(this, "connecting"); + if (!backoff_begun_) { + backoff_begun_ = true; + ContinueConnectingLocked(); + } else { + GPR_ASSERT(!have_retry_alarm_); + have_retry_alarm_ = true; + const grpc_millis time_til_next = + next_attempt_deadline_ - ExecCtx::Get()->Now(); + if (time_til_next <= 0) { + gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", this); + } else { + gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRId64 " milliseconds", + this, time_til_next); + } + GRPC_CLOSURE_INIT(&on_retry_alarm_, OnRetryAlarm, this, + grpc_schedule_on_exec_ctx); + grpc_timer_init(&retry_alarm_, next_attempt_deadline_, &on_retry_alarm_); + } } -grpc_core::RefCountedPtr -grpc_subchannel_get_connected_subchannel(grpc_subchannel* c) { - gpr_mu_lock(&c->mu); - auto copy = c->connected_subchannel; - gpr_mu_unlock(&c->mu); - return copy; +void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { + Subchannel* c = static_cast(arg); + gpr_mu_lock(&c->mu_); + c->have_retry_alarm_ = false; + if (c->disconnected_) { + error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", + &error, 1); + } else if (c->retry_immediately_) { + c->retry_immediately_ = false; + error = GRPC_ERROR_NONE; + } else { + GRPC_ERROR_REF(error); + } + if (error == GRPC_ERROR_NONE) { + gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); + c->ContinueConnectingLocked(); + gpr_mu_unlock(&c->mu_); + } else { + gpr_mu_unlock(&c->mu_); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } + GRPC_ERROR_UNREF(error); } -void* grpc_connected_subchannel_call_get_parent_data( - grpc_subchannel_call* subchannel_call) { - grpc_channel_stack* chanstk = subchannel_call->connection->channel_stack(); - return (char*)subchannel_call + - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_subchannel_call)) + - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(chanstk->call_stack_size); +void Subchannel::ContinueConnectingLocked() { + grpc_connect_in_args args; + args.interested_parties = pollset_set_; + const grpc_millis min_deadline = + min_connect_timeout_ms_ + ExecCtx::Get()->Now(); + next_attempt_deadline_ = backoff_.NextAttemptTime(); + args.deadline = std::max(next_attempt_deadline_, min_deadline); + args.channel_args = args_; + SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, + "connecting"); + grpc_connectivity_state_set(&state_and_health_tracker_, + GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, + "connecting"); + grpc_connector_connect(connector_, &args, &connecting_result_, + &on_connecting_finished_); } -grpc_call_stack* grpc_subchannel_call_get_call_stack( - grpc_subchannel_call* subchannel_call) { - return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call); -} +void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) { + auto* c = static_cast(arg); + grpc_channel_args* delete_channel_args = c->connecting_result_.channel_args; + GRPC_SUBCHANNEL_WEAK_REF(c, "on_connecting_finished"); + gpr_mu_lock(&c->mu_); + c->connecting_ = false; + if (c->connecting_result_.transport != nullptr && + c->PublishTransportLocked()) { + // Do nothing, transport was published. + } else if (c->disconnected_) { + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } else { + c->SetConnectivityStateLocked( + GRPC_CHANNEL_TRANSIENT_FAILURE, + grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Connect Failed", &error, 1), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), + "connect_failed"); + grpc_connectivity_state_set( + &c->state_and_health_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE, + grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Connect Failed", &error, 1), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), + "connect_failed"); -static void grpc_uri_to_sockaddr(const char* uri_str, - grpc_resolved_address* addr) { - grpc_uri* uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */); - GPR_ASSERT(uri != nullptr); - if (!grpc_parse_uri(uri, addr)) memset(addr, 0, sizeof(*addr)); - grpc_uri_destroy(uri); -} + const char* errmsg = grpc_error_string(error); + gpr_log(GPR_INFO, "Connect failed: %s", errmsg); -void grpc_get_subchannel_address_arg(const grpc_channel_args* args, - grpc_resolved_address* addr) { - const char* addr_uri_str = grpc_get_subchannel_address_uri_arg(args); - memset(addr, 0, sizeof(*addr)); - if (*addr_uri_str != '\0') { - grpc_uri_to_sockaddr(addr_uri_str, addr); + c->MaybeStartConnectingLocked(); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); } + gpr_mu_unlock(&c->mu_); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "on_connecting_finished"); + grpc_channel_args_destroy(delete_channel_args); } -const char* grpc_subchannel_get_target(grpc_subchannel* subchannel) { - const grpc_arg* addr_arg = - grpc_channel_args_find(subchannel->args, GRPC_ARG_SUBCHANNEL_ADDRESS); - const char* addr_str = grpc_channel_arg_get_string(addr_arg); - GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. - return addr_str; -} - -const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args) { - const grpc_arg* addr_arg = - grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); - const char* addr_str = grpc_channel_arg_get_string(addr_arg); - GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. - return addr_str; -} - -grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr) { - return grpc_channel_arg_string_create( - (char*)GRPC_ARG_SUBCHANNEL_ADDRESS, - addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup("")); -} - -namespace grpc_core { - -ConnectedSubchannel::ConnectedSubchannel( - grpc_channel_stack* channel_stack, const grpc_channel_args* args, - grpc_core::RefCountedPtr - channelz_subchannel, - intptr_t socket_uuid) - : RefCounted(&grpc_trace_stream_refcount), - channel_stack_(channel_stack), - args_(grpc_channel_args_copy(args)), - channelz_subchannel_(std::move(channelz_subchannel)), - socket_uuid_(socket_uuid) {} +namespace { -ConnectedSubchannel::~ConnectedSubchannel() { - grpc_channel_args_destroy(args_); - GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor"); +void ConnectionDestroy(void* arg, grpc_error* error) { + grpc_channel_stack* stk = static_cast(arg); + grpc_channel_stack_destroy(stk); + gpr_free(stk); } -void ConnectedSubchannel::NotifyOnStateChange( - grpc_pollset_set* interested_parties, grpc_connectivity_state* state, - grpc_closure* closure) { - grpc_transport_op* op = grpc_make_transport_op(nullptr); - grpc_channel_element* elem; - op->connectivity_state = state; - op->on_connectivity_state_change = closure; - op->bind_pollset_set = interested_parties; - elem = grpc_channel_stack_element(channel_stack_, 0); - elem->filter->start_transport_op(elem, op); -} +} // namespace -void ConnectedSubchannel::Ping(grpc_closure* on_initiate, - grpc_closure* on_ack) { - grpc_transport_op* op = grpc_make_transport_op(nullptr); - grpc_channel_element* elem; - op->send_ping.on_initiate = on_initiate; - op->send_ping.on_ack = on_ack; - elem = grpc_channel_stack_element(channel_stack_, 0); - elem->filter->start_transport_op(elem, op); +bool Subchannel::PublishTransportLocked() { + // Construct channel stack. + grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create(); + grpc_channel_stack_builder_set_channel_arguments( + builder, connecting_result_.channel_args); + grpc_channel_stack_builder_set_transport(builder, + connecting_result_.transport); + if (!grpc_channel_init_create_stack(builder, GRPC_CLIENT_SUBCHANNEL)) { + grpc_channel_stack_builder_destroy(builder); + return false; + } + grpc_channel_stack* stk; + grpc_error* error = grpc_channel_stack_builder_finish( + builder, 0, 1, ConnectionDestroy, nullptr, + reinterpret_cast(&stk)); + if (error != GRPC_ERROR_NONE) { + grpc_transport_destroy(connecting_result_.transport); + gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", + grpc_error_string(error)); + GRPC_ERROR_UNREF(error); + return false; + } + intptr_t socket_uuid = connecting_result_.socket_uuid; + memset(&connecting_result_, 0, sizeof(connecting_result_)); + if (disconnected_) { + grpc_channel_stack_destroy(stk); + gpr_free(stk); + return false; + } + // Publish. + connected_subchannel_.reset( + New(stk, args_, channelz_node_, socket_uuid)); + gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p", + connected_subchannel_.get(), this); + // Instantiate state watcher. Will clean itself up. + connected_subchannel_watcher_ = + MakeOrphanable(this); + return true; } -grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, - grpc_subchannel_call** call) { - const size_t allocation_size = - GetInitialCallSizeEstimate(args.parent_data_size); - *call = new (gpr_arena_alloc(args.arena, allocation_size)) - grpc_subchannel_call(this, args); - grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call); - RefCountedPtr connection = - Ref(DEBUG_LOCATION, "subchannel_call"); - connection.release(); // Ref is passed to the grpc_subchannel_call object. - const grpc_call_element_args call_args = { - callstk, /* call_stack */ - nullptr, /* server_transport_data */ - args.context, /* context */ - args.path, /* path */ - args.start_time, /* start_time */ - args.deadline, /* deadline */ - args.arena, /* arena */ - args.call_combiner /* call_combiner */ - }; - grpc_error* error = grpc_call_stack_init( - channel_stack_, 1, subchannel_call_destroy, *call, &call_args); - if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { - const char* error_string = grpc_error_string(error); - gpr_log(GPR_ERROR, "error: %s", error_string); - return error; - } - grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); - if (channelz_subchannel_ != nullptr) { - channelz_subchannel_->RecordCallStarted(); +void Subchannel::Disconnect() { + // The subchannel_pool is only used once here in this subchannel, so the + // access can be outside of the lock. + if (subchannel_pool_ != nullptr) { + subchannel_pool_->UnregisterSubchannel(key_); + subchannel_pool_.reset(); } - return GRPC_ERROR_NONE; + MutexLock lock(&mu_); + GPR_ASSERT(!disconnected_); + disconnected_ = true; + grpc_connector_shutdown(connector_, GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Subchannel disconnected")); + connected_subchannel_.reset(); + connected_subchannel_watcher_.reset(); } -size_t ConnectedSubchannel::GetInitialCallSizeEstimate( - size_t parent_data_size) const { - size_t allocation_size = - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_subchannel_call)); - if (parent_data_size > 0) { - allocation_size += - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) + - parent_data_size; - } else { - allocation_size += channel_stack_->call_stack_size; +gpr_atm Subchannel::RefMutate( + gpr_atm delta, int barrier GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS) { + gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&ref_pair_, delta) + : gpr_atm_no_barrier_fetch_add(&ref_pair_, delta); +#ifndef NDEBUG + if (grpc_trace_stream_refcount.enabled()) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", this, + purpose, old_val, old_val + delta, reason); } - return allocation_size; +#endif + return old_val; } } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index fac515eee5c..88282c9d95e 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -24,53 +24,49 @@ #include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/connector.h" #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" +#include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/gpr/arena.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/metadata.h" // Channel arg containing a grpc_resolved_address to connect to. #define GRPC_ARG_SUBCHANNEL_ADDRESS "grpc.subchannel_address" -/** A (sub-)channel that knows how to connect to exactly one target - address. Provides a target for load balancing. */ -typedef struct grpc_subchannel grpc_subchannel; -typedef struct grpc_subchannel_call grpc_subchannel_call; - +// For debugging refcounting. #ifndef NDEBUG -#define GRPC_SUBCHANNEL_REF(p, r) \ - grpc_subchannel_ref((p), __FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_REF(p, r) (p)->Ref(__FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \ - grpc_subchannel_ref_from_weak_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_UNREF(p, r) \ - grpc_subchannel_unref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_WEAK_REF(p, r) \ - grpc_subchannel_weak_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) \ - grpc_subchannel_weak_unref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_CALL_REF(p, r) \ - grpc_subchannel_call_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_CALL_UNREF(p, r) \ - grpc_subchannel_call_unref((p), __FILE__, __LINE__, (r)) + (p)->RefFromWeakRef(__FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_UNREF(p, r) (p)->Unref(__FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_WEAK_REF(p, r) (p)->WeakRef(__FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) (p)->WeakUnref(__FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS \ - , const char *file, int line, const char *reason + const char *file, int line, const char *reason +#define GRPC_SUBCHANNEL_REF_REASON reason +#define GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS \ + , GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char* purpose +#define GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE(x) , file, line, reason, x #else -#define GRPC_SUBCHANNEL_REF(p, r) grpc_subchannel_ref((p)) -#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \ - grpc_subchannel_ref_from_weak_ref((p)) -#define GRPC_SUBCHANNEL_UNREF(p, r) grpc_subchannel_unref((p)) -#define GRPC_SUBCHANNEL_WEAK_REF(p, r) grpc_subchannel_weak_ref((p)) -#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) grpc_subchannel_weak_unref((p)) -#define GRPC_SUBCHANNEL_CALL_REF(p, r) grpc_subchannel_call_ref((p)) -#define GRPC_SUBCHANNEL_CALL_UNREF(p, r) grpc_subchannel_call_unref((p)) +#define GRPC_SUBCHANNEL_REF(p, r) (p)->Ref() +#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) (p)->RefFromWeakRef() +#define GRPC_SUBCHANNEL_UNREF(p, r) (p)->Unref() +#define GRPC_SUBCHANNEL_WEAK_REF(p, r) (p)->WeakRef() +#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) (p)->WeakUnref() #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS +#define GRPC_SUBCHANNEL_REF_REASON "" +#define GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS +#define GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE(x) #endif namespace grpc_core { +class SubchannelCall; + class ConnectedSubchannel : public RefCounted { public: struct CallArgs { @@ -86,8 +82,7 @@ class ConnectedSubchannel : public RefCounted { ConnectedSubchannel( grpc_channel_stack* channel_stack, const grpc_channel_args* args, - grpc_core::RefCountedPtr - channelz_subchannel, + RefCountedPtr channelz_subchannel, intptr_t socket_uuid); ~ConnectedSubchannel(); @@ -95,7 +90,8 @@ class ConnectedSubchannel : public RefCounted { grpc_connectivity_state* state, grpc_closure* closure); void Ping(grpc_closure* on_initiate, grpc_closure* on_ack); - grpc_error* CreateCall(const CallArgs& args, grpc_subchannel_call** call); + RefCountedPtr CreateCall(const CallArgs& args, + grpc_error** error); grpc_channel_stack* channel_stack() const { return channel_stack_; } const grpc_channel_args* args() const { return args_; } @@ -111,91 +107,204 @@ class ConnectedSubchannel : public RefCounted { grpc_channel_args* args_; // ref counted pointer to the channelz node in this connected subchannel's // owning subchannel. - grpc_core::RefCountedPtr - channelz_subchannel_; + RefCountedPtr channelz_subchannel_; // uuid of this subchannel's socket. 0 if this subchannel is not connected. const intptr_t socket_uuid_; }; -} // namespace grpc_core +// Implements the interface of RefCounted<>. +class SubchannelCall { + public: + SubchannelCall(RefCountedPtr connected_subchannel, + const ConnectedSubchannel::CallArgs& args) + : connected_subchannel_(std::move(connected_subchannel)), + deadline_(args.deadline) {} + + // Continues processing a transport stream op batch. + void StartTransportStreamOpBatch(grpc_transport_stream_op_batch* batch); + + // Returns a pointer to the parent data associated with the subchannel call. + // The data will be of the size specified in \a parent_data_size field of + // the args passed to \a ConnectedSubchannel::CreateCall(). + void* GetParentData(); + + // Returns the call stack of the subchannel call. + grpc_call_stack* GetCallStack(); + + grpc_closure* after_call_stack_destroy() const { + return after_call_stack_destroy_; + } + + // Sets the 'then_schedule_closure' argument for call stack destruction. + // Must be called once per call. + void SetAfterCallStackDestroy(grpc_closure* closure); + + // Interface of RefCounted<>. + RefCountedPtr Ref() GRPC_MUST_USE_RESULT; + RefCountedPtr Ref(const DebugLocation& location, + const char* reason) GRPC_MUST_USE_RESULT; + // When refcount drops to 0, destroys itself and the associated call stack, + // but does NOT free the memory because it's in the call arena. + void Unref(); + void Unref(const DebugLocation& location, const char* reason); + + private: + // Allow RefCountedPtr<> to access IncrementRefCount(). + template + friend class RefCountedPtr; + + // If channelz is enabled, intercepts recv_trailing so that we may check the + // status and associate it to a subchannel. + void MaybeInterceptRecvTrailingMetadata( + grpc_transport_stream_op_batch* batch); + + static void RecvTrailingMetadataReady(void* arg, grpc_error* error); + + // Interface of RefCounted<>. + void IncrementRefCount(); + void IncrementRefCount(const DebugLocation& location, const char* reason); + + RefCountedPtr connected_subchannel_; + grpc_closure* after_call_stack_destroy_ = nullptr; + // State needed to support channelz interception of recv trailing metadata. + grpc_closure recv_trailing_metadata_ready_; + grpc_closure* original_recv_trailing_metadata_ = nullptr; + grpc_metadata_batch* recv_trailing_metadata_ = nullptr; + grpc_millis deadline_; +}; + +// A subchannel that knows how to connect to exactly one target address. It +// provides a target for load balancing. +class Subchannel { + public: + // The ctor and dtor are not intended to use directly. + Subchannel(SubchannelKey* key, grpc_connector* connector, + const grpc_channel_args* args); + ~Subchannel(); + + // Creates a subchannel given \a connector and \a args. + static Subchannel* Create(grpc_connector* connector, + const grpc_channel_args* args); + + // Strong and weak refcounting. + Subchannel* Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + void Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + Subchannel* WeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + void WeakUnref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + Subchannel* RefFromWeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + + intptr_t GetChildSocketUuid(); -grpc_subchannel* grpc_subchannel_ref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -grpc_subchannel* grpc_subchannel_ref_from_weak_ref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -void grpc_subchannel_unref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -grpc_subchannel* grpc_subchannel_weak_ref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -void grpc_subchannel_weak_unref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -grpc_subchannel_call* grpc_subchannel_call_ref( - grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -void grpc_subchannel_call_unref( - grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS); - -grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node( - grpc_subchannel* subchannel); - -intptr_t grpc_subchannel_get_child_socket_uuid(grpc_subchannel* subchannel); - -/** Returns a pointer to the parent data associated with \a subchannel_call. - The data will be of the size specified in \a parent_data_size - field of the args passed to \a grpc_connected_subchannel_create_call(). */ -void* grpc_connected_subchannel_call_get_parent_data( - grpc_subchannel_call* subchannel_call); - -/** poll the current connectivity state of a channel */ -grpc_connectivity_state grpc_subchannel_check_connectivity( - grpc_subchannel* channel, grpc_error** error, bool inhibit_health_checking); - -/** Calls notify when the connectivity state of a channel becomes different - from *state. Updates *state with the new state of the channel. */ -void grpc_subchannel_notify_on_state_change( - grpc_subchannel* channel, grpc_pollset_set* interested_parties, - grpc_connectivity_state* state, grpc_closure* notify, - bool inhibit_health_checks); - -/** retrieve the grpc_core::ConnectedSubchannel - or nullptr if not connected - * (which may happen before it initially connects or during transient failures) - * */ -grpc_core::RefCountedPtr -grpc_subchannel_get_connected_subchannel(grpc_subchannel* c); - -// Resets the connection backoff of the subchannel. -// TODO(roth): Move connection backoff out of subchannels and up into LB -// policy code (probably by adding a SubchannelGroup between -// SubchannelList and SubchannelData), at which point this method can -// go away. -void grpc_subchannel_reset_backoff(grpc_subchannel* subchannel); - -/** continue processing a transport op */ -void grpc_subchannel_call_process_op(grpc_subchannel_call* subchannel_call, - grpc_transport_stream_op_batch* op); - -/** Must be called once per call. Sets the 'then_schedule_closure' argument for - call stack destruction. */ -void grpc_subchannel_call_set_cleanup_closure( - grpc_subchannel_call* subchannel_call, grpc_closure* closure); - -grpc_call_stack* grpc_subchannel_call_get_call_stack( - grpc_subchannel_call* subchannel_call); - -/** create a subchannel given a connector */ -grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, - const grpc_channel_args* args); - -/// Sets \a addr from \a args. -void grpc_get_subchannel_address_arg(const grpc_channel_args* args, - grpc_resolved_address* addr); - -const char* grpc_subchannel_get_target(grpc_subchannel* subchannel); - -/// Returns the URI string for the address to connect to. -const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args); - -/// Returns a new channel arg encoding the subchannel address as a string. -/// Caller is responsible for freeing the string. -grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr); + // Gets the string representing the subchannel address. + // Caller doesn't take ownership. + const char* GetTargetAddress(); + + // Gets the connected subchannel - or nullptr if not connected (which may + // happen before it initially connects or during transient failures). + RefCountedPtr connected_subchannel(); + + channelz::SubchannelNode* channelz_node(); + + // Polls the current connectivity state of the subchannel. + grpc_connectivity_state CheckConnectivity(grpc_error** error, + bool inhibit_health_checking); + + // When the connectivity state of the subchannel changes from \a *state, + // invokes \a notify and updates \a *state with the new state. + void NotifyOnStateChange(grpc_pollset_set* interested_parties, + grpc_connectivity_state* state, grpc_closure* notify, + bool inhibit_health_checks); + + // Resets the connection backoff of the subchannel. + // TODO(roth): Move connection backoff out of subchannels and up into LB + // policy code (probably by adding a SubchannelGroup between + // SubchannelList and SubchannelData), at which point this method can + // go away. + void ResetBackoff(); + + // Returns a new channel arg encoding the subchannel address as a URI + // string. Caller is responsible for freeing the string. + static grpc_arg CreateSubchannelAddressArg(const grpc_resolved_address* addr); + + // Returns the URI string from the subchannel address arg in \a args. + static const char* GetUriFromSubchannelAddressArg( + const grpc_channel_args* args); + + // Sets \a addr from the subchannel address arg in \a args. + static void GetAddressFromSubchannelAddressArg(const grpc_channel_args* args, + grpc_resolved_address* addr); + + private: + struct ExternalStateWatcher; + class ConnectedSubchannelStateWatcher; + + // Sets the subchannel's connectivity state to \a state. + void SetConnectivityStateLocked(grpc_connectivity_state state, + grpc_error* error, const char* reason); + + // Methods for connection. + void MaybeStartConnectingLocked(); + static void OnRetryAlarm(void* arg, grpc_error* error); + void ContinueConnectingLocked(); + static void OnConnectingFinished(void* arg, grpc_error* error); + bool PublishTransportLocked(); + void Disconnect(); + + gpr_atm RefMutate(gpr_atm delta, + int barrier GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS); + + // The subchannel pool this subchannel is in. + RefCountedPtr subchannel_pool_; + // TODO(juanlishen): Consider using args_ as key_ directly. + // Subchannel key that identifies this subchannel in the subchannel pool. + SubchannelKey* key_; + // Channel args. + grpc_channel_args* args_; + // pollset_set tracking who's interested in a connection being setup. + grpc_pollset_set* pollset_set_; + // Protects the other members. + gpr_mu mu_; + // Refcount + // - lower INTERNAL_REF_BITS bits are for internal references: + // these do not keep the subchannel open. + // - upper remaining bits are for public references: these do + // keep the subchannel open + gpr_atm ref_pair_; + + // Connection states. + grpc_connector* connector_ = nullptr; + // Set during connection. + grpc_connect_out_args connecting_result_; + grpc_closure on_connecting_finished_; + // Active connection, or null. + RefCountedPtr connected_subchannel_; + OrphanablePtr connected_subchannel_watcher_; + bool connecting_ = false; + bool disconnected_ = false; + + // Connectivity state tracking. + grpc_connectivity_state_tracker state_tracker_; + grpc_connectivity_state_tracker state_and_health_tracker_; + UniquePtr health_check_service_name_; + ExternalStateWatcher* external_state_watcher_list_ = nullptr; + + // Backoff state. + BackOff backoff_; + grpc_millis next_attempt_deadline_; + grpc_millis min_connect_timeout_ms_; + bool backoff_begun_ = false; + + // Retry alarm. + grpc_timer retry_alarm_; + grpc_closure on_retry_alarm_; + bool have_retry_alarm_ = false; + // reset_backoff() was called while alarm was pending. + bool retry_immediately_ = false; + + // Channelz tracking. + RefCountedPtr channelz_node_; +}; + +} // namespace grpc_core #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_H */ diff --git a/src/core/ext/filters/client_channel/subchannel_pool_interface.h b/src/core/ext/filters/client_channel/subchannel_pool_interface.h index 21597bf4276..eeb56faf0c0 100644 --- a/src/core/ext/filters/client_channel/subchannel_pool_interface.h +++ b/src/core/ext/filters/client_channel/subchannel_pool_interface.h @@ -26,10 +26,10 @@ #include "src/core/lib/gprpp/abstract.h" #include "src/core/lib/gprpp/ref_counted.h" -struct grpc_subchannel; - namespace grpc_core { +class Subchannel; + extern TraceFlag grpc_subchannel_pool_trace; // A key that can uniquely identify a subchannel. @@ -69,15 +69,15 @@ class SubchannelPoolInterface : public RefCounted { // Registers a subchannel against a key. Returns the subchannel registered // with \a key, which may be different from \a constructed because we reuse // (instead of update) any existing subchannel already registered with \a key. - virtual grpc_subchannel* RegisterSubchannel( - SubchannelKey* key, grpc_subchannel* constructed) GRPC_ABSTRACT; + virtual Subchannel* RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) GRPC_ABSTRACT; // Removes the registered subchannel found by \a key. virtual void UnregisterSubchannel(SubchannelKey* key) GRPC_ABSTRACT; // Finds the subchannel registered for the given subchannel key. Returns NULL // if no such channel exists. Thread-safe. - virtual grpc_subchannel* FindSubchannel(SubchannelKey* key) GRPC_ABSTRACT; + virtual Subchannel* FindSubchannel(SubchannelKey* key) GRPC_ABSTRACT; // Creates a channel arg from \a subchannel pool. static grpc_arg CreateChannelArg(SubchannelPoolInterface* subchannel_pool); diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.cc b/src/core/ext/transport/chttp2/client/chttp2_connector.cc index 42a2e2e896c..1e9a75d0630 100644 --- a/src/core/ext/transport/chttp2/client/chttp2_connector.cc +++ b/src/core/ext/transport/chttp2/client/chttp2_connector.cc @@ -202,7 +202,8 @@ static void chttp2_connector_connect(grpc_connector* con, grpc_closure* notify) { chttp2_connector* c = reinterpret_cast(con); grpc_resolved_address addr; - grpc_get_subchannel_address_arg(args->channel_args, &addr); + grpc_core::Subchannel::GetAddressFromSubchannelAddressArg(args->channel_args, + &addr); gpr_mu_lock(&c->mu); GPR_ASSERT(c->notify == nullptr); c->notify = notify; 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 a5bf1bf21d4..8aabcfa2000 100644 --- a/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.cc @@ -39,11 +39,11 @@ static void client_channel_factory_ref( static void client_channel_factory_unref( grpc_client_channel_factory* cc_factory) {} -static grpc_subchannel* client_channel_factory_create_subchannel( +static grpc_core::Subchannel* client_channel_factory_create_subchannel( 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, new_args); + grpc_core::Subchannel* s = grpc_core::Subchannel::Create(connector, new_args); grpc_connector_unref(connector); 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 5985fa0cbdb..eb2fee2af91 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 @@ -76,7 +76,8 @@ static grpc_channel_args* get_secure_naming_channel_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); + const char* target_uri_str = + grpc_core::Subchannel::GetUriFromSubchannelAddressArg(args); grpc_uri* target_uri = grpc_uri_parse(target_uri_str, false /* suppress errors */); GPR_ASSERT(target_uri != nullptr); @@ -138,7 +139,7 @@ static grpc_channel_args* get_secure_naming_channel_args( return new_args; } -static grpc_subchannel* client_channel_factory_create_subchannel( +static grpc_core::Subchannel* client_channel_factory_create_subchannel( 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) { @@ -147,7 +148,7 @@ static grpc_subchannel* client_channel_factory_create_subchannel( return nullptr; } grpc_connector* connector = grpc_chttp2_connector_create(); - grpc_subchannel* s = grpc_subchannel_create(connector, new_args); + grpc_core::Subchannel* s = grpc_core::Subchannel::Create(connector, new_args); grpc_connector_unref(connector); grpc_channel_args_destroy(new_args); return s; diff --git a/test/core/util/debugger_macros.cc b/test/core/util/debugger_macros.cc index 05fb1461733..fed6ad97285 100644 --- a/test/core/util/debugger_macros.cc +++ b/test/core/util/debugger_macros.cc @@ -36,13 +36,14 @@ grpc_stream* grpc_transport_stream_from_call(grpc_call* call) { for (;;) { grpc_call_element* el = grpc_call_stack_element(cs, cs->count - 1); if (el->filter == &grpc_client_channel_filter) { - grpc_subchannel_call* scc = grpc_client_channel_get_subchannel_call(el); + grpc_core::RefCountedPtr scc = + grpc_client_channel_get_subchannel_call(el); if (scc == nullptr) { fprintf(stderr, "No subchannel-call"); fflush(stderr); return nullptr; } - cs = grpc_subchannel_call_get_call_stack(scc); + cs = scc->GetCallStack(); } else if (el->filter == &grpc_connected_filter) { return grpc_connected_channel_get_stream(el); } else { diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc index 125b1ce5c4e..973f47beaf7 100644 --- a/test/cpp/microbenchmarks/bm_call_create.cc +++ b/test/cpp/microbenchmarks/bm_call_create.cc @@ -325,8 +325,8 @@ class FakeClientChannelFactory : public grpc_client_channel_factory { private: 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_channel_args* args) { + static grpc_core::Subchannel* CreateSubchannel( + grpc_client_channel_factory* factory, const grpc_channel_args* args) { return nullptr; } static grpc_channel* CreateClientChannel(grpc_client_channel_factory* factory, From b20f15892217698f2bb9f9c8ad7bf26607953329 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Tue, 29 Jan 2019 12:40:31 -0800 Subject: [PATCH 101/218] Deflake a shared CQ usage --- test/cpp/end2end/generic_end2end_test.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc index 015862bfe81..8c4b3cf1fd3 100644 --- a/test/cpp/end2end/generic_end2end_test.cc +++ b/test/cpp/end2end/generic_end2end_test.cc @@ -17,6 +17,7 @@ */ #include +#include #include #include @@ -219,10 +220,11 @@ TEST_F(GenericEnd2endTest, SequentialUnaryRpcs) { // Use the same cq as server so that events can be polled in time. std::unique_ptr call = generic_stub_->PrepareUnaryCall(&cli_ctx, kMethodName, - *cli_send_buffer.get(), srv_cq_.get()); + *cli_send_buffer.get(), &cli_cq_); call->StartCall(); ByteBuffer cli_recv_buffer; call->Finish(&cli_recv_buffer, &recv_status, tag(1)); + std::thread client_check([this] { client_ok(1); }); generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(), srv_cq_.get(), tag(4)); @@ -246,7 +248,7 @@ TEST_F(GenericEnd2endTest, SequentialUnaryRpcs) { stream.Finish(Status::OK, tag(7)); server_ok(7); - verify_ok(srv_cq_.get(), 1, true); + client_check.join(); EXPECT_TRUE(ParseFromByteBuffer(&cli_recv_buffer, &recv_response)); EXPECT_EQ(send_response.message(), recv_response.message()); EXPECT_TRUE(recv_status.ok()); From 7da0aacef2886d5556a043fc3b6400db9daa5424 Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Tue, 29 Jan 2019 13:50:16 -0800 Subject: [PATCH 102/218] Revert "Merge pull request #17644 from lidizheng/bzl-py3" This reverts commit a25828ad784e4302699c00751ebe1191462caee8, reversing changes made to 5176fd80fc160c492cb6529569bde5f36e1ecf44. --- BUILD | 5 --- src/python/grpcio/grpc/BUILD.bazel | 6 ++-- .../grpcio/grpc/framework/common/BUILD.bazel | 14 ++++---- .../grpc/framework/foundation/BUILD.bazel | 13 +++----- .../framework/interfaces/base/BUILD.bazel | 13 +++----- .../framework/interfaces/face/BUILD.bazel | 6 ++-- .../grpcio_status/grpc_status/rpc_status.py | 5 +++ src/python/grpcio_tests/tests/BUILD.bazel | 8 ----- .../tests/bazel_namespace_package_hack.py | 32 ------------------- .../grpcio_tests/tests/interop/BUILD.bazel | 7 ++-- .../grpcio_tests/tests/interop/methods.py | 3 -- .../reflection/_reflection_servicer_test.py | 20 +++--------- .../grpcio_tests/tests/status/BUILD.bazel | 1 - .../tests/status/_grpc_status_test.py | 3 -- third_party/py/python_configure.bzl | 11 +++---- tools/bazel.rc | 4 --- .../linux/grpc_python_bazel_test_in_docker.sh | 2 -- 17 files changed, 36 insertions(+), 117 deletions(-) delete mode 100644 src/python/grpcio_tests/tests/BUILD.bazel delete mode 100644 src/python/grpcio_tests/tests/bazel_namespace_package_hack.py diff --git a/BUILD b/BUILD index ff066edaeaf..3f1e735466d 100644 --- a/BUILD +++ b/BUILD @@ -63,11 +63,6 @@ config_setting( values = {"cpu": "x64_windows_msvc"}, ) -config_setting( - name = "python3", - values = {"python_path": "python3"}, -) - # This should be updated along with build.yaml g_stands_for = "gold" diff --git a/src/python/grpcio/grpc/BUILD.bazel b/src/python/grpcio/grpc/BUILD.bazel index 27d5d2e4bb2..6958ccdfb66 100644 --- a/src/python/grpcio/grpc/BUILD.bazel +++ b/src/python/grpcio/grpc/BUILD.bazel @@ -15,11 +15,9 @@ py_library( "//src/python/grpcio/grpc/_cython:cygrpc", "//src/python/grpcio/grpc/experimental", "//src/python/grpcio/grpc/framework", + requirement('enum34'), requirement('six'), - ] + select({ - "//conditions:default": [requirement('enum34'),], - "//:python3": [], - }), + ], data = [ "//:grpc", ], diff --git a/src/python/grpcio/grpc/framework/common/BUILD.bazel b/src/python/grpcio/grpc/framework/common/BUILD.bazel index 52fbb2b516c..9d9ef682c90 100644 --- a/src/python/grpcio/grpc/framework/common/BUILD.bazel +++ b/src/python/grpcio/grpc/framework/common/BUILD.bazel @@ -13,17 +13,15 @@ py_library( py_library( name = "cardinality", srcs = ["cardinality.py"], - deps = select({ - "//conditions:default": [requirement('enum34'),], - "//:python3": [], - }), + deps = [ + requirement("enum34"), + ], ) py_library( name = "style", srcs = ["style.py"], - deps = select({ - "//conditions:default": [requirement('enum34'),], - "//:python3": [], - }), + deps = [ + requirement("enum34"), + ], ) diff --git a/src/python/grpcio/grpc/framework/foundation/BUILD.bazel b/src/python/grpcio/grpc/framework/foundation/BUILD.bazel index a447ecded49..1287fdd44ed 100644 --- a/src/python/grpcio/grpc/framework/foundation/BUILD.bazel +++ b/src/python/grpcio/grpc/framework/foundation/BUILD.bazel @@ -23,11 +23,9 @@ py_library( name = "callable_util", srcs = ["callable_util.py"], deps = [ + requirement("enum34"), requirement("six"), - ] + select({ - "//conditions:default": [requirement('enum34'),], - "//:python3": [], - }), + ], ) py_library( @@ -41,10 +39,9 @@ py_library( py_library( name = "logging_pool", srcs = ["logging_pool.py"], - deps = select({ - "//conditions:default": [requirement('futures'),], - "//:python3": [], - }), + deps = [ + requirement("futures"), + ], ) py_library( diff --git a/src/python/grpcio/grpc/framework/interfaces/base/BUILD.bazel b/src/python/grpcio/grpc/framework/interfaces/base/BUILD.bazel index 35cfe877f34..408a66a6310 100644 --- a/src/python/grpcio/grpc/framework/interfaces/base/BUILD.bazel +++ b/src/python/grpcio/grpc/framework/interfaces/base/BUILD.bazel @@ -15,18 +15,15 @@ py_library( srcs = ["base.py"], deps = [ "//src/python/grpcio/grpc/framework/foundation:abandonment", + requirement("enum34"), requirement("six"), - ] + select({ - "//conditions:default": [requirement('enum34'),], - "//:python3": [], - }), + ], ) py_library( name = "utilities", srcs = ["utilities.py"], - deps = select({ - "//conditions:default": [requirement('enum34'),], - "//:python3": [], - }), + deps = [ + requirement("enum34"), + ], ) diff --git a/src/python/grpcio/grpc/framework/interfaces/face/BUILD.bazel b/src/python/grpcio/grpc/framework/interfaces/face/BUILD.bazel index 83fadb6372e..e683e7cc426 100644 --- a/src/python/grpcio/grpc/framework/interfaces/face/BUILD.bazel +++ b/src/python/grpcio/grpc/framework/interfaces/face/BUILD.bazel @@ -16,11 +16,9 @@ py_library( deps = [ "//src/python/grpcio/grpc/framework/foundation", "//src/python/grpcio/grpc/framework/common", + requirement("enum34"), requirement("six"), - ] + select({ - "//conditions:default": [requirement('enum34'),], - "//:python3": [], - }), + ], ) py_library( diff --git a/src/python/grpcio_status/grpc_status/rpc_status.py b/src/python/grpcio_status/grpc_status/rpc_status.py index 76891e2422e..87618fa5412 100644 --- a/src/python/grpcio_status/grpc_status/rpc_status.py +++ b/src/python/grpcio_status/grpc_status/rpc_status.py @@ -17,6 +17,11 @@ import collections import grpc +# TODO(https://github.com/bazelbuild/bazel/issues/6844) +# Due to Bazel issue, the namespace packages won't resolve correctly. +# Adding this unused-import as a workaround to avoid module-not-found error +# under Bazel builds. +import google.protobuf # pylint: disable=unused-import from google.rpc import status_pb2 _CODE_TO_GRPC_CODE_MAPPING = {x.value[0]: x for x in grpc.StatusCode} diff --git a/src/python/grpcio_tests/tests/BUILD.bazel b/src/python/grpcio_tests/tests/BUILD.bazel deleted file mode 100644 index b908ab85173..00000000000 --- a/src/python/grpcio_tests/tests/BUILD.bazel +++ /dev/null @@ -1,8 +0,0 @@ -py_library( - name = "bazel_namespace_package_hack", - srcs = ["bazel_namespace_package_hack.py"], - visibility = [ - "//src/python/grpcio_tests/tests/status:__subpackages__", - "//src/python/grpcio_tests/tests/interop:__subpackages__", - ], -) diff --git a/src/python/grpcio_tests/tests/bazel_namespace_package_hack.py b/src/python/grpcio_tests/tests/bazel_namespace_package_hack.py deleted file mode 100644 index c6b72c327b1..00000000000 --- a/src/python/grpcio_tests/tests/bazel_namespace_package_hack.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2019 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. - -import os -import site -import sys - - -# TODO(https://github.com/bazelbuild/bazel/issues/6844) Bazel failed to -# interpret namespace packages correctly. This monkey patch will force the -# Python process to parse the .pth file in the sys.path to resolve namespace -# package in the right place. -# Analysis in depth: https://github.com/bazelbuild/rules_python/issues/55 -def sys_path_to_site_dir_hack(): - """Add valid sys.path item to site directory to parse the .pth files.""" - for item in sys.path: - if os.path.exists(item): - # The only difference between sys.path and site-directory is - # whether the .pth file will be parsed or not. A site-directory - # will always exist in sys.path, but not another way around. - site.addsitedir(item) diff --git a/src/python/grpcio_tests/tests/interop/BUILD.bazel b/src/python/grpcio_tests/tests/interop/BUILD.bazel index 770b1f78a70..aebdbf67ebf 100644 --- a/src/python/grpcio_tests/tests/interop/BUILD.bazel +++ b/src/python/grpcio_tests/tests/interop/BUILD.bazel @@ -29,20 +29,17 @@ py_library( srcs = ["methods.py"], deps = [ "//src/python/grpcio/grpc:grpcio", - "//src/python/grpcio_tests/tests:bazel_namespace_package_hack", "//src/proto/grpc/testing:py_empty_proto", "//src/proto/grpc/testing:py_messages_proto", "//src/proto/grpc/testing:py_test_proto", requirement('google-auth'), requirement('requests'), + requirement('enum34'), requirement('urllib3'), requirement('chardet'), requirement('certifi'), requirement('idna'), - ] + select({ - "//conditions:default": [requirement('enum34'),], - "//:python3": [], - }), + ], imports=["../../",], ) diff --git a/src/python/grpcio_tests/tests/interop/methods.py b/src/python/grpcio_tests/tests/interop/methods.py index e16966e3918..c11f6c8fad7 100644 --- a/src/python/grpcio_tests/tests/interop/methods.py +++ b/src/python/grpcio_tests/tests/interop/methods.py @@ -13,9 +13,6 @@ # limitations under the License. """Implementations of interoperability test methods.""" -from tests import bazel_namespace_package_hack -bazel_namespace_package_hack.sys_path_to_site_dir_hack() - import enum import json import os 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 37a66ad52bb..560f6d3ddb3 100644 --- a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py +++ b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py @@ -50,16 +50,6 @@ def _file_descriptor_to_proto(descriptor): class ReflectionServicerTest(unittest.TestCase): - # TODO(https://github.com/grpc/grpc/issues/17844) - # Bazel + Python 3 will result in creating two different instance of - # DESCRIPTOR for each message. So, the equal comparison between protobuf - # returned by stub and manually crafted protobuf will always fail. - def _assert_sequence_of_proto_equal(self, x, y): - self.assertSequenceEqual( - list(map(lambda x: x.SerializeToString(), x)), - list(map(lambda x: x.SerializeToString(), y)), - ) - def setUp(self): self._server = test_common.test_server() reflection.enable_server_reflection(_SERVICE_NAMES, self._server) @@ -94,7 +84,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self._assert_sequence_of_proto_equal(expected_responses, responses) + self.assertSequenceEqual(expected_responses, responses) def testFileBySymbol(self): requests = ( @@ -118,7 +108,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self._assert_sequence_of_proto_equal(expected_responses, responses) + self.assertSequenceEqual(expected_responses, responses) def testFileContainingExtension(self): requests = ( @@ -147,7 +137,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self._assert_sequence_of_proto_equal(expected_responses, responses) + self.assertSequenceEqual(expected_responses, responses) def testExtensionNumbersOfType(self): requests = ( @@ -172,7 +162,7 @@ class ReflectionServicerTest(unittest.TestCase): error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), )), ) - self._assert_sequence_of_proto_equal(expected_responses, responses) + self.assertSequenceEqual(expected_responses, responses) def testListServices(self): requests = (reflection_pb2.ServerReflectionRequest(list_services='',),) @@ -183,7 +173,7 @@ class ReflectionServicerTest(unittest.TestCase): service=tuple( reflection_pb2.ServiceResponse(name=name) for name in _SERVICE_NAMES))),) - self._assert_sequence_of_proto_equal(expected_responses, responses) + self.assertSequenceEqual(expected_responses, responses) def testReflectionServiceName(self): self.assertEqual(reflection.SERVICE_NAME, diff --git a/src/python/grpcio_tests/tests/status/BUILD.bazel b/src/python/grpcio_tests/tests/status/BUILD.bazel index b163fe3975e..937e50498e0 100644 --- a/src/python/grpcio_tests/tests/status/BUILD.bazel +++ b/src/python/grpcio_tests/tests/status/BUILD.bazel @@ -10,7 +10,6 @@ py_test( deps = [ "//src/python/grpcio/grpc:grpcio", "//src/python/grpcio_status/grpc_status:grpc_status", - "//src/python/grpcio_tests/tests:bazel_namespace_package_hack", "//src/python/grpcio_tests/tests/unit:test_common", "//src/python/grpcio_tests/tests/unit/framework/common:common", requirement('protobuf'), diff --git a/src/python/grpcio_tests/tests/status/_grpc_status_test.py b/src/python/grpcio_tests/tests/status/_grpc_status_test.py index 77f5fb283d1..519c372a960 100644 --- a/src/python/grpcio_tests/tests/status/_grpc_status_test.py +++ b/src/python/grpcio_tests/tests/status/_grpc_status_test.py @@ -13,9 +13,6 @@ # limitations under the License. """Tests of grpc_status.""" -from tests import bazel_namespace_package_hack -bazel_namespace_package_hack.sys_path_to_site_dir_hack() - import unittest import logging diff --git a/third_party/py/python_configure.bzl b/third_party/py/python_configure.bzl index 9036a95909b..2ba1e07049c 100644 --- a/third_party/py/python_configure.bzl +++ b/third_party/py/python_configure.bzl @@ -138,13 +138,10 @@ def _symlink_genrule_for_dir(repository_ctx, def _get_python_bin(repository_ctx): """Gets the python bin path.""" - python_bin = repository_ctx.os.environ.get(_PYTHON_BIN_PATH, 'python') - if not '/' in python_bin and not '\\' in python_bin: - # It's a command, use 'which' to find its path. - python_bin_path = repository_ctx.which(python_bin) - else: - # It's a path, use it as it is. - python_bin_path = python_bin + python_bin = repository_ctx.os.environ.get(_PYTHON_BIN_PATH) + if python_bin != None: + return python_bin + python_bin_path = repository_ctx.which("python") if python_bin_path != None: return str(python_bin_path) _fail("Cannot find python in PATH, please make sure " + diff --git a/tools/bazel.rc b/tools/bazel.rc index 99347495361..59e597b4723 100644 --- a/tools/bazel.rc +++ b/tools/bazel.rc @@ -57,7 +57,3 @@ build:basicprof --copt=-DNDEBUG build:basicprof --copt=-O2 build:basicprof --copt=-DGRPC_BASIC_PROFILER build:basicprof --copt=-DGRPC_TIMERS_RDTSC - -build:python3 --python_path=python3 -build:python3 --force_python=PY3 -build:python3 --action_env=PYTHON_BIN_PATH=python3 diff --git a/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh b/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh index 14989648a2a..156d65955ad 100755 --- a/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh +++ b/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh @@ -25,5 +25,3 @@ git clone /var/local/jenkins/grpc /var/local/git/grpc ${name}') cd /var/local/git/grpc/test bazel test --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... -bazel clean --expunge -bazel test --config=python3 --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... From bbfc024a02e522570e75e6645bd154568aedd022 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Tue, 29 Jan 2019 15:23:55 -0800 Subject: [PATCH 103/218] Revert "C++-ify subchannel" --- .../filters/client_channel/client_channel.cc | 114 +- .../filters/client_channel/client_channel.h | 4 +- .../client_channel/client_channel_channelz.cc | 11 +- .../client_channel/client_channel_channelz.h | 9 +- .../client_channel/client_channel_factory.cc | 2 +- .../client_channel/client_channel_factory.h | 6 +- .../client_channel/global_subchannel_pool.cc | 19 +- .../client_channel/global_subchannel_pool.h | 6 +- .../health/health_check_client.cc | 18 +- .../health/health_check_client.h | 2 +- .../lb_policy/pick_first/pick_first.cc | 2 +- .../lb_policy/round_robin/round_robin.cc | 2 +- .../lb_policy/subchannel_list.h | 37 +- .../client_channel/local_subchannel_pool.cc | 14 +- .../client_channel/local_subchannel_pool.h | 6 +- .../ext/filters/client_channel/subchannel.cc | 1436 +++++++++-------- .../ext/filters/client_channel/subchannel.h | 331 ++-- .../subchannel_pool_interface.h | 10 +- .../chttp2/client/chttp2_connector.cc | 3 +- .../chttp2/client/insecure/channel_create.cc | 4 +- .../client/secure/secure_channel_create.cc | 7 +- test/core/util/debugger_macros.cc | 5 +- test/cpp/microbenchmarks/bm_call_create.cc | 4 +- 23 files changed, 1027 insertions(+), 1025 deletions(-) diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 38525dbf97e..35c3efab6aa 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -394,7 +394,7 @@ struct subchannel_batch_data { gpr_refcount refs; grpc_call_element* elem; - grpc_core::RefCountedPtr subchannel_call; + grpc_subchannel_call* subchannel_call; // Holds a ref. // The batch to use in the subchannel call. // Its payload field points to subchannel_call_retry_state.batch_payload. grpc_transport_stream_op_batch batch; @@ -478,7 +478,7 @@ struct pending_batch { bool send_ops_cached; }; -/** Call data. Holds a pointer to SubchannelCall and the +/** Call data. Holds a pointer to grpc_subchannel_call and the associated machinery to create such a pointer. Handles queueing of stream ops until a call object is ready, waiting for initial metadata before trying to create a call object, @@ -504,6 +504,10 @@ struct call_data { last_attempt_got_server_pushback(false) {} ~call_data() { + if (GPR_LIKELY(subchannel_call != nullptr)) { + GRPC_SUBCHANNEL_CALL_UNREF(subchannel_call, + "client_channel_destroy_call"); + } grpc_slice_unref_internal(path); GRPC_ERROR_UNREF(cancel_error); for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches); ++i) { @@ -532,7 +536,7 @@ struct call_data { grpc_core::RefCountedPtr retry_throttle_data; grpc_core::RefCountedPtr method_params; - grpc_core::RefCountedPtr subchannel_call; + grpc_subchannel_call* subchannel_call = nullptr; // Set when we get a cancel_stream op. grpc_error* cancel_error = GRPC_ERROR_NONE; @@ -803,8 +807,8 @@ static void pending_batches_add(grpc_call_element* elem, calld->subchannel_call == nullptr ? nullptr : static_cast( - - calld->subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data( + calld->subchannel_call)); retry_commit(elem, retry_state); // If we are not going to retry and have not yet started, pretend // retries are disabled so that we don't bother with retry overhead. @@ -892,10 +896,10 @@ static void resume_pending_batch_in_call_combiner(void* arg, grpc_error* ignored) { grpc_transport_stream_op_batch* batch = static_cast(arg); - grpc_core::SubchannelCall* subchannel_call = - static_cast(batch->handler_private.extra_arg); + grpc_subchannel_call* subchannel_call = + static_cast(batch->handler_private.extra_arg); // Note: This will release the call combiner. - subchannel_call->StartTransportStreamOpBatch(batch); + grpc_subchannel_call_process_op(subchannel_call, batch); } // This is called via the call combiner, so access to calld is synchronized. @@ -915,7 +919,7 @@ static void pending_batches_resume(grpc_call_element* elem) { gpr_log(GPR_INFO, "chand=%p calld=%p: starting %" PRIuPTR " pending batches on subchannel_call=%p", - chand, calld, num_batches, calld->subchannel_call.get()); + chand, calld, num_batches, calld->subchannel_call); } grpc_core::CallCombinerClosureList closures; for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) { @@ -926,7 +930,7 @@ static void pending_batches_resume(grpc_call_element* elem) { maybe_inject_recv_trailing_metadata_ready_for_lb( *calld->request->pick(), batch); } - batch->handler_private.extra_arg = calld->subchannel_call.get(); + batch->handler_private.extra_arg = calld->subchannel_call; GRPC_CLOSURE_INIT(&batch->handler_private.closure, resume_pending_batch_in_call_combiner, batch, grpc_schedule_on_exec_ctx); @@ -1015,7 +1019,12 @@ static void do_retry(grpc_call_element* elem, const ClientChannelMethodParams::RetryPolicy* retry_policy = calld->method_params->retry_policy(); GPR_ASSERT(retry_policy != nullptr); - calld->subchannel_call.reset(); + // Reset subchannel call and connected subchannel. + if (calld->subchannel_call != nullptr) { + GRPC_SUBCHANNEL_CALL_UNREF(calld->subchannel_call, + "client_channel_call_retry"); + calld->subchannel_call = nullptr; + } if (calld->have_request) { calld->have_request = false; calld->request.Destroy(); @@ -1069,7 +1078,8 @@ static bool maybe_retry(grpc_call_element* elem, subchannel_call_retry_state* retry_state = nullptr; if (batch_data != nullptr) { retry_state = static_cast( - batch_data->subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data( + batch_data->subchannel_call)); if (retry_state->retry_dispatched) { if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: retry already dispatched", chand, @@ -1170,10 +1180,13 @@ namespace { subchannel_batch_data::subchannel_batch_data(grpc_call_element* elem, call_data* calld, int refcount, bool set_on_complete) - : elem(elem), subchannel_call(calld->subchannel_call) { + : elem(elem), + subchannel_call(GRPC_SUBCHANNEL_CALL_REF(calld->subchannel_call, + "batch_data_create")) { subchannel_call_retry_state* retry_state = static_cast( - calld->subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data( + calld->subchannel_call)); batch.payload = &retry_state->batch_payload; gpr_ref_init(&refs, refcount); if (set_on_complete) { @@ -1187,7 +1200,7 @@ subchannel_batch_data::subchannel_batch_data(grpc_call_element* elem, void subchannel_batch_data::destroy() { subchannel_call_retry_state* retry_state = static_cast( - subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data(subchannel_call)); if (batch.send_initial_metadata) { grpc_metadata_batch_destroy(&retry_state->send_initial_metadata); } @@ -1200,7 +1213,7 @@ void subchannel_batch_data::destroy() { if (batch.recv_trailing_metadata) { grpc_metadata_batch_destroy(&retry_state->recv_trailing_metadata); } - subchannel_call.reset(); + GRPC_SUBCHANNEL_CALL_UNREF(subchannel_call, "batch_data_unref"); call_data* calld = static_cast(elem->call_data); GRPC_CALL_STACK_UNREF(calld->owning_call, "batch_data"); } @@ -1247,7 +1260,8 @@ static void invoke_recv_initial_metadata_callback(void* arg, // Return metadata. subchannel_call_retry_state* retry_state = static_cast( - batch_data->subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data( + batch_data->subchannel_call)); grpc_metadata_batch_move( &retry_state->recv_initial_metadata, pending->batch->payload->recv_initial_metadata.recv_initial_metadata); @@ -1279,7 +1293,8 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - batch_data->subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data( + batch_data->subchannel_call)); retry_state->completed_recv_initial_metadata = true; // If a retry was already dispatched, then we're not going to use the // result of this recv_initial_metadata op, so do nothing. @@ -1340,7 +1355,8 @@ static void invoke_recv_message_callback(void* arg, grpc_error* error) { // Return payload. subchannel_call_retry_state* retry_state = static_cast( - batch_data->subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data( + batch_data->subchannel_call)); *pending->batch->payload->recv_message.recv_message = std::move(retry_state->recv_message); // Update bookkeeping. @@ -1368,7 +1384,8 @@ static void recv_message_ready(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - batch_data->subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data( + batch_data->subchannel_call)); ++retry_state->completed_recv_message_count; // If a retry was already dispatched, then we're not going to use the // result of this recv_message op, so do nothing. @@ -1456,7 +1473,8 @@ static void add_closure_for_recv_trailing_metadata_ready( // Return metadata. subchannel_call_retry_state* retry_state = static_cast( - batch_data->subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data( + batch_data->subchannel_call)); grpc_metadata_batch_move( &retry_state->recv_trailing_metadata, pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata); @@ -1558,7 +1576,8 @@ static void run_closures_for_completed_call(subchannel_batch_data* batch_data, call_data* calld = static_cast(elem->call_data); subchannel_call_retry_state* retry_state = static_cast( - batch_data->subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data( + batch_data->subchannel_call)); // Construct list of closures to execute. grpc_core::CallCombinerClosureList closures; // First, add closure for recv_trailing_metadata_ready. @@ -1592,7 +1611,8 @@ static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - batch_data->subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data( + batch_data->subchannel_call)); retry_state->completed_recv_trailing_metadata = true; // Get the call's status and check for server pushback metadata. grpc_status_code status = GRPC_STATUS_OK; @@ -1715,7 +1735,8 @@ static void on_complete(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - batch_data->subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data( + batch_data->subchannel_call)); // Update bookkeeping in retry_state. if (batch_data->batch.send_initial_metadata) { retry_state->completed_send_initial_metadata = true; @@ -1771,10 +1792,10 @@ static void on_complete(void* arg, grpc_error* error) { static void start_batch_in_call_combiner(void* arg, grpc_error* ignored) { grpc_transport_stream_op_batch* batch = static_cast(arg); - grpc_core::SubchannelCall* subchannel_call = - static_cast(batch->handler_private.extra_arg); + grpc_subchannel_call* subchannel_call = + static_cast(batch->handler_private.extra_arg); // Note: This will release the call combiner. - subchannel_call->StartTransportStreamOpBatch(batch); + grpc_subchannel_call_process_op(subchannel_call, batch); } // Adds a closure to closures that will execute batch in the call combiner. @@ -1783,7 +1804,7 @@ static void add_closure_for_subchannel_batch( grpc_core::CallCombinerClosureList* closures) { channel_data* chand = static_cast(elem->channel_data); call_data* calld = static_cast(elem->call_data); - batch->handler_private.extra_arg = calld->subchannel_call.get(); + batch->handler_private.extra_arg = calld->subchannel_call; GRPC_CLOSURE_INIT(&batch->handler_private.closure, start_batch_in_call_combiner, batch, grpc_schedule_on_exec_ctx); @@ -1957,7 +1978,8 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem) { } subchannel_call_retry_state* retry_state = static_cast( - calld->subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data( + calld->subchannel_call)); // Create batch_data with 2 refs, since this batch will be unreffed twice: // once for the recv_trailing_metadata_ready callback when the subchannel // batch returns, and again when we actually get a recv_trailing_metadata @@ -1967,7 +1989,7 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem) { add_retriable_recv_trailing_metadata_op(calld, retry_state, batch_data); retry_state->recv_trailing_metadata_internal_batch = batch_data; // Note: This will release the call combiner. - calld->subchannel_call->StartTransportStreamOpBatch(&batch_data->batch); + grpc_subchannel_call_process_op(calld->subchannel_call, &batch_data->batch); } // If there are any cached send ops that need to be replayed on the @@ -2174,7 +2196,8 @@ static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored) { } subchannel_call_retry_state* retry_state = static_cast( - calld->subchannel_call->GetParentData()); + grpc_connected_subchannel_call_get_parent_data( + calld->subchannel_call)); // Construct list of closures to execute, one for each pending batch. grpc_core::CallCombinerClosureList closures; // Replay previously-returned send_* ops if needed. @@ -2197,7 +2220,7 @@ static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored) { gpr_log(GPR_INFO, "chand=%p calld=%p: starting %" PRIuPTR " retriable batches on subchannel_call=%p", - chand, calld, closures.size(), calld->subchannel_call.get()); + chand, calld, closures.size(), calld->subchannel_call); } // Note: This will yield the call combiner. closures.RunClosures(calld->call_combiner); @@ -2222,22 +2245,22 @@ static void create_subchannel_call(grpc_call_element* elem, grpc_error* error) { calld->call_combiner, // call_combiner parent_data_size // parent_data_size }; - grpc_error* new_error = GRPC_ERROR_NONE; - calld->subchannel_call = - calld->request->pick()->connected_subchannel->CreateCall(call_args, - &new_error); + grpc_error* new_error = + calld->request->pick()->connected_subchannel->CreateCall( + call_args, &calld->subchannel_call); if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: create subchannel_call=%p: error=%s", - chand, calld, calld->subchannel_call.get(), - grpc_error_string(new_error)); + chand, calld, calld->subchannel_call, grpc_error_string(new_error)); } if (GPR_UNLIKELY(new_error != GRPC_ERROR_NONE)) { new_error = grpc_error_add_child(new_error, error); pending_batches_fail(elem, new_error, true /* yield_call_combiner */); } else { if (parent_data_size > 0) { - new (calld->subchannel_call->GetParentData()) subchannel_call_retry_state( - calld->request->pick()->subchannel_call_context); + new (grpc_connected_subchannel_call_get_parent_data( + calld->subchannel_call)) + subchannel_call_retry_state( + calld->request->pick()->subchannel_call_context); } pending_batches_resume(elem); } @@ -2465,7 +2488,7 @@ static void cc_start_transport_stream_op_batch( batch, GRPC_ERROR_REF(calld->cancel_error), calld->call_combiner); } else { // Note: This will release the call combiner. - calld->subchannel_call->StartTransportStreamOpBatch(batch); + grpc_subchannel_call_process_op(calld->subchannel_call, batch); } return; } @@ -2479,7 +2502,7 @@ static void cc_start_transport_stream_op_batch( if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: starting batch on subchannel_call=%p", chand, - calld, calld->subchannel_call.get()); + calld, calld->subchannel_call); } pending_batches_resume(elem); return; @@ -2522,7 +2545,8 @@ static void cc_destroy_call_elem(grpc_call_element* elem, grpc_closure* then_schedule_closure) { call_data* calld = static_cast(elem->call_data); if (GPR_LIKELY(calld->subchannel_call != nullptr)) { - calld->subchannel_call->SetAfterCallStackDestroy(then_schedule_closure); + grpc_subchannel_call_set_cleanup_closure(calld->subchannel_call, + then_schedule_closure); then_schedule_closure = nullptr; } calld->~call_data(); @@ -2728,8 +2752,8 @@ void grpc_client_channel_watch_connectivity_state( GRPC_ERROR_NONE); } -grpc_core::RefCountedPtr -grpc_client_channel_get_subchannel_call(grpc_call_element* elem) { +grpc_subchannel_call* grpc_client_channel_get_subchannel_call( + grpc_call_element* elem) { call_data* calld = static_cast(elem->call_data); return calld->subchannel_call; } diff --git a/src/core/ext/filters/client_channel/client_channel.h b/src/core/ext/filters/client_channel/client_channel.h index 5bfff4df9cd..4935fd24d87 100644 --- a/src/core/ext/filters/client_channel/client_channel.h +++ b/src/core/ext/filters/client_channel/client_channel.h @@ -60,7 +60,7 @@ void grpc_client_channel_watch_connectivity_state( grpc_closure* watcher_timer_init); /* Debug helper: pull the subchannel call from a call stack element */ -grpc_core::RefCountedPtr -grpc_client_channel_get_subchannel_call(grpc_call_element* elem); +grpc_subchannel_call* grpc_client_channel_get_subchannel_call( + grpc_call_element* elem); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H */ diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 76c5a786240..8e5426081c4 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -113,11 +113,12 @@ RefCountedPtr ClientChannelNode::MakeClientChannelNode( is_top_level_channel); } -SubchannelNode::SubchannelNode(Subchannel* subchannel, +SubchannelNode::SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes) : BaseNode(EntityType::kSubchannel), subchannel_(subchannel), - target_(UniquePtr(gpr_strdup(subchannel_->GetTargetAddress()))), + target_( + UniquePtr(gpr_strdup(grpc_subchannel_get_target(subchannel_)))), trace_(channel_tracer_max_nodes) {} SubchannelNode::~SubchannelNode() {} @@ -127,8 +128,8 @@ void SubchannelNode::PopulateConnectivityState(grpc_json* json) { if (subchannel_ == nullptr) { state = GRPC_CHANNEL_SHUTDOWN; } else { - state = subchannel_->CheckConnectivity(nullptr, - true /* inhibit_health_checking */); + state = grpc_subchannel_check_connectivity( + subchannel_, nullptr, true /* inhibit_health_checking */); } json = grpc_json_create_child(nullptr, json, "state", nullptr, GRPC_JSON_OBJECT, false); @@ -169,7 +170,7 @@ grpc_json* SubchannelNode::RenderJson() { call_counter_.PopulateCallCounts(json); json = top_level_json; // populate the child socket. - intptr_t socket_uuid = subchannel_->GetChildSocketUuid(); + intptr_t socket_uuid = grpc_subchannel_get_child_socket_uuid(subchannel_); if (socket_uuid != 0) { grpc_json* array_parent = grpc_json_create_child( nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index 1dc1bf595be..8a5c3e7e5e5 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -26,10 +26,9 @@ #include "src/core/lib/channel/channel_trace.h" #include "src/core/lib/channel/channelz.h" -namespace grpc_core { - -class Subchannel; +typedef struct grpc_subchannel grpc_subchannel; +namespace grpc_core { namespace channelz { // Subtype of ChannelNode that overrides and provides client_channel specific @@ -60,7 +59,7 @@ class ClientChannelNode : public ChannelNode { // Handles channelz bookkeeping for sockets class SubchannelNode : public BaseNode { public: - SubchannelNode(Subchannel* subchannel, size_t channel_tracer_max_nodes); + SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes); ~SubchannelNode() override; void MarkSubchannelDestroyed() { @@ -85,7 +84,7 @@ class SubchannelNode : public BaseNode { void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } private: - Subchannel* subchannel_; + grpc_subchannel* subchannel_; UniquePtr target_; CallCountingHelper call_counter_; ChannelTrace trace_; 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 8c558382fdf..130bbe04180 100644 --- a/src/core/ext/filters/client_channel/client_channel_factory.cc +++ b/src/core/ext/filters/client_channel/client_channel_factory.cc @@ -29,7 +29,7 @@ void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory) { factory->vtable->unref(factory); } -grpc_core::Subchannel* grpc_client_channel_factory_create_subchannel( +grpc_subchannel* grpc_client_channel_factory_create_subchannel( 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 4b72aa46499..91dec12282f 100644 --- a/src/core/ext/filters/client_channel/client_channel_factory.h +++ b/src/core/ext/filters/client_channel/client_channel_factory.h @@ -48,8 +48,8 @@ struct grpc_client_channel_factory { struct grpc_client_channel_factory_vtable { void (*ref)(grpc_client_channel_factory* factory); void (*unref)(grpc_client_channel_factory* factory); - grpc_core::Subchannel* (*create_subchannel)( - grpc_client_channel_factory* factory, const grpc_channel_args* args); + grpc_subchannel* (*create_subchannel)(grpc_client_channel_factory* factory, + const grpc_channel_args* args); grpc_channel* (*create_client_channel)(grpc_client_channel_factory* factory, const char* target, grpc_client_channel_type type, @@ -60,7 +60,7 @@ void grpc_client_channel_factory_ref(grpc_client_channel_factory* factory); void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory); /** Create a new grpc_subchannel */ -grpc_core::Subchannel* grpc_client_channel_factory_create_subchannel( +grpc_subchannel* grpc_client_channel_factory_create_subchannel( grpc_client_channel_factory* factory, const grpc_channel_args* args); /** Create a new grpc_channel */ diff --git a/src/core/ext/filters/client_channel/global_subchannel_pool.cc b/src/core/ext/filters/client_channel/global_subchannel_pool.cc index ee6e58159a0..a41d993fe66 100644 --- a/src/core/ext/filters/client_channel/global_subchannel_pool.cc +++ b/src/core/ext/filters/client_channel/global_subchannel_pool.cc @@ -54,9 +54,9 @@ RefCountedPtr GlobalSubchannelPool::instance() { return *instance_; } -Subchannel* GlobalSubchannelPool::RegisterSubchannel(SubchannelKey* key, - Subchannel* constructed) { - Subchannel* c = nullptr; +grpc_subchannel* GlobalSubchannelPool::RegisterSubchannel( + SubchannelKey* key, grpc_subchannel* constructed) { + grpc_subchannel* c = nullptr; // Compare and swap (CAS) loop: while (c == nullptr) { // Ref the shared map to have a local copy. @@ -64,7 +64,7 @@ Subchannel* GlobalSubchannelPool::RegisterSubchannel(SubchannelKey* key, grpc_avl old_map = grpc_avl_ref(subchannel_map_, nullptr); gpr_mu_unlock(&mu_); // Check to see if a subchannel already exists. - c = static_cast(grpc_avl_get(old_map, key, nullptr)); + c = static_cast(grpc_avl_get(old_map, key, nullptr)); if (c != nullptr) { // The subchannel already exists. Reuse it. c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "subchannel_register+reuse"); @@ -121,14 +121,15 @@ void GlobalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) { } } -Subchannel* GlobalSubchannelPool::FindSubchannel(SubchannelKey* key) { +grpc_subchannel* GlobalSubchannelPool::FindSubchannel(SubchannelKey* key) { // Lock, and take a reference to the subchannel map. // We don't need to do the search under a lock as AVL's are immutable. gpr_mu_lock(&mu_); grpc_avl index = grpc_avl_ref(subchannel_map_, nullptr); gpr_mu_unlock(&mu_); - Subchannel* c = static_cast(grpc_avl_get(index, key, nullptr)); - if (c != nullptr) GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "found_from_pool"); + grpc_subchannel* c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF( + static_cast(grpc_avl_get(index, key, nullptr)), + "found_from_pool"); grpc_avl_unref(index, nullptr); return c; } @@ -155,11 +156,11 @@ long sck_avl_compare(void* a, void* b, void* unused) { } void scv_avl_destroy(void* p, void* user_data) { - GRPC_SUBCHANNEL_WEAK_UNREF((Subchannel*)p, "global_subchannel_pool"); + GRPC_SUBCHANNEL_WEAK_UNREF((grpc_subchannel*)p, "global_subchannel_pool"); } void* scv_avl_copy(void* p, void* unused) { - GRPC_SUBCHANNEL_WEAK_REF((Subchannel*)p, "global_subchannel_pool"); + GRPC_SUBCHANNEL_WEAK_REF((grpc_subchannel*)p, "global_subchannel_pool"); return p; } diff --git a/src/core/ext/filters/client_channel/global_subchannel_pool.h b/src/core/ext/filters/client_channel/global_subchannel_pool.h index 96dc8d7b3a4..0deb3769360 100644 --- a/src/core/ext/filters/client_channel/global_subchannel_pool.h +++ b/src/core/ext/filters/client_channel/global_subchannel_pool.h @@ -45,10 +45,10 @@ class GlobalSubchannelPool final : public SubchannelPoolInterface { static RefCountedPtr instance(); // Implements interface methods. - Subchannel* RegisterSubchannel(SubchannelKey* key, - Subchannel* constructed) override; + grpc_subchannel* RegisterSubchannel(SubchannelKey* key, + grpc_subchannel* constructed) override; void UnregisterSubchannel(SubchannelKey* key) override; - Subchannel* FindSubchannel(SubchannelKey* key) override; + grpc_subchannel* FindSubchannel(SubchannelKey* key) override; private: // The singleton instance. (It's a pointer to RefCountedPtr so that this diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc index e845d63d295..2232c57120e 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -295,9 +295,7 @@ HealthCheckClient::CallState::~CallState() { gpr_log(GPR_INFO, "HealthCheckClient %p: destroying CallState %p", health_check_client_.get(), this); } - // The subchannel call is in the arena, so reset the pointer before we destroy - // the arena. - call_.reset(); + if (call_ != nullptr) GRPC_SUBCHANNEL_CALL_UNREF(call_, "call_ended"); for (size_t i = 0; i < GRPC_CONTEXT_COUNT; i++) { if (context_[i].destroy != nullptr) { context_[i].destroy(context_[i].value); @@ -331,8 +329,8 @@ void HealthCheckClient::CallState::StartCall() { &call_combiner_, 0, // parent_data_size }; - grpc_error* error = GRPC_ERROR_NONE; - call_ = health_check_client_->connected_subchannel_->CreateCall(args, &error); + grpc_error* error = + health_check_client_->connected_subchannel_->CreateCall(args, &call_); if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "HealthCheckClient %p CallState %p: error creating health " @@ -425,14 +423,14 @@ void HealthCheckClient::CallState::StartBatchInCallCombiner(void* arg, grpc_error* error) { grpc_transport_stream_op_batch* batch = static_cast(arg); - SubchannelCall* call = - static_cast(batch->handler_private.extra_arg); - call->StartTransportStreamOpBatch(batch); + grpc_subchannel_call* call = + static_cast(batch->handler_private.extra_arg); + grpc_subchannel_call_process_op(call, batch); } void HealthCheckClient::CallState::StartBatch( grpc_transport_stream_op_batch* batch) { - batch->handler_private.extra_arg = call_.get(); + batch->handler_private.extra_arg = call_; GRPC_CLOSURE_INIT(&batch->handler_private.closure, StartBatchInCallCombiner, batch, grpc_schedule_on_exec_ctx); GRPC_CALL_COMBINER_START(&call_combiner_, &batch->handler_private.closure, @@ -454,7 +452,7 @@ void HealthCheckClient::CallState::StartCancel(void* arg, grpc_error* error) { GRPC_CLOSURE_CREATE(OnCancelComplete, self, grpc_schedule_on_exec_ctx)); batch->cancel_stream = true; batch->payload->cancel_stream.cancel_error = GRPC_ERROR_CANCELLED; - self->call_->StartTransportStreamOpBatch(batch); + grpc_subchannel_call_process_op(self->call_, batch); } void HealthCheckClient::CallState::Cancel() { diff --git a/src/core/ext/filters/client_channel/health/health_check_client.h b/src/core/ext/filters/client_channel/health/health_check_client.h index 7af88a54cfc..2369b73feac 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.h +++ b/src/core/ext/filters/client_channel/health/health_check_client.h @@ -99,7 +99,7 @@ class HealthCheckClient : public InternallyRefCounted { grpc_call_context_element context_[GRPC_CONTEXT_COUNT] = {}; // The streaming call to the backend. Always non-NULL. - RefCountedPtr call_; + grpc_subchannel_call* call_; grpc_transport_stream_op_batch_payload payload_; grpc_transport_stream_op_batch batch_; diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index dc716a6adac..ec5c782c469 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -79,7 +79,7 @@ class PickFirst : public LoadBalancingPolicy { PickFirstSubchannelData( SubchannelList* subchannel_list, - const ServerAddress& address, Subchannel* subchannel, + const ServerAddress& address, grpc_subchannel* subchannel, grpc_combiner* combiner) : SubchannelData(subchannel_list, address, subchannel, combiner) {} diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index aab6dd68216..30316689ea7 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -94,7 +94,7 @@ class RoundRobin : public LoadBalancingPolicy { RoundRobinSubchannelData( SubchannelList* subchannel_list, - const ServerAddress& address, Subchannel* subchannel, + const ServerAddress& address, grpc_subchannel* subchannel, grpc_combiner* combiner) : SubchannelData(subchannel_list, address, subchannel, combiner) {} 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 0174a98a73d..2eb92b7ead0 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 @@ -88,7 +88,7 @@ class SubchannelData { } // Returns a pointer to the subchannel. - Subchannel* subchannel() const { return subchannel_; } + grpc_subchannel* subchannel() const { return subchannel_; } // Returns the connected subchannel. Will be null if the subchannel // is not connected. @@ -103,8 +103,8 @@ class SubchannelData { // ProcessConnectivityChangeLocked()). grpc_connectivity_state CheckConnectivityStateLocked(grpc_error** error) { GPR_ASSERT(!connectivity_notification_pending_); - pending_connectivity_state_unsafe_ = subchannel()->CheckConnectivity( - error, subchannel_list_->inhibit_health_checking()); + pending_connectivity_state_unsafe_ = grpc_subchannel_check_connectivity( + subchannel(), error, subchannel_list_->inhibit_health_checking()); UpdateConnectedSubchannelLocked(); return pending_connectivity_state_unsafe_; } @@ -142,7 +142,7 @@ class SubchannelData { protected: SubchannelData( SubchannelList* subchannel_list, - const ServerAddress& address, Subchannel* subchannel, + const ServerAddress& address, grpc_subchannel* subchannel, grpc_combiner* combiner); virtual ~SubchannelData(); @@ -170,7 +170,7 @@ class SubchannelData { SubchannelList* subchannel_list_; // The subchannel and connected subchannel. - Subchannel* subchannel_; + grpc_subchannel* subchannel_; RefCountedPtr connected_subchannel_; // Notification that connectivity has changed on subchannel. @@ -203,7 +203,7 @@ class SubchannelList : public InternallyRefCounted { for (size_t i = 0; i < subchannels_.size(); ++i) { if (subchannels_[i].subchannel() != nullptr) { grpc_core::channelz::SubchannelNode* subchannel_node = - subchannels_[i].subchannel()->channelz_node(); + grpc_subchannel_get_channelz_node(subchannels_[i].subchannel()); if (subchannel_node != nullptr) { refs_list->push_back(subchannel_node->uuid()); } @@ -276,7 +276,7 @@ class SubchannelList : public InternallyRefCounted { template SubchannelData::SubchannelData( SubchannelList* subchannel_list, - const ServerAddress& address, Subchannel* subchannel, + const ServerAddress& address, grpc_subchannel* subchannel, grpc_combiner* combiner) : subchannel_list_(subchannel_list), subchannel_(subchannel), @@ -317,7 +317,7 @@ template void SubchannelData::ResetBackoffLocked() { if (subchannel_ != nullptr) { - subchannel_->ResetBackoff(); + grpc_subchannel_reset_backoff(subchannel_); } } @@ -337,8 +337,8 @@ void SubchannelDataRef(DEBUG_LOCATION, "connectivity_watch").release(); - subchannel_->NotifyOnStateChange( - subchannel_list_->policy()->interested_parties(), + grpc_subchannel_notify_on_state_change( + subchannel_, subchannel_list_->policy()->interested_parties(), &pending_connectivity_state_unsafe_, &connectivity_changed_closure_, subchannel_list_->inhibit_health_checking()); } @@ -357,8 +357,8 @@ void SubchannelDataNotifyOnStateChange( - subchannel_list_->policy()->interested_parties(), + grpc_subchannel_notify_on_state_change( + subchannel_, subchannel_list_->policy()->interested_parties(), &pending_connectivity_state_unsafe_, &connectivity_changed_closure_, subchannel_list_->inhibit_health_checking()); } @@ -391,9 +391,9 @@ void SubchannelData:: subchannel_, reason); } GPR_ASSERT(connectivity_notification_pending_); - subchannel_->NotifyOnStateChange(nullptr, nullptr, - &connectivity_changed_closure_, - subchannel_list_->inhibit_health_checking()); + grpc_subchannel_notify_on_state_change( + subchannel_, nullptr, nullptr, &connectivity_changed_closure_, + subchannel_list_->inhibit_health_checking()); } template @@ -401,7 +401,8 @@ bool SubchannelData::UpdateConnectedSubchannelLocked() { // If the subchannel is READY, take a ref to the connected subchannel. if (pending_connectivity_state_unsafe_ == GRPC_CHANNEL_READY) { - connected_subchannel_ = subchannel_->connected_subchannel(); + connected_subchannel_ = + grpc_subchannel_get_connected_subchannel(subchannel_); // If the subchannel became disconnected between the time that READY // was reported and the time we got here (e.g., between when a // notification callback is scheduled and when it was actually run in @@ -517,7 +518,7 @@ SubchannelList::SubchannelList( SubchannelPoolInterface::CreateChannelArg(policy_->subchannel_pool())); const size_t subchannel_address_arg_index = args_to_add.size(); args_to_add.emplace_back( - Subchannel::CreateSubchannelAddressArg(&addresses[i].address())); + grpc_create_subchannel_address_arg(&addresses[i].address())); if (addresses[i].args() != nullptr) { for (size_t j = 0; j < addresses[i].args()->num_args; ++j) { args_to_add.emplace_back(addresses[i].args()->args[j]); @@ -527,7 +528,7 @@ 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[subchannel_address_arg_index].value.string); - Subchannel* subchannel = grpc_client_channel_factory_create_subchannel( + grpc_subchannel* subchannel = grpc_client_channel_factory_create_subchannel( client_channel_factory, new_args); grpc_channel_args_destroy(new_args); if (subchannel == nullptr) { diff --git a/src/core/ext/filters/client_channel/local_subchannel_pool.cc b/src/core/ext/filters/client_channel/local_subchannel_pool.cc index d1c1cacb441..145fa4e0374 100644 --- a/src/core/ext/filters/client_channel/local_subchannel_pool.cc +++ b/src/core/ext/filters/client_channel/local_subchannel_pool.cc @@ -32,11 +32,11 @@ LocalSubchannelPool::~LocalSubchannelPool() { grpc_avl_unref(subchannel_map_, nullptr); } -Subchannel* LocalSubchannelPool::RegisterSubchannel(SubchannelKey* key, - Subchannel* constructed) { +grpc_subchannel* LocalSubchannelPool::RegisterSubchannel( + SubchannelKey* key, grpc_subchannel* constructed) { // Check to see if a subchannel already exists. - Subchannel* c = - static_cast(grpc_avl_get(subchannel_map_, key, nullptr)); + grpc_subchannel* c = static_cast( + grpc_avl_get(subchannel_map_, key, nullptr)); if (c != nullptr) { // The subchannel already exists. Reuse it. c = GRPC_SUBCHANNEL_REF(c, "subchannel_register+reuse"); @@ -54,9 +54,9 @@ void LocalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) { subchannel_map_ = grpc_avl_remove(subchannel_map_, key, nullptr); } -Subchannel* LocalSubchannelPool::FindSubchannel(SubchannelKey* key) { - Subchannel* c = - static_cast(grpc_avl_get(subchannel_map_, key, nullptr)); +grpc_subchannel* LocalSubchannelPool::FindSubchannel(SubchannelKey* key) { + grpc_subchannel* c = static_cast( + grpc_avl_get(subchannel_map_, key, nullptr)); return c == nullptr ? c : GRPC_SUBCHANNEL_REF(c, "found_from_pool"); } diff --git a/src/core/ext/filters/client_channel/local_subchannel_pool.h b/src/core/ext/filters/client_channel/local_subchannel_pool.h index a6b7e259fbb..9929cdb3627 100644 --- a/src/core/ext/filters/client_channel/local_subchannel_pool.h +++ b/src/core/ext/filters/client_channel/local_subchannel_pool.h @@ -39,10 +39,10 @@ class LocalSubchannelPool final : public SubchannelPoolInterface { // Implements interface methods. // Thread-unsafe. Intended to be invoked within the client_channel combiner. - Subchannel* RegisterSubchannel(SubchannelKey* key, - Subchannel* constructed) override; + grpc_subchannel* RegisterSubchannel(SubchannelKey* key, + grpc_subchannel* constructed) override; void UnregisterSubchannel(SubchannelKey* key) override; - Subchannel* FindSubchannel(SubchannelKey* key) override; + grpc_subchannel* FindSubchannel(SubchannelKey* key) override; private: // The vtable for subchannel operations in an AVL tree. diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 70285659aad..d77bb3c286b 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -44,6 +44,7 @@ #include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/channel.h" @@ -54,256 +55,153 @@ #include "src/core/lib/transport/status_metadata.h" #include "src/core/lib/uri/uri_parser.h" -// Strong and weak refs. #define INTERNAL_REF_BITS 16 #define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1)) -// Backoff parameters. #define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1 #define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6 #define GRPC_SUBCHANNEL_RECONNECT_MIN_TIMEOUT_SECONDS 20 #define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120 #define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2 -// Conversion between subchannel call and call stack. -#define SUBCHANNEL_CALL_TO_CALL_STACK(call) \ - (grpc_call_stack*)((char*)(call) + \ - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall))) -#define CALL_STACK_TO_SUBCHANNEL_CALL(callstack) \ - (SubchannelCall*)(((char*)(call_stack)) - \ - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall))) +typedef struct external_state_watcher { + grpc_subchannel* subchannel; + grpc_pollset_set* pollset_set; + grpc_closure* notify; + grpc_closure closure; + struct external_state_watcher* next; + struct external_state_watcher* prev; +} external_state_watcher; namespace grpc_core { -// -// ConnectedSubchannel -// - -ConnectedSubchannel::ConnectedSubchannel( - grpc_channel_stack* channel_stack, const grpc_channel_args* args, - RefCountedPtr channelz_subchannel, - intptr_t socket_uuid) - : RefCounted(&grpc_trace_stream_refcount), - channel_stack_(channel_stack), - args_(grpc_channel_args_copy(args)), - channelz_subchannel_(std::move(channelz_subchannel)), - socket_uuid_(socket_uuid) {} +class ConnectedSubchannelStateWatcher; -ConnectedSubchannel::~ConnectedSubchannel() { - grpc_channel_args_destroy(args_); - GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor"); -} +} // namespace grpc_core -void ConnectedSubchannel::NotifyOnStateChange( - grpc_pollset_set* interested_parties, grpc_connectivity_state* state, - grpc_closure* closure) { - grpc_transport_op* op = grpc_make_transport_op(nullptr); - grpc_channel_element* elem; - op->connectivity_state = state; - op->on_connectivity_state_change = closure; - op->bind_pollset_set = interested_parties; - elem = grpc_channel_stack_element(channel_stack_, 0); - elem->filter->start_transport_op(elem, op); -} +struct grpc_subchannel { + /** The subchannel pool this subchannel is in */ + grpc_core::RefCountedPtr subchannel_pool; -void ConnectedSubchannel::Ping(grpc_closure* on_initiate, - grpc_closure* on_ack) { - grpc_transport_op* op = grpc_make_transport_op(nullptr); - grpc_channel_element* elem; - op->send_ping.on_initiate = on_initiate; - op->send_ping.on_ack = on_ack; - elem = grpc_channel_stack_element(channel_stack_, 0); - elem->filter->start_transport_op(elem, op); -} + grpc_connector* connector; -namespace { + /** refcount + - lower INTERNAL_REF_BITS bits are for internal references: + these do not keep the subchannel open. + - upper remaining bits are for public references: these do + keep the subchannel open */ + gpr_atm ref_pair; -void SubchannelCallDestroy(void* arg, grpc_error* error) { - GPR_TIMER_SCOPE("subchannel_call_destroy", 0); - SubchannelCall* call = static_cast(arg); - grpc_closure* after_call_stack_destroy = call->after_call_stack_destroy(); - call->~SubchannelCall(); - // This should be the last step to destroy the subchannel call, because - // call->after_call_stack_destroy(), if not null, will free the call arena. - grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(call), nullptr, - after_call_stack_destroy); -} + /** channel arguments */ + grpc_channel_args* args; -} // namespace + grpc_core::SubchannelKey* key; -RefCountedPtr ConnectedSubchannel::CreateCall( - const CallArgs& args, grpc_error** error) { - const size_t allocation_size = - GetInitialCallSizeEstimate(args.parent_data_size); - RefCountedPtr call( - new (gpr_arena_alloc(args.arena, allocation_size)) - SubchannelCall(Ref(DEBUG_LOCATION, "subchannel_call"), args)); - grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call.get()); - const grpc_call_element_args call_args = { - callstk, /* call_stack */ - nullptr, /* server_transport_data */ - args.context, /* context */ - args.path, /* path */ - args.start_time, /* start_time */ - args.deadline, /* deadline */ - args.arena, /* arena */ - args.call_combiner /* call_combiner */ - }; - *error = grpc_call_stack_init(channel_stack_, 1, SubchannelCallDestroy, - call.get(), &call_args); - if (GPR_UNLIKELY(*error != GRPC_ERROR_NONE)) { - const char* error_string = grpc_error_string(*error); - gpr_log(GPR_ERROR, "error: %s", error_string); - return call; - } - grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); - if (channelz_subchannel_ != nullptr) { - channelz_subchannel_->RecordCallStarted(); - } - return call; -} + /** set during connection */ + grpc_connect_out_args connecting_result; -size_t ConnectedSubchannel::GetInitialCallSizeEstimate( - size_t parent_data_size) const { - size_t allocation_size = - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)); - if (parent_data_size > 0) { - allocation_size += - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) + - parent_data_size; - } else { - allocation_size += channel_stack_->call_stack_size; - } - return allocation_size; -} + /** callback for connection finishing */ + grpc_closure on_connected; -// -// SubchannelCall -// + /** callback for our alarm */ + grpc_closure on_alarm; -void SubchannelCall::StartTransportStreamOpBatch( - grpc_transport_stream_op_batch* batch) { - GPR_TIMER_SCOPE("subchannel_call_process_op", 0); - MaybeInterceptRecvTrailingMetadata(batch); - grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(this); - grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0); - GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch); - top_elem->filter->start_transport_stream_op_batch(top_elem, batch); -} + /** pollset_set tracking who's interested in a connection + being setup */ + grpc_pollset_set* pollset_set; -void* SubchannelCall::GetParentData() { - grpc_channel_stack* chanstk = connected_subchannel_->channel_stack(); - return (char*)this + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)) + - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(chanstk->call_stack_size); -} + grpc_core::UniquePtr health_check_service_name; -grpc_call_stack* SubchannelCall::GetCallStack() { - return SUBCHANNEL_CALL_TO_CALL_STACK(this); -} + /** mutex protecting remaining elements */ + gpr_mu mu; -void SubchannelCall::SetAfterCallStackDestroy(grpc_closure* closure) { - GPR_ASSERT(after_call_stack_destroy_ == nullptr); - GPR_ASSERT(closure != nullptr); - after_call_stack_destroy_ = closure; -} + /** active connection, or null */ + grpc_core::RefCountedPtr connected_subchannel; + grpc_core::OrphanablePtr + connected_subchannel_watcher; -RefCountedPtr SubchannelCall::Ref() { - IncrementRefCount(); - return RefCountedPtr(this); -} + /** have we seen a disconnection? */ + bool disconnected; + /** are we connecting */ + bool connecting; -RefCountedPtr SubchannelCall::Ref( - const grpc_core::DebugLocation& location, const char* reason) { - IncrementRefCount(location, reason); - return RefCountedPtr(this); -} + /** connectivity state tracking */ + grpc_connectivity_state_tracker state_tracker; + grpc_connectivity_state_tracker state_and_health_tracker; -void SubchannelCall::Unref() { - GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), ""); -} + external_state_watcher root_external_state_watcher; -void SubchannelCall::Unref(const DebugLocation& location, const char* reason) { - GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason); -} + /** backoff state */ + grpc_core::ManualConstructor backoff; + grpc_millis next_attempt_deadline; + grpc_millis min_connect_timeout_ms; -void SubchannelCall::MaybeInterceptRecvTrailingMetadata( - grpc_transport_stream_op_batch* batch) { - // only intercept payloads with recv trailing. - if (!batch->recv_trailing_metadata) { - return; - } - // only add interceptor is channelz is enabled. - if (connected_subchannel_->channelz_subchannel() == nullptr) { - return; - } - GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready_, RecvTrailingMetadataReady, - this, grpc_schedule_on_exec_ctx); - // save some state needed for the interception callback. - GPR_ASSERT(recv_trailing_metadata_ == nullptr); - recv_trailing_metadata_ = - batch->payload->recv_trailing_metadata.recv_trailing_metadata; - original_recv_trailing_metadata_ = - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = - &recv_trailing_metadata_ready_; -} + /** do we have an active alarm? */ + bool have_alarm; + /** have we started the backoff loop */ + bool backoff_begun; + // reset_backoff() was called while alarm was pending + bool retry_immediately; + /** our alarm */ + grpc_timer alarm; -namespace { + grpc_core::RefCountedPtr + channelz_subchannel; +}; -// Sets *status based on the rest of the parameters. -void GetCallStatus(grpc_status_code* status, grpc_millis deadline, - grpc_metadata_batch* md_batch, grpc_error* error) { - if (error != GRPC_ERROR_NONE) { - grpc_error_get_status(error, deadline, status, nullptr, nullptr, nullptr); - } else { - if (md_batch->idx.named.grpc_status != nullptr) { - *status = grpc_get_status_code_from_metadata( - md_batch->idx.named.grpc_status->md); - } else { - *status = GRPC_STATUS_UNKNOWN; - } - } - GRPC_ERROR_UNREF(error); -} +struct grpc_subchannel_call { + grpc_subchannel_call(grpc_core::ConnectedSubchannel* connection, + const grpc_core::ConnectedSubchannel::CallArgs& args) + : connection(connection), deadline(args.deadline) {} + + grpc_core::ConnectedSubchannel* connection; + grpc_closure* schedule_closure_after_destroy = nullptr; + // state needed to support channelz interception of recv trailing metadata. + grpc_closure recv_trailing_metadata_ready; + grpc_closure* original_recv_trailing_metadata; + grpc_metadata_batch* recv_trailing_metadata = nullptr; + grpc_millis deadline; +}; -} // namespace +static void maybe_start_connecting_locked(grpc_subchannel* c); -void SubchannelCall::RecvTrailingMetadataReady(void* arg, grpc_error* error) { - SubchannelCall* call = static_cast(arg); - GPR_ASSERT(call->recv_trailing_metadata_ != nullptr); - grpc_status_code status = GRPC_STATUS_OK; - GetCallStatus(&status, call->deadline_, call->recv_trailing_metadata_, - GRPC_ERROR_REF(error)); - channelz::SubchannelNode* channelz_subchannel = - call->connected_subchannel_->channelz_subchannel(); - GPR_ASSERT(channelz_subchannel != nullptr); - if (status == GRPC_STATUS_OK) { - channelz_subchannel->RecordCallSucceeded(); - } else { - channelz_subchannel->RecordCallFailed(); +static const char* subchannel_connectivity_state_change_string( + grpc_connectivity_state state) { + switch (state) { + case GRPC_CHANNEL_IDLE: + return "Subchannel state change to IDLE"; + case GRPC_CHANNEL_CONNECTING: + return "Subchannel state change to CONNECTING"; + case GRPC_CHANNEL_READY: + return "Subchannel state change to READY"; + case GRPC_CHANNEL_TRANSIENT_FAILURE: + return "Subchannel state change to TRANSIENT_FAILURE"; + case GRPC_CHANNEL_SHUTDOWN: + return "Subchannel state change to SHUTDOWN"; } - GRPC_CLOSURE_RUN(call->original_recv_trailing_metadata_, - GRPC_ERROR_REF(error)); -} - -void SubchannelCall::IncrementRefCount() { - GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(this), ""); + GPR_UNREACHABLE_CODE(return "UNKNOWN"); } -void SubchannelCall::IncrementRefCount(const grpc_core::DebugLocation& location, - const char* reason) { - GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason); +static void set_subchannel_connectivity_state_locked( + grpc_subchannel* c, grpc_connectivity_state state, grpc_error* error, + const char* reason) { + if (c->channelz_subchannel != nullptr) { + c->channelz_subchannel->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string( + subchannel_connectivity_state_change_string(state))); + } + grpc_connectivity_state_set(&c->state_tracker, state, error, reason); } -// -// Subchannel::ConnectedSubchannelStateWatcher -// +namespace grpc_core { -class Subchannel::ConnectedSubchannelStateWatcher +class ConnectedSubchannelStateWatcher : public InternallyRefCounted { public: // Must be instantiated while holding c->mu. - explicit ConnectedSubchannelStateWatcher(Subchannel* c) : subchannel_(c) { + explicit ConnectedSubchannelStateWatcher(grpc_subchannel* c) + : subchannel_(c) { // Steal subchannel ref for connecting. GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "state_watcher"); GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "connecting"); @@ -311,15 +209,15 @@ class Subchannel::ConnectedSubchannelStateWatcher // Callback uses initial ref to this. GRPC_CLOSURE_INIT(&on_connectivity_changed_, OnConnectivityChanged, this, grpc_schedule_on_exec_ctx); - c->connected_subchannel_->NotifyOnStateChange(c->pollset_set_, - &pending_connectivity_state_, - &on_connectivity_changed_); + c->connected_subchannel->NotifyOnStateChange(c->pollset_set, + &pending_connectivity_state_, + &on_connectivity_changed_); // Start health check if needed. grpc_connectivity_state health_state = GRPC_CHANNEL_READY; - if (c->health_check_service_name_ != nullptr) { - health_check_client_ = MakeOrphanable( - c->health_check_service_name_.get(), c->connected_subchannel_, - c->pollset_set_, c->channelz_node_); + if (c->health_check_service_name != nullptr) { + health_check_client_ = grpc_core::MakeOrphanable( + c->health_check_service_name.get(), c->connected_subchannel, + c->pollset_set, c->channelz_subchannel); GRPC_CLOSURE_INIT(&on_health_changed_, OnHealthChanged, this, grpc_schedule_on_exec_ctx); Ref().release(); // Ref for health callback tracked manually. @@ -328,9 +226,9 @@ class Subchannel::ConnectedSubchannelStateWatcher health_state = GRPC_CHANNEL_CONNECTING; } // Report initial state. - c->SetConnectivityStateLocked(GRPC_CHANNEL_READY, GRPC_ERROR_NONE, - "subchannel_connected"); - grpc_connectivity_state_set(&c->state_and_health_tracker_, health_state, + set_subchannel_connectivity_state_locked( + c, GRPC_CHANNEL_READY, GRPC_ERROR_NONE, "subchannel_connected"); + grpc_connectivity_state_set(&c->state_and_health_tracker, health_state, GRPC_ERROR_NONE, "subchannel_connected"); } @@ -344,33 +242,33 @@ class Subchannel::ConnectedSubchannelStateWatcher private: static void OnConnectivityChanged(void* arg, grpc_error* error) { auto* self = static_cast(arg); - Subchannel* c = self->subchannel_; + grpc_subchannel* c = self->subchannel_; { - MutexLock lock(&c->mu_); + MutexLock lock(&c->mu); switch (self->pending_connectivity_state_) { case GRPC_CHANNEL_TRANSIENT_FAILURE: case GRPC_CHANNEL_SHUTDOWN: { - if (!c->disconnected_ && c->connected_subchannel_ != nullptr) { + if (!c->disconnected && c->connected_subchannel != nullptr) { if (grpc_trace_stream_refcount.enabled()) { gpr_log(GPR_INFO, "Connected subchannel %p of subchannel %p has gone into " "%s. Attempting to reconnect.", - c->connected_subchannel_.get(), c, + c->connected_subchannel.get(), c, grpc_connectivity_state_name( self->pending_connectivity_state_)); } - c->connected_subchannel_.reset(); - c->connected_subchannel_watcher_.reset(); + c->connected_subchannel.reset(); + c->connected_subchannel_watcher.reset(); self->last_connectivity_state_ = GRPC_CHANNEL_TRANSIENT_FAILURE; - c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, - GRPC_ERROR_REF(error), - "reflect_child"); - grpc_connectivity_state_set(&c->state_and_health_tracker_, + set_subchannel_connectivity_state_locked( + c, GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), + "reflect_child"); + grpc_connectivity_state_set(&c->state_and_health_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), "reflect_child"); - c->backoff_begun_ = false; - c->backoff_.Reset(); - c->MaybeStartConnectingLocked(); + c->backoff_begun = false; + c->backoff->Reset(); + maybe_start_connecting_locked(c); } else { self->last_connectivity_state_ = GRPC_CHANNEL_SHUTDOWN; } @@ -383,14 +281,15 @@ class Subchannel::ConnectedSubchannelStateWatcher // this watch from. And a connected subchannel should never go // from READY to CONNECTING or IDLE. self->last_connectivity_state_ = self->pending_connectivity_state_; - c->SetConnectivityStateLocked(self->pending_connectivity_state_, - GRPC_ERROR_REF(error), "reflect_child"); + set_subchannel_connectivity_state_locked( + c, self->pending_connectivity_state_, GRPC_ERROR_REF(error), + "reflect_child"); if (self->pending_connectivity_state_ != GRPC_CHANNEL_READY) { - grpc_connectivity_state_set(&c->state_and_health_tracker_, + grpc_connectivity_state_set(&c->state_and_health_tracker, self->pending_connectivity_state_, GRPC_ERROR_REF(error), "reflect_child"); } - c->connected_subchannel_->NotifyOnStateChange( + c->connected_subchannel->NotifyOnStateChange( nullptr, &self->pending_connectivity_state_, &self->on_connectivity_changed_); self = nullptr; // So we don't unref below. @@ -404,14 +303,14 @@ class Subchannel::ConnectedSubchannelStateWatcher static void OnHealthChanged(void* arg, grpc_error* error) { auto* self = static_cast(arg); - Subchannel* c = self->subchannel_; - MutexLock lock(&c->mu_); + grpc_subchannel* c = self->subchannel_; + MutexLock lock(&c->mu); if (self->health_state_ == GRPC_CHANNEL_SHUTDOWN) { self->Unref(); return; } if (self->last_connectivity_state_ == GRPC_CHANNEL_READY) { - grpc_connectivity_state_set(&c->state_and_health_tracker_, + grpc_connectivity_state_set(&c->state_and_health_tracker, self->health_state_, GRPC_ERROR_REF(error), "health_changed"); } @@ -419,63 +318,163 @@ class Subchannel::ConnectedSubchannelStateWatcher &self->on_health_changed_); } - Subchannel* subchannel_; + grpc_subchannel* subchannel_; grpc_closure on_connectivity_changed_; grpc_connectivity_state pending_connectivity_state_ = GRPC_CHANNEL_READY; grpc_connectivity_state last_connectivity_state_ = GRPC_CHANNEL_READY; - OrphanablePtr health_check_client_; + grpc_core::OrphanablePtr health_check_client_; grpc_closure on_health_changed_; grpc_connectivity_state health_state_ = GRPC_CHANNEL_CONNECTING; }; -// -// Subchannel::ExternalStateWatcher -// +} // namespace grpc_core + +#define SUBCHANNEL_CALL_TO_CALL_STACK(call) \ + (grpc_call_stack*)((char*)(call) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \ + sizeof(grpc_subchannel_call))) +#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \ + (grpc_subchannel_call*)(((char*)(call_stack)) - \ + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \ + sizeof(grpc_subchannel_call))) -struct Subchannel::ExternalStateWatcher { - ExternalStateWatcher(Subchannel* subchannel, grpc_pollset_set* pollset_set, - grpc_closure* notify) - : subchannel(subchannel), pollset_set(pollset_set), notify(notify) { - GRPC_SUBCHANNEL_WEAK_REF(subchannel, "external_state_watcher+init"); - GRPC_CLOSURE_INIT(&on_state_changed, OnStateChanged, this, - grpc_schedule_on_exec_ctx); +static void on_subchannel_connected(void* subchannel, grpc_error* error); + +#ifndef NDEBUG +#define REF_REASON reason +#define REF_MUTATE_EXTRA_ARGS \ + GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char* purpose +#define REF_MUTATE_PURPOSE(x) , file, line, reason, x +#else +#define REF_REASON "" +#define REF_MUTATE_EXTRA_ARGS +#define REF_MUTATE_PURPOSE(x) +#endif + +/* + * connection implementation + */ + +static void connection_destroy(void* arg, grpc_error* error) { + grpc_channel_stack* stk = static_cast(arg); + grpc_channel_stack_destroy(stk); + gpr_free(stk); +} + +/* + * grpc_subchannel implementation + */ + +static void subchannel_destroy(void* arg, grpc_error* error) { + grpc_subchannel* c = static_cast(arg); + if (c->channelz_subchannel != nullptr) { + c->channelz_subchannel->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Subchannel destroyed")); + c->channelz_subchannel->MarkSubchannelDestroyed(); + c->channelz_subchannel.reset(); } + c->health_check_service_name.reset(); + grpc_channel_args_destroy(c->args); + grpc_connectivity_state_destroy(&c->state_tracker); + grpc_connectivity_state_destroy(&c->state_and_health_tracker); + grpc_connector_unref(c->connector); + grpc_pollset_set_destroy(c->pollset_set); + grpc_core::Delete(c->key); + gpr_mu_destroy(&c->mu); + gpr_free(c); +} - static void OnStateChanged(void* arg, grpc_error* error) { - ExternalStateWatcher* w = static_cast(arg); - grpc_closure* follow_up = w->notify; - if (w->pollset_set != nullptr) { - grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set_, - w->pollset_set); - } - gpr_mu_lock(&w->subchannel->mu_); - if (w->subchannel->external_state_watcher_list_ == w) { - w->subchannel->external_state_watcher_list_ = w->next; +static gpr_atm ref_mutate(grpc_subchannel* c, gpr_atm delta, + int barrier REF_MUTATE_EXTRA_ARGS) { + gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta) + : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta); +#ifndef NDEBUG + if (grpc_trace_stream_refcount.enabled()) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", c, + purpose, old_val, old_val + delta, reason); + } +#endif + return old_val; +} + +grpc_subchannel* grpc_subchannel_ref( + grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + old_refs = ref_mutate(c, (1 << INTERNAL_REF_BITS), + 0 REF_MUTATE_PURPOSE("STRONG_REF")); + GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0); + return c; +} + +grpc_subchannel* grpc_subchannel_weak_ref( + grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + old_refs = ref_mutate(c, 1, 0 REF_MUTATE_PURPOSE("WEAK_REF")); + GPR_ASSERT(old_refs != 0); + return c; +} + +grpc_subchannel* grpc_subchannel_ref_from_weak_ref( + grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + if (!c) return nullptr; + for (;;) { + gpr_atm old_refs = gpr_atm_acq_load(&c->ref_pair); + if (old_refs >= (1 << INTERNAL_REF_BITS)) { + gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS); + if (gpr_atm_rel_cas(&c->ref_pair, old_refs, new_refs)) { + return c; + } + } else { + return nullptr; } - if (w->next != nullptr) w->next->prev = w->prev; - if (w->prev != nullptr) w->prev->next = w->next; - gpr_mu_unlock(&w->subchannel->mu_); - GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher+done"); - Delete(w); - GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); } +} - Subchannel* subchannel; - grpc_pollset_set* pollset_set; - grpc_closure* notify; - grpc_closure on_state_changed; - ExternalStateWatcher* next = nullptr; - ExternalStateWatcher* prev = nullptr; -}; +static void disconnect(grpc_subchannel* c) { + // The subchannel_pool is only used once here in this subchannel, so the + // access can be outside of the lock. + if (c->subchannel_pool != nullptr) { + c->subchannel_pool->UnregisterSubchannel(c->key); + c->subchannel_pool.reset(); + } + gpr_mu_lock(&c->mu); + GPR_ASSERT(!c->disconnected); + c->disconnected = true; + grpc_connector_shutdown(c->connector, GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Subchannel disconnected")); + c->connected_subchannel.reset(); + c->connected_subchannel_watcher.reset(); + gpr_mu_unlock(&c->mu); +} -// -// Subchannel -// +void grpc_subchannel_unref(grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + // add a weak ref and subtract a strong ref (atomically) + old_refs = ref_mutate( + c, static_cast(1) - static_cast(1 << INTERNAL_REF_BITS), + 1 REF_MUTATE_PURPOSE("STRONG_UNREF")); + if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) { + disconnect(c); + } + GRPC_SUBCHANNEL_WEAK_UNREF(c, "strong-unref"); +} -namespace { +void grpc_subchannel_weak_unref( + grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + old_refs = ref_mutate(c, -static_cast(1), + 1 REF_MUTATE_PURPOSE("WEAK_UNREF")); + if (old_refs == 1) { + GRPC_CLOSURE_SCHED( + GRPC_CLOSURE_CREATE(subchannel_destroy, c, grpc_schedule_on_exec_ctx), + GRPC_ERROR_NONE); + } +} -BackOff::Options ParseArgsForBackoffValues( - const grpc_channel_args* args, grpc_millis* min_connect_timeout_ms) { +static void parse_args_for_backoff_values( + const grpc_channel_args* args, grpc_core::BackOff::Options* backoff_options, + grpc_millis* min_connect_timeout_ms) { grpc_millis initial_backoff_ms = GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000; *min_connect_timeout_ms = @@ -512,8 +511,7 @@ BackOff::Options ParseArgsForBackoffValues( } } } - return BackOff::Options() - .set_initial_backoff(initial_backoff_ms) + backoff_options->set_initial_backoff(initial_backoff_ms) .set_multiplier(fixed_reconnect_backoff ? 1.0 : GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER) @@ -522,6 +520,9 @@ BackOff::Options ParseArgsForBackoffValues( .set_max_backoff(max_backoff_ms); } +namespace grpc_core { +namespace { + struct HealthCheckParams { UniquePtr service_name; @@ -542,19 +543,31 @@ struct HealthCheckParams { }; } // namespace +} // namespace grpc_core -Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector, - const grpc_channel_args* args) - : key_(key), - connector_(connector), - backoff_(ParseArgsForBackoffValues(args, &min_connect_timeout_ms_)) { +grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, + const grpc_channel_args* args) { + grpc_core::SubchannelKey* key = + grpc_core::New(args); + grpc_core::SubchannelPoolInterface* subchannel_pool = + grpc_core::SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs( + args); + GPR_ASSERT(subchannel_pool != nullptr); + grpc_subchannel* c = subchannel_pool->FindSubchannel(key); + if (c != nullptr) { + grpc_core::Delete(key); + return c; + } GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED(); - gpr_atm_no_barrier_store(&ref_pair_, 1 << INTERNAL_REF_BITS); - grpc_connector_ref(connector_); - pollset_set_ = grpc_pollset_set_create(); + c = static_cast(gpr_zalloc(sizeof(*c))); + c->key = key; + gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS); + c->connector = connector; + grpc_connector_ref(c->connector); + c->pollset_set = grpc_pollset_set_create(); grpc_resolved_address* addr = static_cast(gpr_malloc(sizeof(*addr))); - GetAddressFromSubchannelAddressArg(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, &new_address, &new_args)) { @@ -563,492 +576,569 @@ Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector, addr = new_address; } static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS}; - grpc_arg new_arg = CreateSubchannelAddressArg(addr); + grpc_arg new_arg = grpc_create_subchannel_address_arg(addr); gpr_free(addr); - args_ = grpc_channel_args_copy_and_add_and_remove( + c->args = grpc_channel_args_copy_and_add_and_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); - GRPC_CLOSURE_INIT(&on_connecting_finished_, OnConnectingFinished, this, + c->root_external_state_watcher.next = c->root_external_state_watcher.prev = + &c->root_external_state_watcher; + GRPC_CLOSURE_INIT(&c->on_connected, on_subchannel_connected, c, grpc_schedule_on_exec_ctx); - grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE, + grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE, "subchannel"); - grpc_connectivity_state_init(&state_and_health_tracker_, GRPC_CHANNEL_IDLE, + grpc_connectivity_state_init(&c->state_and_health_tracker, GRPC_CHANNEL_IDLE, "subchannel"); - gpr_mu_init(&mu_); + grpc_core::BackOff::Options 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); + // Check whether we should enable health checking. const char* service_config_json = grpc_channel_arg_get_string( - grpc_channel_args_find(args_, GRPC_ARG_SERVICE_CONFIG)); + grpc_channel_args_find(c->args, GRPC_ARG_SERVICE_CONFIG)); if (service_config_json != nullptr) { - UniquePtr service_config = - ServiceConfig::Create(service_config_json); + grpc_core::UniquePtr service_config = + grpc_core::ServiceConfig::Create(service_config_json); if (service_config != nullptr) { - HealthCheckParams params; - service_config->ParseGlobalParams(HealthCheckParams::Parse, ¶ms); - health_check_service_name_ = std::move(params.service_name); + grpc_core::HealthCheckParams params; + service_config->ParseGlobalParams(grpc_core::HealthCheckParams::Parse, + ¶ms); + c->health_check_service_name = std::move(params.service_name); } } - const grpc_arg* arg = grpc_channel_args_find(args_, GRPC_ARG_ENABLE_CHANNELZ); - const bool channelz_enabled = + + const grpc_arg* arg = + grpc_channel_args_find(c->args, GRPC_ARG_ENABLE_CHANNELZ); + bool channelz_enabled = grpc_channel_arg_get_bool(arg, GRPC_ENABLE_CHANNELZ_DEFAULT); arg = grpc_channel_args_find( - args_, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE); + c->args, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE); const grpc_integer_options options = { GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT, 0, INT_MAX}; size_t channel_tracer_max_memory = (size_t)grpc_channel_arg_get_integer(arg, options); if (channelz_enabled) { - channelz_node_ = MakeRefCounted( - this, channel_tracer_max_memory); - channelz_node_->AddTraceEvent( - channelz::ChannelTrace::Severity::Info, - grpc_slice_from_static_string("subchannel created")); - } -} - -Subchannel::~Subchannel() { - if (channelz_node_ != nullptr) { - channelz_node_->AddTraceEvent( - channelz::ChannelTrace::Severity::Info, - grpc_slice_from_static_string("Subchannel destroyed")); - channelz_node_->MarkSubchannelDestroyed(); - } - grpc_channel_args_destroy(args_); - grpc_connectivity_state_destroy(&state_tracker_); - grpc_connectivity_state_destroy(&state_and_health_tracker_); - grpc_connector_unref(connector_); - grpc_pollset_set_destroy(pollset_set_); - Delete(key_); - gpr_mu_destroy(&mu_); -} - -Subchannel* Subchannel::Create(grpc_connector* connector, - const grpc_channel_args* args) { - SubchannelKey* key = New(args); - SubchannelPoolInterface* subchannel_pool = - SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs(args); - GPR_ASSERT(subchannel_pool != nullptr); - Subchannel* c = subchannel_pool->FindSubchannel(key); - if (c != nullptr) { - Delete(key); - return c; + c->channelz_subchannel = + grpc_core::MakeRefCounted( + c, channel_tracer_max_memory); + c->channelz_subchannel->AddTraceEvent( + grpc_core::channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Subchannel created")); } - c = New(key, connector, args); // Try to register the subchannel before setting the subchannel pool. // Otherwise, in case of a registration race, unreffing c in - // RegisterSubchannel() will cause c to be tried to be unregistered, while - // its key maps to a different subchannel. - Subchannel* registered = subchannel_pool->RegisterSubchannel(key, c); - if (registered == c) c->subchannel_pool_ = subchannel_pool->Ref(); + // RegisterSubchannel() will cause c to be tried to be unregistered, while its + // key maps to a different subchannel. + grpc_subchannel* registered = subchannel_pool->RegisterSubchannel(key, c); + if (registered == c) c->subchannel_pool = subchannel_pool->Ref(); return registered; } -Subchannel* Subchannel::Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = RefMutate((1 << INTERNAL_REF_BITS), - 0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_REF")); - GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0); - return this; +grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node( + grpc_subchannel* subchannel) { + return subchannel->channelz_subchannel.get(); } -void Subchannel::Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - // add a weak ref and subtract a strong ref (atomically) - old_refs = RefMutate( - static_cast(1) - static_cast(1 << INTERNAL_REF_BITS), - 1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_UNREF")); - if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) { - Disconnect(); +intptr_t grpc_subchannel_get_child_socket_uuid(grpc_subchannel* subchannel) { + if (subchannel->connected_subchannel != nullptr) { + return subchannel->connected_subchannel->socket_uuid(); + } else { + return 0; } - GRPC_SUBCHANNEL_WEAK_UNREF(this, "strong-unref"); -} - -Subchannel* Subchannel::WeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = RefMutate(1, 0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_REF")); - GPR_ASSERT(old_refs != 0); - return this; } -namespace { - -void subchannel_destroy(void* arg, grpc_error* error) { - Subchannel* self = static_cast(arg); - Delete(self); +static void continue_connect_locked(grpc_subchannel* c) { + grpc_connect_in_args args; + args.interested_parties = c->pollset_set; + const grpc_millis min_deadline = + c->min_connect_timeout_ms + grpc_core::ExecCtx::Get()->Now(); + c->next_attempt_deadline = c->backoff->NextAttemptTime(); + args.deadline = std::max(c->next_attempt_deadline, min_deadline); + args.channel_args = c->args; + set_subchannel_connectivity_state_locked(c, GRPC_CHANNEL_CONNECTING, + GRPC_ERROR_NONE, "connecting"); + grpc_connectivity_state_set(&c->state_and_health_tracker, + GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, + "connecting"); + grpc_connector_connect(c->connector, &args, &c->connecting_result, + &c->on_connected); } -} // namespace - -void Subchannel::WeakUnref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = RefMutate(-static_cast(1), - 1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_UNREF")); - if (old_refs == 1) { - GRPC_CLOSURE_SCHED(GRPC_CLOSURE_CREATE(subchannel_destroy, this, - grpc_schedule_on_exec_ctx), - GRPC_ERROR_NONE); - } +grpc_connectivity_state grpc_subchannel_check_connectivity( + grpc_subchannel* c, grpc_error** error, bool inhibit_health_checks) { + gpr_mu_lock(&c->mu); + grpc_connectivity_state_tracker* tracker = + inhibit_health_checks ? &c->state_tracker : &c->state_and_health_tracker; + grpc_connectivity_state state = grpc_connectivity_state_get(tracker, error); + gpr_mu_unlock(&c->mu); + return state; } -Subchannel* Subchannel::RefFromWeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - for (;;) { - gpr_atm old_refs = gpr_atm_acq_load(&ref_pair_); - if (old_refs >= (1 << INTERNAL_REF_BITS)) { - gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS); - if (gpr_atm_rel_cas(&ref_pair_, old_refs, new_refs)) { - return this; - } - } else { - return nullptr; - } +static void on_external_state_watcher_done(void* arg, grpc_error* error) { + external_state_watcher* w = static_cast(arg); + grpc_closure* follow_up = w->notify; + if (w->pollset_set != nullptr) { + grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set, + w->pollset_set); } + gpr_mu_lock(&w->subchannel->mu); + w->next->prev = w->prev; + w->prev->next = w->next; + gpr_mu_unlock(&w->subchannel->mu); + GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher"); + gpr_free(w); + GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); } -intptr_t Subchannel::GetChildSocketUuid() { - if (connected_subchannel_ != nullptr) { - return connected_subchannel_->socket_uuid(); +static void on_alarm(void* arg, grpc_error* error) { + grpc_subchannel* c = static_cast(arg); + gpr_mu_lock(&c->mu); + c->have_alarm = false; + if (c->disconnected) { + error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", + &error, 1); + } else if (c->retry_immediately) { + c->retry_immediately = false; + error = GRPC_ERROR_NONE; } else { - return 0; + GRPC_ERROR_REF(error); } + if (error == GRPC_ERROR_NONE) { + gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); + continue_connect_locked(c); + gpr_mu_unlock(&c->mu); + } else { + gpr_mu_unlock(&c->mu); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } + GRPC_ERROR_UNREF(error); } -const char* Subchannel::GetTargetAddress() { - const grpc_arg* addr_arg = - grpc_channel_args_find(args_, GRPC_ARG_SUBCHANNEL_ADDRESS); - const char* addr_str = grpc_channel_arg_get_string(addr_arg); - GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. - return addr_str; -} - -RefCountedPtr Subchannel::connected_subchannel() { - MutexLock lock(&mu_); - return connected_subchannel_; -} - -channelz::SubchannelNode* Subchannel::channelz_node() { - return channelz_node_.get(); -} - -grpc_connectivity_state Subchannel::CheckConnectivity( - grpc_error** error, bool inhibit_health_checks) { - MutexLock lock(&mu_); - grpc_connectivity_state_tracker* tracker = - inhibit_health_checks ? &state_tracker_ : &state_and_health_tracker_; - grpc_connectivity_state state = grpc_connectivity_state_get(tracker, error); - return state; +static void maybe_start_connecting_locked(grpc_subchannel* c) { + if (c->disconnected) { + /* Don't try to connect if we're already disconnected */ + return; + } + if (c->connecting) { + /* Already connecting: don't restart */ + return; + } + if (c->connected_subchannel != nullptr) { + /* Already connected: don't restart */ + return; + } + if (!grpc_connectivity_state_has_watchers(&c->state_tracker) && + !grpc_connectivity_state_has_watchers(&c->state_and_health_tracker)) { + /* Nobody is interested in connecting: so don't just yet */ + return; + } + c->connecting = true; + GRPC_SUBCHANNEL_WEAK_REF(c, "connecting"); + if (!c->backoff_begun) { + c->backoff_begun = true; + continue_connect_locked(c); + } else { + GPR_ASSERT(!c->have_alarm); + c->have_alarm = true; + const grpc_millis time_til_next = + c->next_attempt_deadline - grpc_core::ExecCtx::Get()->Now(); + if (time_til_next <= 0) { + gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", c); + } else { + gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRId64 " milliseconds", c, + time_til_next); + } + GRPC_CLOSURE_INIT(&c->on_alarm, on_alarm, c, grpc_schedule_on_exec_ctx); + grpc_timer_init(&c->alarm, c->next_attempt_deadline, &c->on_alarm); + } } -void Subchannel::NotifyOnStateChange(grpc_pollset_set* interested_parties, - grpc_connectivity_state* state, - grpc_closure* notify, - bool inhibit_health_checks) { +void grpc_subchannel_notify_on_state_change( + grpc_subchannel* c, grpc_pollset_set* interested_parties, + grpc_connectivity_state* state, grpc_closure* notify, + bool inhibit_health_checks) { grpc_connectivity_state_tracker* tracker = - inhibit_health_checks ? &state_tracker_ : &state_and_health_tracker_; - ExternalStateWatcher* w; + inhibit_health_checks ? &c->state_tracker : &c->state_and_health_tracker; + external_state_watcher* w; if (state == nullptr) { - MutexLock lock(&mu_); - for (w = external_state_watcher_list_; w != nullptr; w = w->next) { + gpr_mu_lock(&c->mu); + for (w = c->root_external_state_watcher.next; + w != &c->root_external_state_watcher; w = w->next) { if (w->notify == notify) { grpc_connectivity_state_notify_on_state_change(tracker, nullptr, - &w->on_state_changed); + &w->closure); } } + gpr_mu_unlock(&c->mu); } else { - w = New(this, interested_parties, notify); + w = static_cast(gpr_malloc(sizeof(*w))); + w->subchannel = c; + w->pollset_set = interested_parties; + w->notify = notify; + GRPC_CLOSURE_INIT(&w->closure, on_external_state_watcher_done, w, + grpc_schedule_on_exec_ctx); if (interested_parties != nullptr) { - grpc_pollset_set_add_pollset_set(pollset_set_, interested_parties); + grpc_pollset_set_add_pollset_set(c->pollset_set, interested_parties); } - MutexLock lock(&mu_); - if (external_state_watcher_list_ != nullptr) { - w->next = external_state_watcher_list_; - w->next->prev = w; - } - external_state_watcher_list_ = w; - grpc_connectivity_state_notify_on_state_change(tracker, state, - &w->on_state_changed); - MaybeStartConnectingLocked(); + GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher"); + gpr_mu_lock(&c->mu); + w->next = &c->root_external_state_watcher; + w->prev = w->next->prev; + w->next->prev = w->prev->next = w; + grpc_connectivity_state_notify_on_state_change(tracker, state, &w->closure); + maybe_start_connecting_locked(c); + gpr_mu_unlock(&c->mu); } } -void Subchannel::ResetBackoff() { - MutexLock lock(&mu_); - backoff_.Reset(); - if (have_retry_alarm_) { - retry_immediately_ = true; - grpc_timer_cancel(&retry_alarm_); - } else { - backoff_begun_ = false; - MaybeStartConnectingLocked(); +static bool publish_transport_locked(grpc_subchannel* c) { + /* construct channel stack */ + grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create(); + grpc_channel_stack_builder_set_channel_arguments( + builder, c->connecting_result.channel_args); + grpc_channel_stack_builder_set_transport(builder, + c->connecting_result.transport); + + if (!grpc_channel_init_create_stack(builder, GRPC_CLIENT_SUBCHANNEL)) { + grpc_channel_stack_builder_destroy(builder); + return false; } -} + grpc_channel_stack* stk; + grpc_error* error = grpc_channel_stack_builder_finish( + builder, 0, 1, connection_destroy, nullptr, + reinterpret_cast(&stk)); + if (error != GRPC_ERROR_NONE) { + grpc_transport_destroy(c->connecting_result.transport); + gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", + grpc_error_string(error)); + GRPC_ERROR_UNREF(error); + return false; + } + intptr_t socket_uuid = c->connecting_result.socket_uuid; + memset(&c->connecting_result, 0, sizeof(c->connecting_result)); -grpc_arg Subchannel::CreateSubchannelAddressArg( - const grpc_resolved_address* addr) { - return grpc_channel_arg_string_create( - (char*)GRPC_ARG_SUBCHANNEL_ADDRESS, - addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup("")); -} + if (c->disconnected) { + grpc_channel_stack_destroy(stk); + gpr_free(stk); + return false; + } -const char* Subchannel::GetUriFromSubchannelAddressArg( - const grpc_channel_args* args) { - const grpc_arg* addr_arg = - grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); - const char* addr_str = grpc_channel_arg_get_string(addr_arg); - GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. - return addr_str; -} + /* publish */ + c->connected_subchannel.reset(grpc_core::New( + stk, c->args, c->channelz_subchannel, socket_uuid)); + gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p", + c->connected_subchannel.get(), c); -namespace { + // Instantiate state watcher. Will clean itself up. + c->connected_subchannel_watcher = + grpc_core::MakeOrphanable(c); -void UriToSockaddr(const char* uri_str, grpc_resolved_address* addr) { - grpc_uri* uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */); - GPR_ASSERT(uri != nullptr); - if (!grpc_parse_uri(uri, addr)) memset(addr, 0, sizeof(*addr)); - grpc_uri_destroy(uri); + return true; } -} // namespace +static void on_subchannel_connected(void* arg, grpc_error* error) { + grpc_subchannel* c = static_cast(arg); + grpc_channel_args* delete_channel_args = c->connecting_result.channel_args; + + GRPC_SUBCHANNEL_WEAK_REF(c, "on_subchannel_connected"); + gpr_mu_lock(&c->mu); + c->connecting = false; + if (c->connecting_result.transport != nullptr && + publish_transport_locked(c)) { + /* do nothing, transport was published */ + } else if (c->disconnected) { + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } else { + set_subchannel_connectivity_state_locked( + c, GRPC_CHANNEL_TRANSIENT_FAILURE, + grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Connect Failed", &error, 1), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), + "connect_failed"); + grpc_connectivity_state_set( + &c->state_and_health_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, + grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Connect Failed", &error, 1), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), + "connect_failed"); -void Subchannel::GetAddressFromSubchannelAddressArg( - const grpc_channel_args* args, grpc_resolved_address* addr) { - const char* addr_uri_str = GetUriFromSubchannelAddressArg(args); - memset(addr, 0, sizeof(*addr)); - if (*addr_uri_str != '\0') { - UriToSockaddr(addr_uri_str, addr); + const char* errmsg = grpc_error_string(error); + gpr_log(GPR_INFO, "Connect failed: %s", errmsg); + + maybe_start_connecting_locked(c); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); } + gpr_mu_unlock(&c->mu); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connected"); + grpc_channel_args_destroy(delete_channel_args); } -namespace { - -// Returns a string indicating the subchannel's connectivity state change to -// \a state. -const char* SubchannelConnectivityStateChangeString( - grpc_connectivity_state state) { - switch (state) { - case GRPC_CHANNEL_IDLE: - return "Subchannel state change to IDLE"; - case GRPC_CHANNEL_CONNECTING: - return "Subchannel state change to CONNECTING"; - case GRPC_CHANNEL_READY: - return "Subchannel state change to READY"; - case GRPC_CHANNEL_TRANSIENT_FAILURE: - return "Subchannel state change to TRANSIENT_FAILURE"; - case GRPC_CHANNEL_SHUTDOWN: - return "Subchannel state change to SHUTDOWN"; +void grpc_subchannel_reset_backoff(grpc_subchannel* subchannel) { + gpr_mu_lock(&subchannel->mu); + subchannel->backoff->Reset(); + if (subchannel->have_alarm) { + subchannel->retry_immediately = true; + grpc_timer_cancel(&subchannel->alarm); + } else { + subchannel->backoff_begun = false; + maybe_start_connecting_locked(subchannel); } - GPR_UNREACHABLE_CODE(return "UNKNOWN"); + gpr_mu_unlock(&subchannel->mu); } -} // namespace +/* + * grpc_subchannel_call implementation + */ -void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state, - grpc_error* error, - const char* reason) { - if (channelz_node_ != nullptr) { - channelz_node_->AddTraceEvent( - channelz::ChannelTrace::Severity::Info, - grpc_slice_from_static_string( - SubchannelConnectivityStateChangeString(state))); - } - grpc_connectivity_state_set(&state_tracker_, state, error, reason); +static void subchannel_call_destroy(void* call, grpc_error* error) { + GPR_TIMER_SCOPE("grpc_subchannel_call_unref.destroy", 0); + grpc_subchannel_call* c = static_cast(call); + grpc_core::ConnectedSubchannel* connection = c->connection; + grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(c), nullptr, + c->schedule_closure_after_destroy); + connection->Unref(DEBUG_LOCATION, "subchannel_call"); + c->~grpc_subchannel_call(); } -void Subchannel::MaybeStartConnectingLocked() { - if (disconnected_) { - // Don't try to connect if we're already disconnected. - return; - } - if (connecting_) { - // Already connecting: don't restart. - return; - } - if (connected_subchannel_ != nullptr) { - // Already connected: don't restart. - return; - } - if (!grpc_connectivity_state_has_watchers(&state_tracker_) && - !grpc_connectivity_state_has_watchers(&state_and_health_tracker_)) { - // Nobody is interested in connecting: so don't just yet. - return; - } - connecting_ = true; - GRPC_SUBCHANNEL_WEAK_REF(this, "connecting"); - if (!backoff_begun_) { - backoff_begun_ = true; - ContinueConnectingLocked(); +void grpc_subchannel_call_set_cleanup_closure(grpc_subchannel_call* call, + grpc_closure* closure) { + GPR_ASSERT(call->schedule_closure_after_destroy == nullptr); + GPR_ASSERT(closure != nullptr); + call->schedule_closure_after_destroy = closure; +} + +grpc_subchannel_call* grpc_subchannel_call_ref( + grpc_subchannel_call* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON); + return c; +} + +void grpc_subchannel_call_unref( + grpc_subchannel_call* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON); +} + +// Sets *status based on md_batch and error. +static void get_call_status(grpc_subchannel_call* call, + grpc_metadata_batch* md_batch, grpc_error* error, + grpc_status_code* status) { + if (error != GRPC_ERROR_NONE) { + grpc_error_get_status(error, call->deadline, status, nullptr, nullptr, + nullptr); } else { - GPR_ASSERT(!have_retry_alarm_); - have_retry_alarm_ = true; - const grpc_millis time_til_next = - next_attempt_deadline_ - ExecCtx::Get()->Now(); - if (time_til_next <= 0) { - gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", this); + if (md_batch->idx.named.grpc_status != nullptr) { + *status = grpc_get_status_code_from_metadata( + md_batch->idx.named.grpc_status->md); } else { - gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRId64 " milliseconds", - this, time_til_next); + *status = GRPC_STATUS_UNKNOWN; } - GRPC_CLOSURE_INIT(&on_retry_alarm_, OnRetryAlarm, this, - grpc_schedule_on_exec_ctx); - grpc_timer_init(&retry_alarm_, next_attempt_deadline_, &on_retry_alarm_); } + GRPC_ERROR_UNREF(error); } -void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { - Subchannel* c = static_cast(arg); - gpr_mu_lock(&c->mu_); - c->have_retry_alarm_ = false; - if (c->disconnected_) { - error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", - &error, 1); - } else if (c->retry_immediately_) { - c->retry_immediately_ = false; - error = GRPC_ERROR_NONE; +static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { + grpc_subchannel_call* call = static_cast(arg); + GPR_ASSERT(call->recv_trailing_metadata != nullptr); + grpc_status_code status = GRPC_STATUS_OK; + grpc_metadata_batch* md_batch = call->recv_trailing_metadata; + get_call_status(call, md_batch, GRPC_ERROR_REF(error), &status); + grpc_core::channelz::SubchannelNode* channelz_subchannel = + call->connection->channelz_subchannel(); + GPR_ASSERT(channelz_subchannel != nullptr); + if (status == GRPC_STATUS_OK) { + channelz_subchannel->RecordCallSucceeded(); } else { - GRPC_ERROR_REF(error); + channelz_subchannel->RecordCallFailed(); } - if (error == GRPC_ERROR_NONE) { - gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); - c->ContinueConnectingLocked(); - gpr_mu_unlock(&c->mu_); - } else { - gpr_mu_unlock(&c->mu_); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + GRPC_CLOSURE_RUN(call->original_recv_trailing_metadata, + GRPC_ERROR_REF(error)); +} + +// If channelz is enabled, intercept recv_trailing so that we may check the +// status and associate it to a subchannel. +static void maybe_intercept_recv_trailing_metadata( + grpc_subchannel_call* call, grpc_transport_stream_op_batch* batch) { + // only intercept payloads with recv trailing. + if (!batch->recv_trailing_metadata) { + return; } - GRPC_ERROR_UNREF(error); + // only add interceptor is channelz is enabled. + if (call->connection->channelz_subchannel() == nullptr) { + return; + } + GRPC_CLOSURE_INIT(&call->recv_trailing_metadata_ready, + recv_trailing_metadata_ready, call, + grpc_schedule_on_exec_ctx); + // save some state needed for the interception callback. + GPR_ASSERT(call->recv_trailing_metadata == nullptr); + call->recv_trailing_metadata = + batch->payload->recv_trailing_metadata.recv_trailing_metadata; + call->original_recv_trailing_metadata = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &call->recv_trailing_metadata_ready; } -void Subchannel::ContinueConnectingLocked() { - grpc_connect_in_args args; - args.interested_parties = pollset_set_; - const grpc_millis min_deadline = - min_connect_timeout_ms_ + ExecCtx::Get()->Now(); - next_attempt_deadline_ = backoff_.NextAttemptTime(); - args.deadline = std::max(next_attempt_deadline_, min_deadline); - args.channel_args = args_; - SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, - "connecting"); - grpc_connectivity_state_set(&state_and_health_tracker_, - GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, - "connecting"); - grpc_connector_connect(connector_, &args, &connecting_result_, - &on_connecting_finished_); +void grpc_subchannel_call_process_op(grpc_subchannel_call* call, + grpc_transport_stream_op_batch* batch) { + GPR_TIMER_SCOPE("grpc_subchannel_call_process_op", 0); + maybe_intercept_recv_trailing_metadata(call, batch); + grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call); + grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0); + GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch); + top_elem->filter->start_transport_stream_op_batch(top_elem, batch); } -void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) { - auto* c = static_cast(arg); - grpc_channel_args* delete_channel_args = c->connecting_result_.channel_args; - GRPC_SUBCHANNEL_WEAK_REF(c, "on_connecting_finished"); - gpr_mu_lock(&c->mu_); - c->connecting_ = false; - if (c->connecting_result_.transport != nullptr && - c->PublishTransportLocked()) { - // Do nothing, transport was published. - } else if (c->disconnected_) { - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); - } else { - c->SetConnectivityStateLocked( - GRPC_CHANNEL_TRANSIENT_FAILURE, - grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Connect Failed", &error, 1), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), - "connect_failed"); - grpc_connectivity_state_set( - &c->state_and_health_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE, - grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Connect Failed", &error, 1), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), - "connect_failed"); +grpc_core::RefCountedPtr +grpc_subchannel_get_connected_subchannel(grpc_subchannel* c) { + gpr_mu_lock(&c->mu); + auto copy = c->connected_subchannel; + gpr_mu_unlock(&c->mu); + return copy; +} - const char* errmsg = grpc_error_string(error); - gpr_log(GPR_INFO, "Connect failed: %s", errmsg); +void* grpc_connected_subchannel_call_get_parent_data( + grpc_subchannel_call* subchannel_call) { + grpc_channel_stack* chanstk = subchannel_call->connection->channel_stack(); + return (char*)subchannel_call + + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_subchannel_call)) + + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(chanstk->call_stack_size); +} - c->MaybeStartConnectingLocked(); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); +grpc_call_stack* grpc_subchannel_call_get_call_stack( + grpc_subchannel_call* subchannel_call) { + return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call); +} + +static void grpc_uri_to_sockaddr(const char* uri_str, + grpc_resolved_address* addr) { + grpc_uri* uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */); + GPR_ASSERT(uri != nullptr); + if (!grpc_parse_uri(uri, addr)) memset(addr, 0, sizeof(*addr)); + grpc_uri_destroy(uri); +} + +void grpc_get_subchannel_address_arg(const grpc_channel_args* args, + grpc_resolved_address* addr) { + const char* addr_uri_str = grpc_get_subchannel_address_uri_arg(args); + memset(addr, 0, sizeof(*addr)); + if (*addr_uri_str != '\0') { + grpc_uri_to_sockaddr(addr_uri_str, addr); } - gpr_mu_unlock(&c->mu_); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "on_connecting_finished"); - grpc_channel_args_destroy(delete_channel_args); } -namespace { +const char* grpc_subchannel_get_target(grpc_subchannel* subchannel) { + const grpc_arg* addr_arg = + grpc_channel_args_find(subchannel->args, GRPC_ARG_SUBCHANNEL_ADDRESS); + const char* addr_str = grpc_channel_arg_get_string(addr_arg); + GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. + return addr_str; +} -void ConnectionDestroy(void* arg, grpc_error* error) { - grpc_channel_stack* stk = static_cast(arg); - grpc_channel_stack_destroy(stk); - gpr_free(stk); +const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args) { + const grpc_arg* addr_arg = + grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); + const char* addr_str = grpc_channel_arg_get_string(addr_arg); + GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. + return addr_str; } -} // namespace +grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr) { + return grpc_channel_arg_string_create( + (char*)GRPC_ARG_SUBCHANNEL_ADDRESS, + addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup("")); +} -bool Subchannel::PublishTransportLocked() { - // Construct channel stack. - grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create(); - grpc_channel_stack_builder_set_channel_arguments( - builder, connecting_result_.channel_args); - grpc_channel_stack_builder_set_transport(builder, - connecting_result_.transport); - if (!grpc_channel_init_create_stack(builder, GRPC_CLIENT_SUBCHANNEL)) { - grpc_channel_stack_builder_destroy(builder); - return false; - } - grpc_channel_stack* stk; - grpc_error* error = grpc_channel_stack_builder_finish( - builder, 0, 1, ConnectionDestroy, nullptr, - reinterpret_cast(&stk)); - if (error != GRPC_ERROR_NONE) { - grpc_transport_destroy(connecting_result_.transport); - gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", - grpc_error_string(error)); - GRPC_ERROR_UNREF(error); - return false; - } - intptr_t socket_uuid = connecting_result_.socket_uuid; - memset(&connecting_result_, 0, sizeof(connecting_result_)); - if (disconnected_) { - grpc_channel_stack_destroy(stk); - gpr_free(stk); - return false; - } - // Publish. - connected_subchannel_.reset( - New(stk, args_, channelz_node_, socket_uuid)); - gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p", - connected_subchannel_.get(), this); - // Instantiate state watcher. Will clean itself up. - connected_subchannel_watcher_ = - MakeOrphanable(this); - return true; +namespace grpc_core { + +ConnectedSubchannel::ConnectedSubchannel( + grpc_channel_stack* channel_stack, const grpc_channel_args* args, + grpc_core::RefCountedPtr + channelz_subchannel, + intptr_t socket_uuid) + : RefCounted(&grpc_trace_stream_refcount), + channel_stack_(channel_stack), + args_(grpc_channel_args_copy(args)), + channelz_subchannel_(std::move(channelz_subchannel)), + socket_uuid_(socket_uuid) {} + +ConnectedSubchannel::~ConnectedSubchannel() { + grpc_channel_args_destroy(args_); + GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor"); } -void Subchannel::Disconnect() { - // The subchannel_pool is only used once here in this subchannel, so the - // access can be outside of the lock. - if (subchannel_pool_ != nullptr) { - subchannel_pool_->UnregisterSubchannel(key_); - subchannel_pool_.reset(); +void ConnectedSubchannel::NotifyOnStateChange( + grpc_pollset_set* interested_parties, grpc_connectivity_state* state, + grpc_closure* closure) { + grpc_transport_op* op = grpc_make_transport_op(nullptr); + grpc_channel_element* elem; + op->connectivity_state = state; + op->on_connectivity_state_change = closure; + op->bind_pollset_set = interested_parties; + elem = grpc_channel_stack_element(channel_stack_, 0); + elem->filter->start_transport_op(elem, op); +} + +void ConnectedSubchannel::Ping(grpc_closure* on_initiate, + grpc_closure* on_ack) { + grpc_transport_op* op = grpc_make_transport_op(nullptr); + grpc_channel_element* elem; + op->send_ping.on_initiate = on_initiate; + op->send_ping.on_ack = on_ack; + elem = grpc_channel_stack_element(channel_stack_, 0); + elem->filter->start_transport_op(elem, op); +} + +grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, + grpc_subchannel_call** call) { + const size_t allocation_size = + GetInitialCallSizeEstimate(args.parent_data_size); + *call = new (gpr_arena_alloc(args.arena, allocation_size)) + grpc_subchannel_call(this, args); + grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call); + RefCountedPtr connection = + Ref(DEBUG_LOCATION, "subchannel_call"); + connection.release(); // Ref is passed to the grpc_subchannel_call object. + const grpc_call_element_args call_args = { + callstk, /* call_stack */ + nullptr, /* server_transport_data */ + args.context, /* context */ + args.path, /* path */ + args.start_time, /* start_time */ + args.deadline, /* deadline */ + args.arena, /* arena */ + args.call_combiner /* call_combiner */ + }; + grpc_error* error = grpc_call_stack_init( + channel_stack_, 1, subchannel_call_destroy, *call, &call_args); + if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { + const char* error_string = grpc_error_string(error); + gpr_log(GPR_ERROR, "error: %s", error_string); + return error; } - MutexLock lock(&mu_); - GPR_ASSERT(!disconnected_); - disconnected_ = true; - grpc_connector_shutdown(connector_, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Subchannel disconnected")); - connected_subchannel_.reset(); - connected_subchannel_watcher_.reset(); + grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); + if (channelz_subchannel_ != nullptr) { + channelz_subchannel_->RecordCallStarted(); + } + return GRPC_ERROR_NONE; } -gpr_atm Subchannel::RefMutate( - gpr_atm delta, int barrier GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS) { - gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&ref_pair_, delta) - : gpr_atm_no_barrier_fetch_add(&ref_pair_, delta); -#ifndef NDEBUG - if (grpc_trace_stream_refcount.enabled()) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", this, - purpose, old_val, old_val + delta, reason); +size_t ConnectedSubchannel::GetInitialCallSizeEstimate( + size_t parent_data_size) const { + size_t allocation_size = + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_subchannel_call)); + if (parent_data_size > 0) { + allocation_size += + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) + + parent_data_size; + } else { + allocation_size += channel_stack_->call_stack_size; } -#endif - return old_val; + return allocation_size; } } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 88282c9d95e..fac515eee5c 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -24,49 +24,53 @@ #include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/connector.h" #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" -#include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/gpr/arena.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/polling_entity.h" -#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/metadata.h" // Channel arg containing a grpc_resolved_address to connect to. #define GRPC_ARG_SUBCHANNEL_ADDRESS "grpc.subchannel_address" -// For debugging refcounting. +/** A (sub-)channel that knows how to connect to exactly one target + address. Provides a target for load balancing. */ +typedef struct grpc_subchannel grpc_subchannel; +typedef struct grpc_subchannel_call grpc_subchannel_call; + #ifndef NDEBUG -#define GRPC_SUBCHANNEL_REF(p, r) (p)->Ref(__FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_REF(p, r) \ + grpc_subchannel_ref((p), __FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \ - (p)->RefFromWeakRef(__FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_UNREF(p, r) (p)->Unref(__FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_WEAK_REF(p, r) (p)->WeakRef(__FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) (p)->WeakUnref(__FILE__, __LINE__, (r)) + grpc_subchannel_ref_from_weak_ref((p), __FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_UNREF(p, r) \ + grpc_subchannel_unref((p), __FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_WEAK_REF(p, r) \ + grpc_subchannel_weak_ref((p), __FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) \ + grpc_subchannel_weak_unref((p), __FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_CALL_REF(p, r) \ + grpc_subchannel_call_ref((p), __FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_CALL_UNREF(p, r) \ + grpc_subchannel_call_unref((p), __FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS \ - const char *file, int line, const char *reason -#define GRPC_SUBCHANNEL_REF_REASON reason -#define GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS \ - , GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char* purpose -#define GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE(x) , file, line, reason, x + , const char *file, int line, const char *reason #else -#define GRPC_SUBCHANNEL_REF(p, r) (p)->Ref() -#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) (p)->RefFromWeakRef() -#define GRPC_SUBCHANNEL_UNREF(p, r) (p)->Unref() -#define GRPC_SUBCHANNEL_WEAK_REF(p, r) (p)->WeakRef() -#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) (p)->WeakUnref() +#define GRPC_SUBCHANNEL_REF(p, r) grpc_subchannel_ref((p)) +#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \ + grpc_subchannel_ref_from_weak_ref((p)) +#define GRPC_SUBCHANNEL_UNREF(p, r) grpc_subchannel_unref((p)) +#define GRPC_SUBCHANNEL_WEAK_REF(p, r) grpc_subchannel_weak_ref((p)) +#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) grpc_subchannel_weak_unref((p)) +#define GRPC_SUBCHANNEL_CALL_REF(p, r) grpc_subchannel_call_ref((p)) +#define GRPC_SUBCHANNEL_CALL_UNREF(p, r) grpc_subchannel_call_unref((p)) #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS -#define GRPC_SUBCHANNEL_REF_REASON "" -#define GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS -#define GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE(x) #endif namespace grpc_core { -class SubchannelCall; - class ConnectedSubchannel : public RefCounted { public: struct CallArgs { @@ -82,7 +86,8 @@ class ConnectedSubchannel : public RefCounted { ConnectedSubchannel( grpc_channel_stack* channel_stack, const grpc_channel_args* args, - RefCountedPtr channelz_subchannel, + grpc_core::RefCountedPtr + channelz_subchannel, intptr_t socket_uuid); ~ConnectedSubchannel(); @@ -90,8 +95,7 @@ class ConnectedSubchannel : public RefCounted { grpc_connectivity_state* state, grpc_closure* closure); void Ping(grpc_closure* on_initiate, grpc_closure* on_ack); - RefCountedPtr CreateCall(const CallArgs& args, - grpc_error** error); + grpc_error* CreateCall(const CallArgs& args, grpc_subchannel_call** call); grpc_channel_stack* channel_stack() const { return channel_stack_; } const grpc_channel_args* args() const { return args_; } @@ -107,204 +111,91 @@ class ConnectedSubchannel : public RefCounted { grpc_channel_args* args_; // ref counted pointer to the channelz node in this connected subchannel's // owning subchannel. - RefCountedPtr channelz_subchannel_; + grpc_core::RefCountedPtr + channelz_subchannel_; // uuid of this subchannel's socket. 0 if this subchannel is not connected. const intptr_t socket_uuid_; }; -// Implements the interface of RefCounted<>. -class SubchannelCall { - public: - SubchannelCall(RefCountedPtr connected_subchannel, - const ConnectedSubchannel::CallArgs& args) - : connected_subchannel_(std::move(connected_subchannel)), - deadline_(args.deadline) {} - - // Continues processing a transport stream op batch. - void StartTransportStreamOpBatch(grpc_transport_stream_op_batch* batch); - - // Returns a pointer to the parent data associated with the subchannel call. - // The data will be of the size specified in \a parent_data_size field of - // the args passed to \a ConnectedSubchannel::CreateCall(). - void* GetParentData(); - - // Returns the call stack of the subchannel call. - grpc_call_stack* GetCallStack(); - - grpc_closure* after_call_stack_destroy() const { - return after_call_stack_destroy_; - } - - // Sets the 'then_schedule_closure' argument for call stack destruction. - // Must be called once per call. - void SetAfterCallStackDestroy(grpc_closure* closure); - - // Interface of RefCounted<>. - RefCountedPtr Ref() GRPC_MUST_USE_RESULT; - RefCountedPtr Ref(const DebugLocation& location, - const char* reason) GRPC_MUST_USE_RESULT; - // When refcount drops to 0, destroys itself and the associated call stack, - // but does NOT free the memory because it's in the call arena. - void Unref(); - void Unref(const DebugLocation& location, const char* reason); - - private: - // Allow RefCountedPtr<> to access IncrementRefCount(). - template - friend class RefCountedPtr; - - // If channelz is enabled, intercepts recv_trailing so that we may check the - // status and associate it to a subchannel. - void MaybeInterceptRecvTrailingMetadata( - grpc_transport_stream_op_batch* batch); - - static void RecvTrailingMetadataReady(void* arg, grpc_error* error); - - // Interface of RefCounted<>. - void IncrementRefCount(); - void IncrementRefCount(const DebugLocation& location, const char* reason); - - RefCountedPtr connected_subchannel_; - grpc_closure* after_call_stack_destroy_ = nullptr; - // State needed to support channelz interception of recv trailing metadata. - grpc_closure recv_trailing_metadata_ready_; - grpc_closure* original_recv_trailing_metadata_ = nullptr; - grpc_metadata_batch* recv_trailing_metadata_ = nullptr; - grpc_millis deadline_; -}; - -// A subchannel that knows how to connect to exactly one target address. It -// provides a target for load balancing. -class Subchannel { - public: - // The ctor and dtor are not intended to use directly. - Subchannel(SubchannelKey* key, grpc_connector* connector, - const grpc_channel_args* args); - ~Subchannel(); - - // Creates a subchannel given \a connector and \a args. - static Subchannel* Create(grpc_connector* connector, - const grpc_channel_args* args); - - // Strong and weak refcounting. - Subchannel* Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); - void Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); - Subchannel* WeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); - void WeakUnref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); - Subchannel* RefFromWeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); - - intptr_t GetChildSocketUuid(); - - // Gets the string representing the subchannel address. - // Caller doesn't take ownership. - const char* GetTargetAddress(); - - // Gets the connected subchannel - or nullptr if not connected (which may - // happen before it initially connects or during transient failures). - RefCountedPtr connected_subchannel(); - - channelz::SubchannelNode* channelz_node(); - - // Polls the current connectivity state of the subchannel. - grpc_connectivity_state CheckConnectivity(grpc_error** error, - bool inhibit_health_checking); - - // When the connectivity state of the subchannel changes from \a *state, - // invokes \a notify and updates \a *state with the new state. - void NotifyOnStateChange(grpc_pollset_set* interested_parties, - grpc_connectivity_state* state, grpc_closure* notify, - bool inhibit_health_checks); - - // Resets the connection backoff of the subchannel. - // TODO(roth): Move connection backoff out of subchannels and up into LB - // policy code (probably by adding a SubchannelGroup between - // SubchannelList and SubchannelData), at which point this method can - // go away. - void ResetBackoff(); - - // Returns a new channel arg encoding the subchannel address as a URI - // string. Caller is responsible for freeing the string. - static grpc_arg CreateSubchannelAddressArg(const grpc_resolved_address* addr); - - // Returns the URI string from the subchannel address arg in \a args. - static const char* GetUriFromSubchannelAddressArg( - const grpc_channel_args* args); - - // Sets \a addr from the subchannel address arg in \a args. - static void GetAddressFromSubchannelAddressArg(const grpc_channel_args* args, - grpc_resolved_address* addr); - - private: - struct ExternalStateWatcher; - class ConnectedSubchannelStateWatcher; - - // Sets the subchannel's connectivity state to \a state. - void SetConnectivityStateLocked(grpc_connectivity_state state, - grpc_error* error, const char* reason); - - // Methods for connection. - void MaybeStartConnectingLocked(); - static void OnRetryAlarm(void* arg, grpc_error* error); - void ContinueConnectingLocked(); - static void OnConnectingFinished(void* arg, grpc_error* error); - bool PublishTransportLocked(); - void Disconnect(); - - gpr_atm RefMutate(gpr_atm delta, - int barrier GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS); - - // The subchannel pool this subchannel is in. - RefCountedPtr subchannel_pool_; - // TODO(juanlishen): Consider using args_ as key_ directly. - // Subchannel key that identifies this subchannel in the subchannel pool. - SubchannelKey* key_; - // Channel args. - grpc_channel_args* args_; - // pollset_set tracking who's interested in a connection being setup. - grpc_pollset_set* pollset_set_; - // Protects the other members. - gpr_mu mu_; - // Refcount - // - lower INTERNAL_REF_BITS bits are for internal references: - // these do not keep the subchannel open. - // - upper remaining bits are for public references: these do - // keep the subchannel open - gpr_atm ref_pair_; - - // Connection states. - grpc_connector* connector_ = nullptr; - // Set during connection. - grpc_connect_out_args connecting_result_; - grpc_closure on_connecting_finished_; - // Active connection, or null. - RefCountedPtr connected_subchannel_; - OrphanablePtr connected_subchannel_watcher_; - bool connecting_ = false; - bool disconnected_ = false; - - // Connectivity state tracking. - grpc_connectivity_state_tracker state_tracker_; - grpc_connectivity_state_tracker state_and_health_tracker_; - UniquePtr health_check_service_name_; - ExternalStateWatcher* external_state_watcher_list_ = nullptr; - - // Backoff state. - BackOff backoff_; - grpc_millis next_attempt_deadline_; - grpc_millis min_connect_timeout_ms_; - bool backoff_begun_ = false; - - // Retry alarm. - grpc_timer retry_alarm_; - grpc_closure on_retry_alarm_; - bool have_retry_alarm_ = false; - // reset_backoff() was called while alarm was pending. - bool retry_immediately_ = false; - - // Channelz tracking. - RefCountedPtr channelz_node_; -}; - } // namespace grpc_core +grpc_subchannel* grpc_subchannel_ref( + grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); +grpc_subchannel* grpc_subchannel_ref_from_weak_ref( + grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); +void grpc_subchannel_unref( + grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); +grpc_subchannel* grpc_subchannel_weak_ref( + grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); +void grpc_subchannel_weak_unref( + grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); +grpc_subchannel_call* grpc_subchannel_call_ref( + grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS); +void grpc_subchannel_call_unref( + grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + +grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node( + grpc_subchannel* subchannel); + +intptr_t grpc_subchannel_get_child_socket_uuid(grpc_subchannel* subchannel); + +/** Returns a pointer to the parent data associated with \a subchannel_call. + The data will be of the size specified in \a parent_data_size + field of the args passed to \a grpc_connected_subchannel_create_call(). */ +void* grpc_connected_subchannel_call_get_parent_data( + grpc_subchannel_call* subchannel_call); + +/** poll the current connectivity state of a channel */ +grpc_connectivity_state grpc_subchannel_check_connectivity( + grpc_subchannel* channel, grpc_error** error, bool inhibit_health_checking); + +/** Calls notify when the connectivity state of a channel becomes different + from *state. Updates *state with the new state of the channel. */ +void grpc_subchannel_notify_on_state_change( + grpc_subchannel* channel, grpc_pollset_set* interested_parties, + grpc_connectivity_state* state, grpc_closure* notify, + bool inhibit_health_checks); + +/** retrieve the grpc_core::ConnectedSubchannel - or nullptr if not connected + * (which may happen before it initially connects or during transient failures) + * */ +grpc_core::RefCountedPtr +grpc_subchannel_get_connected_subchannel(grpc_subchannel* c); + +// Resets the connection backoff of the subchannel. +// TODO(roth): Move connection backoff out of subchannels and up into LB +// policy code (probably by adding a SubchannelGroup between +// SubchannelList and SubchannelData), at which point this method can +// go away. +void grpc_subchannel_reset_backoff(grpc_subchannel* subchannel); + +/** continue processing a transport op */ +void grpc_subchannel_call_process_op(grpc_subchannel_call* subchannel_call, + grpc_transport_stream_op_batch* op); + +/** Must be called once per call. Sets the 'then_schedule_closure' argument for + call stack destruction. */ +void grpc_subchannel_call_set_cleanup_closure( + grpc_subchannel_call* subchannel_call, grpc_closure* closure); + +grpc_call_stack* grpc_subchannel_call_get_call_stack( + grpc_subchannel_call* subchannel_call); + +/** create a subchannel given a connector */ +grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, + const grpc_channel_args* args); + +/// Sets \a addr from \a args. +void grpc_get_subchannel_address_arg(const grpc_channel_args* args, + grpc_resolved_address* addr); + +const char* grpc_subchannel_get_target(grpc_subchannel* subchannel); + +/// Returns the URI string for the address to connect to. +const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args); + +/// Returns a new channel arg encoding the subchannel address as a string. +/// Caller is responsible for freeing the string. +grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr); + #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_H */ diff --git a/src/core/ext/filters/client_channel/subchannel_pool_interface.h b/src/core/ext/filters/client_channel/subchannel_pool_interface.h index eeb56faf0c0..21597bf4276 100644 --- a/src/core/ext/filters/client_channel/subchannel_pool_interface.h +++ b/src/core/ext/filters/client_channel/subchannel_pool_interface.h @@ -26,9 +26,9 @@ #include "src/core/lib/gprpp/abstract.h" #include "src/core/lib/gprpp/ref_counted.h" -namespace grpc_core { +struct grpc_subchannel; -class Subchannel; +namespace grpc_core { extern TraceFlag grpc_subchannel_pool_trace; @@ -69,15 +69,15 @@ class SubchannelPoolInterface : public RefCounted { // Registers a subchannel against a key. Returns the subchannel registered // with \a key, which may be different from \a constructed because we reuse // (instead of update) any existing subchannel already registered with \a key. - virtual Subchannel* RegisterSubchannel(SubchannelKey* key, - Subchannel* constructed) GRPC_ABSTRACT; + virtual grpc_subchannel* RegisterSubchannel( + SubchannelKey* key, grpc_subchannel* constructed) GRPC_ABSTRACT; // Removes the registered subchannel found by \a key. virtual void UnregisterSubchannel(SubchannelKey* key) GRPC_ABSTRACT; // Finds the subchannel registered for the given subchannel key. Returns NULL // if no such channel exists. Thread-safe. - virtual Subchannel* FindSubchannel(SubchannelKey* key) GRPC_ABSTRACT; + virtual grpc_subchannel* FindSubchannel(SubchannelKey* key) GRPC_ABSTRACT; // Creates a channel arg from \a subchannel pool. static grpc_arg CreateChannelArg(SubchannelPoolInterface* subchannel_pool); diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.cc b/src/core/ext/transport/chttp2/client/chttp2_connector.cc index 1e9a75d0630..42a2e2e896c 100644 --- a/src/core/ext/transport/chttp2/client/chttp2_connector.cc +++ b/src/core/ext/transport/chttp2/client/chttp2_connector.cc @@ -202,8 +202,7 @@ static void chttp2_connector_connect(grpc_connector* con, grpc_closure* notify) { chttp2_connector* c = reinterpret_cast(con); grpc_resolved_address addr; - grpc_core::Subchannel::GetAddressFromSubchannelAddressArg(args->channel_args, - &addr); + grpc_get_subchannel_address_arg(args->channel_args, &addr); gpr_mu_lock(&c->mu); GPR_ASSERT(c->notify == nullptr); c->notify = notify; 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 8aabcfa2000..a5bf1bf21d4 100644 --- a/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.cc @@ -39,11 +39,11 @@ static void client_channel_factory_ref( static void client_channel_factory_unref( grpc_client_channel_factory* cc_factory) {} -static grpc_core::Subchannel* client_channel_factory_create_subchannel( +static grpc_subchannel* client_channel_factory_create_subchannel( 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_core::Subchannel* s = grpc_core::Subchannel::Create(connector, new_args); + grpc_subchannel* s = grpc_subchannel_create(connector, new_args); grpc_connector_unref(connector); 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 eb2fee2af91..5985fa0cbdb 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 @@ -76,8 +76,7 @@ static grpc_channel_args* get_secure_naming_channel_args( grpc_core::UniquePtr authority; if (target_authority_table != nullptr) { // Find the authority for the target. - const char* target_uri_str = - grpc_core::Subchannel::GetUriFromSubchannelAddressArg(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); @@ -139,7 +138,7 @@ static grpc_channel_args* get_secure_naming_channel_args( return new_args; } -static grpc_core::Subchannel* client_channel_factory_create_subchannel( +static grpc_subchannel* client_channel_factory_create_subchannel( 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) { @@ -148,7 +147,7 @@ static grpc_core::Subchannel* client_channel_factory_create_subchannel( return nullptr; } grpc_connector* connector = grpc_chttp2_connector_create(); - grpc_core::Subchannel* s = grpc_core::Subchannel::Create(connector, new_args); + grpc_subchannel* s = grpc_subchannel_create(connector, new_args); grpc_connector_unref(connector); grpc_channel_args_destroy(new_args); return s; diff --git a/test/core/util/debugger_macros.cc b/test/core/util/debugger_macros.cc index fed6ad97285..05fb1461733 100644 --- a/test/core/util/debugger_macros.cc +++ b/test/core/util/debugger_macros.cc @@ -36,14 +36,13 @@ grpc_stream* grpc_transport_stream_from_call(grpc_call* call) { for (;;) { grpc_call_element* el = grpc_call_stack_element(cs, cs->count - 1); if (el->filter == &grpc_client_channel_filter) { - grpc_core::RefCountedPtr scc = - grpc_client_channel_get_subchannel_call(el); + grpc_subchannel_call* scc = grpc_client_channel_get_subchannel_call(el); if (scc == nullptr) { fprintf(stderr, "No subchannel-call"); fflush(stderr); return nullptr; } - cs = scc->GetCallStack(); + cs = grpc_subchannel_call_get_call_stack(scc); } else if (el->filter == &grpc_connected_filter) { return grpc_connected_channel_get_stream(el); } else { diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc index 973f47beaf7..125b1ce5c4e 100644 --- a/test/cpp/microbenchmarks/bm_call_create.cc +++ b/test/cpp/microbenchmarks/bm_call_create.cc @@ -325,8 +325,8 @@ class FakeClientChannelFactory : public grpc_client_channel_factory { private: static void NoRef(grpc_client_channel_factory* factory) {} static void NoUnref(grpc_client_channel_factory* factory) {} - static grpc_core::Subchannel* CreateSubchannel( - grpc_client_channel_factory* factory, const grpc_channel_args* args) { + static grpc_subchannel* CreateSubchannel(grpc_client_channel_factory* factory, + const grpc_channel_args* args) { return nullptr; } static grpc_channel* CreateClientChannel(grpc_client_channel_factory* factory, From 5a0699c705177d4a3c6a35c95a92d0be3ec378a6 Mon Sep 17 00:00:00 2001 From: jiangtaoli2016 Date: Tue, 29 Jan 2019 15:24:24 -0800 Subject: [PATCH 104/218] Allow trust anchor in gRPC ssl transport security --- src/core/tsi/ssl_transport_security.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/tsi/ssl_transport_security.cc b/src/core/tsi/ssl_transport_security.cc index fb6ea192106..b18da575382 100644 --- a/src/core/tsi/ssl_transport_security.cc +++ b/src/core/tsi/ssl_transport_security.cc @@ -651,6 +651,8 @@ static tsi_result ssl_ctx_load_verification_certs(SSL_CTX* context, STACK_OF(X509_NAME) * *root_name) { X509_STORE* cert_store = SSL_CTX_get_cert_store(context); + X509_STORE_set_flags(cert_store, + X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_TRUSTED_FIRST); return x509_store_load_certs(cert_store, pem_roots, pem_roots_size, root_name); } From ad9dcc1ff4c315b4a9d59a9a6623b6be32f10d27 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 29 Jan 2019 15:56:46 -0800 Subject: [PATCH 105/218] Update formatting --- src/compiler/csharp_generator.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index 14ee535d071..2a87463d2d0 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -609,8 +609,8 @@ void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor* service) { out->Print("\n"); } -void GenerateBindServiceWithBinderMethod( - Printer* out, const ServiceDescriptor* service) { +void GenerateBindServiceWithBinderMethod(Printer* out, + const ServiceDescriptor* service) { out->Print( "/// Register service method with a service " "binder without implementation. Useful when customizing the service " From 80b873c3be14fd304cd5d0199f26a87104588882 Mon Sep 17 00:00:00 2001 From: Alex Polcyn Date: Tue, 29 Jan 2019 22:00:26 -0800 Subject: [PATCH 106/218] Fix typo breaking mac to prod --- tools/internal_ci/macos/grpc_interop_toprod.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/internal_ci/macos/grpc_interop_toprod.sh b/tools/internal_ci/macos/grpc_interop_toprod.sh index daca88c5c51..654da373a26 100755 --- a/tools/internal_ci/macos/grpc_interop_toprod.sh +++ b/tools/internal_ci/macos/grpc_interop_toprod.sh @@ -31,7 +31,7 @@ export GRPC_DEFAULT_SSL_ROOTS_FILE_PATH="$(pwd)/etc/roots.pem" # due to different compilation flags tools/run_tests/run_interop_tests.py -l c++ \ --cloud_to_prod --cloud_to_prod_auth \ - --google_default_creds_use_key_file=true \ + --google_default_creds_use_key_file \ --prod_servers default gateway_v4 \ --service_account_key_file="${KOKORO_GFILE_DIR}/GrpcTesting-726eb1347f15.json" \ --skip_compute_engine_creds --internal_ci -t -j 4 || FAILED="true" From 9442811db260ae7f733a70dfb1ab0a2b1144cf7a Mon Sep 17 00:00:00 2001 From: Alex Polcyn Date: Tue, 29 Jan 2019 22:06:34 -0800 Subject: [PATCH 107/218] Fix spam log message --- .../security/credentials/alts/check_gcp_environment_no_op.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc b/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc index d97681b86d2..b71f66a536a 100644 --- a/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc +++ b/src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc @@ -25,8 +25,8 @@ #include bool grpc_alts_is_running_on_gcp() { - gpr_log(GPR_ERROR, - "Platforms other than Linux and Windows are not supported"); + gpr_log(GPR_INFO, + "ALTS: Platforms other than Linux and Windows are not supported"); return false; } From 8410765c0a48342287e5e2f324d17da73b9679da Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Tue, 29 Jan 2019 23:36:18 -0800 Subject: [PATCH 108/218] Eliminate an unneeded log_info --- src/core/lib/surface/server.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc index c20796f5acf..1e0ac0e9237 100644 --- a/src/core/lib/surface/server.cc +++ b/src/core/lib/surface/server.cc @@ -997,10 +997,12 @@ void grpc_server_register_completion_queue(grpc_server* server, "grpc_server_register_completion_queue(server=%p, cq=%p, reserved=%p)", 3, (server, cq, reserved)); - if (grpc_get_cq_completion_type(cq) != GRPC_CQ_NEXT) { + auto cq_type = grpc_get_cq_completion_type(cq); + if (cq_type != GRPC_CQ_NEXT && cq_type != GRPC_CQ_CALLBACK) { gpr_log(GPR_INFO, - "Completion queue which is not of type GRPC_CQ_NEXT is being " - "registered as a server-completion-queue"); + "Completion queue of type %d is being registered as a " + "server-completion-queue", + static_cast(cq_type)); /* Ideally we should log an error and abort but ruby-wrapped-language API calls grpc_completion_queue_pluck() on server completion queues */ } From 8548a932fbc82a260ba7742a8bdf48d9f6dd4be3 Mon Sep 17 00:00:00 2001 From: xichengliudui <1693291525@qq.com> Date: Wed, 30 Jan 2019 11:24:09 -0500 Subject: [PATCH 109/218] Update .cc and .md files --- src/core/ext/filters/max_age/max_age_filter.cc | 2 +- summerofcode/2018/naresh.md | 2 +- test/cpp/end2end/channelz_service_test.cc | 2 +- test/cpp/util/channel_trace_proto_helper.cc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/ext/filters/max_age/max_age_filter.cc b/src/core/ext/filters/max_age/max_age_filter.cc index 431472609eb..ec7f4e254aa 100644 --- a/src/core/ext/filters/max_age/max_age_filter.cc +++ b/src/core/ext/filters/max_age/max_age_filter.cc @@ -106,7 +106,7 @@ struct channel_data { +--------------------------------+----------------+---------+ MAX_IDLE_STATE_INIT: The initial and final state of 'idle_state'. The - channel has 1 or 1+ active calls, and the the timer is not set. Note that + channel has 1 or 1+ active calls, and the timer is not set. Note that we may put a virtual call to hold this state at channel initialization or shutdown, so that the channel won't enter other states. diff --git a/summerofcode/2018/naresh.md b/summerofcode/2018/naresh.md index 0d196bd6001..d471bff5459 100644 --- a/summerofcode/2018/naresh.md +++ b/summerofcode/2018/naresh.md @@ -128,7 +128,7 @@ bazel test --spawn_strategy=standalone --genrule_strategy=standalone //src/pytho - Use `bazel build` with a `-s` flag to see the logs being printed out to standard output while building. -- Similarly, use `bazel test` with a `--test_output=streamed` to see the the +- Similarly, use `bazel test` with a `--test_output=streamed` to see the test logs while testing. Something to know while using this flag is that all tests will be run locally, without sharding, one at a time. diff --git a/test/cpp/end2end/channelz_service_test.cc b/test/cpp/end2end/channelz_service_test.cc index 425334d972e..e7719b5c14e 100644 --- a/test/cpp/end2end/channelz_service_test.cc +++ b/test/cpp/end2end/channelz_service_test.cc @@ -708,7 +708,7 @@ TEST_F(ChannelzServerTest, GetServerSocketsPaginationTest) { get_server_sockets_request, &get_server_sockets_response); EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); - // We add one to account the the channelz stub that will end up creating + // We add one to account the channelz stub that will end up creating // a serversocket. EXPECT_EQ(get_server_sockets_response.socket_ref_size(), kNumServerSocketsCreated + 1); diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc index ff9d8873858..2499edf6540 100644 --- a/test/cpp/util/channel_trace_proto_helper.cc +++ b/test/cpp/util/channel_trace_proto_helper.cc @@ -56,7 +56,7 @@ void VaidateProtoJsonTranslation(char* json_c_str) { EXPECT_EQ(google::protobuf::util::MessageToJsonString(msg, &proto_json_str, print_options), google::protobuf::util::Status::OK); - // uncomment these to compare the the json strings. + // uncomment these to compare the json strings. // gpr_log(GPR_ERROR, "tracer json: %s", json_str.c_str()); // gpr_log(GPR_ERROR, "proto json: %s", proto_json_str.c_str()); EXPECT_EQ(json_str, proto_json_str); From 8e085233ed82d3966ed5d284fb289bc43674be8d Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 28 Jan 2019 17:59:32 -0800 Subject: [PATCH 110/218] Fix CFStream test --- .../xcshareddata/xcschemes/CFStreamTests.xcscheme | 7 +++++++ .../xcshareddata/xcschemes/CFStreamTests_Asan.xcscheme | 9 +++++++-- .../xcshareddata/xcschemes/CFStreamTests_Msan.xcscheme | 9 +++++++-- .../xcshareddata/xcschemes/CFStreamTests_Tsan.xcscheme | 9 +++++++-- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests.xcscheme b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests.xcscheme index 25d6f780a1e..e4b4ce89e27 100644 --- a/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests.xcscheme +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests.xcscheme @@ -36,6 +36,13 @@ debugDocumentVersioning = "YES" debugServiceExtension = "internal" allowLocationSimulation = "YES"> + + + + diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Asan.xcscheme b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Asan.xcscheme index 6c5c43aa721..d29ed5cb548 100644 --- a/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Asan.xcscheme +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Asan.xcscheme @@ -12,7 +12,6 @@ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" enableAddressSanitizer = "YES" enableASanStackUseAfterReturn = "YES" - language = "" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Msan.xcscheme b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Msan.xcscheme index 3e39ff84d06..ab9b9be5917 100644 --- a/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Msan.xcscheme +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Msan.xcscheme @@ -10,7 +10,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Tsan.xcscheme b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Tsan.xcscheme index f0bde837c5b..bad1ceab715 100644 --- a/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Tsan.xcscheme +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamTests.xcodeproj/xcshareddata/xcschemes/CFStreamTests_Tsan.xcscheme @@ -11,7 +11,6 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" enableThreadSanitizer = "YES" - language = "" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + From 4f3c1572e120b856cff028a5ed1247bf7f5a99ba Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Wed, 30 Jan 2019 10:23:07 -0800 Subject: [PATCH 111/218] Revert "Revert "C++-ify subchannel"" --- .../filters/client_channel/client_channel.cc | 114 +- .../filters/client_channel/client_channel.h | 4 +- .../client_channel/client_channel_channelz.cc | 11 +- .../client_channel/client_channel_channelz.h | 9 +- .../client_channel/client_channel_factory.cc | 2 +- .../client_channel/client_channel_factory.h | 6 +- .../client_channel/global_subchannel_pool.cc | 19 +- .../client_channel/global_subchannel_pool.h | 6 +- .../health/health_check_client.cc | 18 +- .../health/health_check_client.h | 2 +- .../lb_policy/pick_first/pick_first.cc | 2 +- .../lb_policy/round_robin/round_robin.cc | 2 +- .../lb_policy/subchannel_list.h | 37 +- .../client_channel/local_subchannel_pool.cc | 14 +- .../client_channel/local_subchannel_pool.h | 6 +- .../ext/filters/client_channel/subchannel.cc | 1436 ++++++++--------- .../ext/filters/client_channel/subchannel.h | 331 ++-- .../subchannel_pool_interface.h | 10 +- .../chttp2/client/chttp2_connector.cc | 3 +- .../chttp2/client/insecure/channel_create.cc | 4 +- .../client/secure/secure_channel_create.cc | 7 +- test/core/util/debugger_macros.cc | 5 +- test/cpp/microbenchmarks/bm_call_create.cc | 4 +- 23 files changed, 1025 insertions(+), 1027 deletions(-) diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 35c3efab6aa..38525dbf97e 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -394,7 +394,7 @@ struct subchannel_batch_data { gpr_refcount refs; grpc_call_element* elem; - grpc_subchannel_call* subchannel_call; // Holds a ref. + grpc_core::RefCountedPtr subchannel_call; // The batch to use in the subchannel call. // Its payload field points to subchannel_call_retry_state.batch_payload. grpc_transport_stream_op_batch batch; @@ -478,7 +478,7 @@ struct pending_batch { bool send_ops_cached; }; -/** Call data. Holds a pointer to grpc_subchannel_call and the +/** Call data. Holds a pointer to SubchannelCall and the associated machinery to create such a pointer. Handles queueing of stream ops until a call object is ready, waiting for initial metadata before trying to create a call object, @@ -504,10 +504,6 @@ struct call_data { last_attempt_got_server_pushback(false) {} ~call_data() { - if (GPR_LIKELY(subchannel_call != nullptr)) { - GRPC_SUBCHANNEL_CALL_UNREF(subchannel_call, - "client_channel_destroy_call"); - } grpc_slice_unref_internal(path); GRPC_ERROR_UNREF(cancel_error); for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches); ++i) { @@ -536,7 +532,7 @@ struct call_data { grpc_core::RefCountedPtr retry_throttle_data; grpc_core::RefCountedPtr method_params; - grpc_subchannel_call* subchannel_call = nullptr; + grpc_core::RefCountedPtr subchannel_call; // Set when we get a cancel_stream op. grpc_error* cancel_error = GRPC_ERROR_NONE; @@ -807,8 +803,8 @@ static void pending_batches_add(grpc_call_element* elem, calld->subchannel_call == nullptr ? nullptr : static_cast( - grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)); + + calld->subchannel_call->GetParentData()); retry_commit(elem, retry_state); // If we are not going to retry and have not yet started, pretend // retries are disabled so that we don't bother with retry overhead. @@ -896,10 +892,10 @@ static void resume_pending_batch_in_call_combiner(void* arg, grpc_error* ignored) { grpc_transport_stream_op_batch* batch = static_cast(arg); - grpc_subchannel_call* subchannel_call = - static_cast(batch->handler_private.extra_arg); + grpc_core::SubchannelCall* subchannel_call = + static_cast(batch->handler_private.extra_arg); // Note: This will release the call combiner. - grpc_subchannel_call_process_op(subchannel_call, batch); + subchannel_call->StartTransportStreamOpBatch(batch); } // This is called via the call combiner, so access to calld is synchronized. @@ -919,7 +915,7 @@ static void pending_batches_resume(grpc_call_element* elem) { gpr_log(GPR_INFO, "chand=%p calld=%p: starting %" PRIuPTR " pending batches on subchannel_call=%p", - chand, calld, num_batches, calld->subchannel_call); + chand, calld, num_batches, calld->subchannel_call.get()); } grpc_core::CallCombinerClosureList closures; for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) { @@ -930,7 +926,7 @@ static void pending_batches_resume(grpc_call_element* elem) { maybe_inject_recv_trailing_metadata_ready_for_lb( *calld->request->pick(), batch); } - batch->handler_private.extra_arg = calld->subchannel_call; + batch->handler_private.extra_arg = calld->subchannel_call.get(); GRPC_CLOSURE_INIT(&batch->handler_private.closure, resume_pending_batch_in_call_combiner, batch, grpc_schedule_on_exec_ctx); @@ -1019,12 +1015,7 @@ static void do_retry(grpc_call_element* elem, const ClientChannelMethodParams::RetryPolicy* retry_policy = calld->method_params->retry_policy(); GPR_ASSERT(retry_policy != nullptr); - // Reset subchannel call and connected subchannel. - if (calld->subchannel_call != nullptr) { - GRPC_SUBCHANNEL_CALL_UNREF(calld->subchannel_call, - "client_channel_call_retry"); - calld->subchannel_call = nullptr; - } + calld->subchannel_call.reset(); if (calld->have_request) { calld->have_request = false; calld->request.Destroy(); @@ -1078,8 +1069,7 @@ static bool maybe_retry(grpc_call_element* elem, subchannel_call_retry_state* retry_state = nullptr; if (batch_data != nullptr) { retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); if (retry_state->retry_dispatched) { if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: retry already dispatched", chand, @@ -1180,13 +1170,10 @@ namespace { subchannel_batch_data::subchannel_batch_data(grpc_call_element* elem, call_data* calld, int refcount, bool set_on_complete) - : elem(elem), - subchannel_call(GRPC_SUBCHANNEL_CALL_REF(calld->subchannel_call, - "batch_data_create")) { + : elem(elem), subchannel_call(calld->subchannel_call) { subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)); + calld->subchannel_call->GetParentData()); batch.payload = &retry_state->batch_payload; gpr_ref_init(&refs, refcount); if (set_on_complete) { @@ -1200,7 +1187,7 @@ subchannel_batch_data::subchannel_batch_data(grpc_call_element* elem, void subchannel_batch_data::destroy() { subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data(subchannel_call)); + subchannel_call->GetParentData()); if (batch.send_initial_metadata) { grpc_metadata_batch_destroy(&retry_state->send_initial_metadata); } @@ -1213,7 +1200,7 @@ void subchannel_batch_data::destroy() { if (batch.recv_trailing_metadata) { grpc_metadata_batch_destroy(&retry_state->recv_trailing_metadata); } - GRPC_SUBCHANNEL_CALL_UNREF(subchannel_call, "batch_data_unref"); + subchannel_call.reset(); call_data* calld = static_cast(elem->call_data); GRPC_CALL_STACK_UNREF(calld->owning_call, "batch_data"); } @@ -1260,8 +1247,7 @@ static void invoke_recv_initial_metadata_callback(void* arg, // Return metadata. subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); grpc_metadata_batch_move( &retry_state->recv_initial_metadata, pending->batch->payload->recv_initial_metadata.recv_initial_metadata); @@ -1293,8 +1279,7 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); retry_state->completed_recv_initial_metadata = true; // If a retry was already dispatched, then we're not going to use the // result of this recv_initial_metadata op, so do nothing. @@ -1355,8 +1340,7 @@ static void invoke_recv_message_callback(void* arg, grpc_error* error) { // Return payload. subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); *pending->batch->payload->recv_message.recv_message = std::move(retry_state->recv_message); // Update bookkeeping. @@ -1384,8 +1368,7 @@ static void recv_message_ready(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); ++retry_state->completed_recv_message_count; // If a retry was already dispatched, then we're not going to use the // result of this recv_message op, so do nothing. @@ -1473,8 +1456,7 @@ static void add_closure_for_recv_trailing_metadata_ready( // Return metadata. subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); grpc_metadata_batch_move( &retry_state->recv_trailing_metadata, pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata); @@ -1576,8 +1558,7 @@ static void run_closures_for_completed_call(subchannel_batch_data* batch_data, call_data* calld = static_cast(elem->call_data); subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); // Construct list of closures to execute. grpc_core::CallCombinerClosureList closures; // First, add closure for recv_trailing_metadata_ready. @@ -1611,8 +1592,7 @@ static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); retry_state->completed_recv_trailing_metadata = true; // Get the call's status and check for server pushback metadata. grpc_status_code status = GRPC_STATUS_OK; @@ -1735,8 +1715,7 @@ static void on_complete(void* arg, grpc_error* error) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - batch_data->subchannel_call)); + batch_data->subchannel_call->GetParentData()); // Update bookkeeping in retry_state. if (batch_data->batch.send_initial_metadata) { retry_state->completed_send_initial_metadata = true; @@ -1792,10 +1771,10 @@ static void on_complete(void* arg, grpc_error* error) { static void start_batch_in_call_combiner(void* arg, grpc_error* ignored) { grpc_transport_stream_op_batch* batch = static_cast(arg); - grpc_subchannel_call* subchannel_call = - static_cast(batch->handler_private.extra_arg); + grpc_core::SubchannelCall* subchannel_call = + static_cast(batch->handler_private.extra_arg); // Note: This will release the call combiner. - grpc_subchannel_call_process_op(subchannel_call, batch); + subchannel_call->StartTransportStreamOpBatch(batch); } // Adds a closure to closures that will execute batch in the call combiner. @@ -1804,7 +1783,7 @@ static void add_closure_for_subchannel_batch( grpc_core::CallCombinerClosureList* closures) { channel_data* chand = static_cast(elem->channel_data); call_data* calld = static_cast(elem->call_data); - batch->handler_private.extra_arg = calld->subchannel_call; + batch->handler_private.extra_arg = calld->subchannel_call.get(); GRPC_CLOSURE_INIT(&batch->handler_private.closure, start_batch_in_call_combiner, batch, grpc_schedule_on_exec_ctx); @@ -1978,8 +1957,7 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)); + calld->subchannel_call->GetParentData()); // Create batch_data with 2 refs, since this batch will be unreffed twice: // once for the recv_trailing_metadata_ready callback when the subchannel // batch returns, and again when we actually get a recv_trailing_metadata @@ -1989,7 +1967,7 @@ static void start_internal_recv_trailing_metadata(grpc_call_element* elem) { add_retriable_recv_trailing_metadata_op(calld, retry_state, batch_data); retry_state->recv_trailing_metadata_internal_batch = batch_data; // Note: This will release the call combiner. - grpc_subchannel_call_process_op(calld->subchannel_call, &batch_data->batch); + calld->subchannel_call->StartTransportStreamOpBatch(&batch_data->batch); } // If there are any cached send ops that need to be replayed on the @@ -2196,8 +2174,7 @@ static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored) { } subchannel_call_retry_state* retry_state = static_cast( - grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)); + calld->subchannel_call->GetParentData()); // Construct list of closures to execute, one for each pending batch. grpc_core::CallCombinerClosureList closures; // Replay previously-returned send_* ops if needed. @@ -2220,7 +2197,7 @@ static void start_retriable_subchannel_batches(void* arg, grpc_error* ignored) { gpr_log(GPR_INFO, "chand=%p calld=%p: starting %" PRIuPTR " retriable batches on subchannel_call=%p", - chand, calld, closures.size(), calld->subchannel_call); + chand, calld, closures.size(), calld->subchannel_call.get()); } // Note: This will yield the call combiner. closures.RunClosures(calld->call_combiner); @@ -2245,22 +2222,22 @@ static void create_subchannel_call(grpc_call_element* elem, grpc_error* error) { calld->call_combiner, // call_combiner parent_data_size // parent_data_size }; - grpc_error* new_error = - calld->request->pick()->connected_subchannel->CreateCall( - call_args, &calld->subchannel_call); + grpc_error* new_error = GRPC_ERROR_NONE; + calld->subchannel_call = + calld->request->pick()->connected_subchannel->CreateCall(call_args, + &new_error); if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: create subchannel_call=%p: error=%s", - chand, calld, calld->subchannel_call, grpc_error_string(new_error)); + chand, calld, calld->subchannel_call.get(), + grpc_error_string(new_error)); } if (GPR_UNLIKELY(new_error != GRPC_ERROR_NONE)) { new_error = grpc_error_add_child(new_error, error); pending_batches_fail(elem, new_error, true /* yield_call_combiner */); } else { if (parent_data_size > 0) { - new (grpc_connected_subchannel_call_get_parent_data( - calld->subchannel_call)) - subchannel_call_retry_state( - calld->request->pick()->subchannel_call_context); + new (calld->subchannel_call->GetParentData()) subchannel_call_retry_state( + calld->request->pick()->subchannel_call_context); } pending_batches_resume(elem); } @@ -2488,7 +2465,7 @@ static void cc_start_transport_stream_op_batch( batch, GRPC_ERROR_REF(calld->cancel_error), calld->call_combiner); } else { // Note: This will release the call combiner. - grpc_subchannel_call_process_op(calld->subchannel_call, batch); + calld->subchannel_call->StartTransportStreamOpBatch(batch); } return; } @@ -2502,7 +2479,7 @@ static void cc_start_transport_stream_op_batch( if (grpc_client_channel_trace.enabled()) { gpr_log(GPR_INFO, "chand=%p calld=%p: starting batch on subchannel_call=%p", chand, - calld, calld->subchannel_call); + calld, calld->subchannel_call.get()); } pending_batches_resume(elem); return; @@ -2545,8 +2522,7 @@ static void cc_destroy_call_elem(grpc_call_element* elem, grpc_closure* then_schedule_closure) { call_data* calld = static_cast(elem->call_data); if (GPR_LIKELY(calld->subchannel_call != nullptr)) { - grpc_subchannel_call_set_cleanup_closure(calld->subchannel_call, - then_schedule_closure); + calld->subchannel_call->SetAfterCallStackDestroy(then_schedule_closure); then_schedule_closure = nullptr; } calld->~call_data(); @@ -2752,8 +2728,8 @@ void grpc_client_channel_watch_connectivity_state( GRPC_ERROR_NONE); } -grpc_subchannel_call* grpc_client_channel_get_subchannel_call( - grpc_call_element* elem) { +grpc_core::RefCountedPtr +grpc_client_channel_get_subchannel_call(grpc_call_element* elem) { call_data* calld = static_cast(elem->call_data); return calld->subchannel_call; } diff --git a/src/core/ext/filters/client_channel/client_channel.h b/src/core/ext/filters/client_channel/client_channel.h index 4935fd24d87..5bfff4df9cd 100644 --- a/src/core/ext/filters/client_channel/client_channel.h +++ b/src/core/ext/filters/client_channel/client_channel.h @@ -60,7 +60,7 @@ void grpc_client_channel_watch_connectivity_state( grpc_closure* watcher_timer_init); /* Debug helper: pull the subchannel call from a call stack element */ -grpc_subchannel_call* grpc_client_channel_get_subchannel_call( - grpc_call_element* elem); +grpc_core::RefCountedPtr +grpc_client_channel_get_subchannel_call(grpc_call_element* elem); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H */ diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 8e5426081c4..76c5a786240 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -113,12 +113,11 @@ RefCountedPtr ClientChannelNode::MakeClientChannelNode( is_top_level_channel); } -SubchannelNode::SubchannelNode(grpc_subchannel* subchannel, +SubchannelNode::SubchannelNode(Subchannel* subchannel, size_t channel_tracer_max_nodes) : BaseNode(EntityType::kSubchannel), subchannel_(subchannel), - target_( - UniquePtr(gpr_strdup(grpc_subchannel_get_target(subchannel_)))), + target_(UniquePtr(gpr_strdup(subchannel_->GetTargetAddress()))), trace_(channel_tracer_max_nodes) {} SubchannelNode::~SubchannelNode() {} @@ -128,8 +127,8 @@ void SubchannelNode::PopulateConnectivityState(grpc_json* json) { if (subchannel_ == nullptr) { state = GRPC_CHANNEL_SHUTDOWN; } else { - state = grpc_subchannel_check_connectivity( - subchannel_, nullptr, true /* inhibit_health_checking */); + state = subchannel_->CheckConnectivity(nullptr, + true /* inhibit_health_checking */); } json = grpc_json_create_child(nullptr, json, "state", nullptr, GRPC_JSON_OBJECT, false); @@ -170,7 +169,7 @@ grpc_json* SubchannelNode::RenderJson() { call_counter_.PopulateCallCounts(json); json = top_level_json; // populate the child socket. - intptr_t socket_uuid = grpc_subchannel_get_child_socket_uuid(subchannel_); + intptr_t socket_uuid = subchannel_->GetChildSocketUuid(); if (socket_uuid != 0) { grpc_json* array_parent = grpc_json_create_child( nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index 8a5c3e7e5e5..1dc1bf595be 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -26,9 +26,10 @@ #include "src/core/lib/channel/channel_trace.h" #include "src/core/lib/channel/channelz.h" -typedef struct grpc_subchannel grpc_subchannel; - namespace grpc_core { + +class Subchannel; + namespace channelz { // Subtype of ChannelNode that overrides and provides client_channel specific @@ -59,7 +60,7 @@ class ClientChannelNode : public ChannelNode { // Handles channelz bookkeeping for sockets class SubchannelNode : public BaseNode { public: - SubchannelNode(grpc_subchannel* subchannel, size_t channel_tracer_max_nodes); + SubchannelNode(Subchannel* subchannel, size_t channel_tracer_max_nodes); ~SubchannelNode() override; void MarkSubchannelDestroyed() { @@ -84,7 +85,7 @@ class SubchannelNode : public BaseNode { void RecordCallSucceeded() { call_counter_.RecordCallSucceeded(); } private: - grpc_subchannel* subchannel_; + Subchannel* subchannel_; UniquePtr target_; CallCountingHelper call_counter_; ChannelTrace trace_; 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 130bbe04180..8c558382fdf 100644 --- a/src/core/ext/filters/client_channel/client_channel_factory.cc +++ b/src/core/ext/filters/client_channel/client_channel_factory.cc @@ -29,7 +29,7 @@ void grpc_client_channel_factory_unref(grpc_client_channel_factory* factory) { factory->vtable->unref(factory); } -grpc_subchannel* grpc_client_channel_factory_create_subchannel( +grpc_core::Subchannel* grpc_client_channel_factory_create_subchannel( 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 91dec12282f..4b72aa46499 100644 --- a/src/core/ext/filters/client_channel/client_channel_factory.h +++ b/src/core/ext/filters/client_channel/client_channel_factory.h @@ -48,8 +48,8 @@ struct grpc_client_channel_factory { 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_channel_args* args); + grpc_core::Subchannel* (*create_subchannel)( + grpc_client_channel_factory* factory, const grpc_channel_args* args); grpc_channel* (*create_client_channel)(grpc_client_channel_factory* factory, const char* target, grpc_client_channel_type type, @@ -60,7 +60,7 @@ void grpc_client_channel_factory_ref(grpc_client_channel_factory* factory); 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_core::Subchannel* grpc_client_channel_factory_create_subchannel( grpc_client_channel_factory* factory, const grpc_channel_args* args); /** Create a new grpc_channel */ diff --git a/src/core/ext/filters/client_channel/global_subchannel_pool.cc b/src/core/ext/filters/client_channel/global_subchannel_pool.cc index a41d993fe66..ee6e58159a0 100644 --- a/src/core/ext/filters/client_channel/global_subchannel_pool.cc +++ b/src/core/ext/filters/client_channel/global_subchannel_pool.cc @@ -54,9 +54,9 @@ RefCountedPtr GlobalSubchannelPool::instance() { return *instance_; } -grpc_subchannel* GlobalSubchannelPool::RegisterSubchannel( - SubchannelKey* key, grpc_subchannel* constructed) { - grpc_subchannel* c = nullptr; +Subchannel* GlobalSubchannelPool::RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) { + Subchannel* c = nullptr; // Compare and swap (CAS) loop: while (c == nullptr) { // Ref the shared map to have a local copy. @@ -64,7 +64,7 @@ grpc_subchannel* GlobalSubchannelPool::RegisterSubchannel( grpc_avl old_map = grpc_avl_ref(subchannel_map_, nullptr); gpr_mu_unlock(&mu_); // Check to see if a subchannel already exists. - c = static_cast(grpc_avl_get(old_map, key, nullptr)); + c = static_cast(grpc_avl_get(old_map, key, nullptr)); if (c != nullptr) { // The subchannel already exists. Reuse it. c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "subchannel_register+reuse"); @@ -121,15 +121,14 @@ void GlobalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) { } } -grpc_subchannel* GlobalSubchannelPool::FindSubchannel(SubchannelKey* key) { +Subchannel* GlobalSubchannelPool::FindSubchannel(SubchannelKey* key) { // Lock, and take a reference to the subchannel map. // We don't need to do the search under a lock as AVL's are immutable. gpr_mu_lock(&mu_); grpc_avl index = grpc_avl_ref(subchannel_map_, nullptr); gpr_mu_unlock(&mu_); - grpc_subchannel* c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF( - static_cast(grpc_avl_get(index, key, nullptr)), - "found_from_pool"); + Subchannel* c = static_cast(grpc_avl_get(index, key, nullptr)); + if (c != nullptr) GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "found_from_pool"); grpc_avl_unref(index, nullptr); return c; } @@ -156,11 +155,11 @@ long sck_avl_compare(void* a, void* b, void* unused) { } void scv_avl_destroy(void* p, void* user_data) { - GRPC_SUBCHANNEL_WEAK_UNREF((grpc_subchannel*)p, "global_subchannel_pool"); + GRPC_SUBCHANNEL_WEAK_UNREF((Subchannel*)p, "global_subchannel_pool"); } void* scv_avl_copy(void* p, void* unused) { - GRPC_SUBCHANNEL_WEAK_REF((grpc_subchannel*)p, "global_subchannel_pool"); + GRPC_SUBCHANNEL_WEAK_REF((Subchannel*)p, "global_subchannel_pool"); return p; } diff --git a/src/core/ext/filters/client_channel/global_subchannel_pool.h b/src/core/ext/filters/client_channel/global_subchannel_pool.h index 0deb3769360..96dc8d7b3a4 100644 --- a/src/core/ext/filters/client_channel/global_subchannel_pool.h +++ b/src/core/ext/filters/client_channel/global_subchannel_pool.h @@ -45,10 +45,10 @@ class GlobalSubchannelPool final : public SubchannelPoolInterface { static RefCountedPtr instance(); // Implements interface methods. - grpc_subchannel* RegisterSubchannel(SubchannelKey* key, - grpc_subchannel* constructed) override; + Subchannel* RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) override; void UnregisterSubchannel(SubchannelKey* key) override; - grpc_subchannel* FindSubchannel(SubchannelKey* key) override; + Subchannel* FindSubchannel(SubchannelKey* key) override; private: // The singleton instance. (It's a pointer to RefCountedPtr so that this diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc index 2232c57120e..e845d63d295 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -295,7 +295,9 @@ HealthCheckClient::CallState::~CallState() { gpr_log(GPR_INFO, "HealthCheckClient %p: destroying CallState %p", health_check_client_.get(), this); } - if (call_ != nullptr) GRPC_SUBCHANNEL_CALL_UNREF(call_, "call_ended"); + // The subchannel call is in the arena, so reset the pointer before we destroy + // the arena. + call_.reset(); for (size_t i = 0; i < GRPC_CONTEXT_COUNT; i++) { if (context_[i].destroy != nullptr) { context_[i].destroy(context_[i].value); @@ -329,8 +331,8 @@ void HealthCheckClient::CallState::StartCall() { &call_combiner_, 0, // parent_data_size }; - grpc_error* error = - health_check_client_->connected_subchannel_->CreateCall(args, &call_); + grpc_error* error = GRPC_ERROR_NONE; + call_ = health_check_client_->connected_subchannel_->CreateCall(args, &error); if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "HealthCheckClient %p CallState %p: error creating health " @@ -423,14 +425,14 @@ void HealthCheckClient::CallState::StartBatchInCallCombiner(void* arg, grpc_error* error) { grpc_transport_stream_op_batch* batch = static_cast(arg); - grpc_subchannel_call* call = - static_cast(batch->handler_private.extra_arg); - grpc_subchannel_call_process_op(call, batch); + SubchannelCall* call = + static_cast(batch->handler_private.extra_arg); + call->StartTransportStreamOpBatch(batch); } void HealthCheckClient::CallState::StartBatch( grpc_transport_stream_op_batch* batch) { - batch->handler_private.extra_arg = call_; + batch->handler_private.extra_arg = call_.get(); GRPC_CLOSURE_INIT(&batch->handler_private.closure, StartBatchInCallCombiner, batch, grpc_schedule_on_exec_ctx); GRPC_CALL_COMBINER_START(&call_combiner_, &batch->handler_private.closure, @@ -452,7 +454,7 @@ void HealthCheckClient::CallState::StartCancel(void* arg, grpc_error* error) { GRPC_CLOSURE_CREATE(OnCancelComplete, self, grpc_schedule_on_exec_ctx)); batch->cancel_stream = true; batch->payload->cancel_stream.cancel_error = GRPC_ERROR_CANCELLED; - grpc_subchannel_call_process_op(self->call_, batch); + self->call_->StartTransportStreamOpBatch(batch); } void HealthCheckClient::CallState::Cancel() { diff --git a/src/core/ext/filters/client_channel/health/health_check_client.h b/src/core/ext/filters/client_channel/health/health_check_client.h index 2369b73feac..7af88a54cfc 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.h +++ b/src/core/ext/filters/client_channel/health/health_check_client.h @@ -99,7 +99,7 @@ class HealthCheckClient : public InternallyRefCounted { grpc_call_context_element context_[GRPC_CONTEXT_COUNT] = {}; // The streaming call to the backend. Always non-NULL. - grpc_subchannel_call* call_; + RefCountedPtr call_; grpc_transport_stream_op_batch_payload payload_; grpc_transport_stream_op_batch batch_; diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index ec5c782c469..dc716a6adac 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -79,7 +79,7 @@ class PickFirst : public LoadBalancingPolicy { PickFirstSubchannelData( SubchannelList* subchannel_list, - const ServerAddress& address, grpc_subchannel* subchannel, + const ServerAddress& address, Subchannel* subchannel, grpc_combiner* combiner) : SubchannelData(subchannel_list, address, subchannel, combiner) {} diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index 30316689ea7..aab6dd68216 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -94,7 +94,7 @@ class RoundRobin : public LoadBalancingPolicy { RoundRobinSubchannelData( SubchannelList* subchannel_list, - const ServerAddress& address, grpc_subchannel* subchannel, + const ServerAddress& address, Subchannel* subchannel, grpc_combiner* combiner) : SubchannelData(subchannel_list, address, subchannel, combiner) {} 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 2eb92b7ead0..0174a98a73d 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 @@ -88,7 +88,7 @@ class SubchannelData { } // Returns a pointer to the subchannel. - grpc_subchannel* subchannel() const { return subchannel_; } + Subchannel* subchannel() const { return subchannel_; } // Returns the connected subchannel. Will be null if the subchannel // is not connected. @@ -103,8 +103,8 @@ class SubchannelData { // ProcessConnectivityChangeLocked()). grpc_connectivity_state CheckConnectivityStateLocked(grpc_error** error) { GPR_ASSERT(!connectivity_notification_pending_); - pending_connectivity_state_unsafe_ = grpc_subchannel_check_connectivity( - subchannel(), error, subchannel_list_->inhibit_health_checking()); + pending_connectivity_state_unsafe_ = subchannel()->CheckConnectivity( + error, subchannel_list_->inhibit_health_checking()); UpdateConnectedSubchannelLocked(); return pending_connectivity_state_unsafe_; } @@ -142,7 +142,7 @@ class SubchannelData { protected: SubchannelData( SubchannelList* subchannel_list, - const ServerAddress& address, grpc_subchannel* subchannel, + const ServerAddress& address, Subchannel* subchannel, grpc_combiner* combiner); virtual ~SubchannelData(); @@ -170,7 +170,7 @@ class SubchannelData { SubchannelList* subchannel_list_; // The subchannel and connected subchannel. - grpc_subchannel* subchannel_; + Subchannel* subchannel_; RefCountedPtr connected_subchannel_; // Notification that connectivity has changed on subchannel. @@ -203,7 +203,7 @@ class SubchannelList : public InternallyRefCounted { for (size_t i = 0; i < subchannels_.size(); ++i) { if (subchannels_[i].subchannel() != nullptr) { grpc_core::channelz::SubchannelNode* subchannel_node = - grpc_subchannel_get_channelz_node(subchannels_[i].subchannel()); + subchannels_[i].subchannel()->channelz_node(); if (subchannel_node != nullptr) { refs_list->push_back(subchannel_node->uuid()); } @@ -276,7 +276,7 @@ class SubchannelList : public InternallyRefCounted { template SubchannelData::SubchannelData( SubchannelList* subchannel_list, - const ServerAddress& address, grpc_subchannel* subchannel, + const ServerAddress& address, Subchannel* subchannel, grpc_combiner* combiner) : subchannel_list_(subchannel_list), subchannel_(subchannel), @@ -317,7 +317,7 @@ template void SubchannelData::ResetBackoffLocked() { if (subchannel_ != nullptr) { - grpc_subchannel_reset_backoff(subchannel_); + subchannel_->ResetBackoff(); } } @@ -337,8 +337,8 @@ void SubchannelDataRef(DEBUG_LOCATION, "connectivity_watch").release(); - grpc_subchannel_notify_on_state_change( - subchannel_, subchannel_list_->policy()->interested_parties(), + subchannel_->NotifyOnStateChange( + subchannel_list_->policy()->interested_parties(), &pending_connectivity_state_unsafe_, &connectivity_changed_closure_, subchannel_list_->inhibit_health_checking()); } @@ -357,8 +357,8 @@ void SubchannelDatapolicy()->interested_parties(), + subchannel_->NotifyOnStateChange( + subchannel_list_->policy()->interested_parties(), &pending_connectivity_state_unsafe_, &connectivity_changed_closure_, subchannel_list_->inhibit_health_checking()); } @@ -391,9 +391,9 @@ void SubchannelData:: subchannel_, reason); } GPR_ASSERT(connectivity_notification_pending_); - grpc_subchannel_notify_on_state_change( - subchannel_, nullptr, nullptr, &connectivity_changed_closure_, - subchannel_list_->inhibit_health_checking()); + subchannel_->NotifyOnStateChange(nullptr, nullptr, + &connectivity_changed_closure_, + subchannel_list_->inhibit_health_checking()); } template @@ -401,8 +401,7 @@ bool SubchannelData::UpdateConnectedSubchannelLocked() { // If the subchannel is READY, take a ref to the connected subchannel. if (pending_connectivity_state_unsafe_ == GRPC_CHANNEL_READY) { - connected_subchannel_ = - grpc_subchannel_get_connected_subchannel(subchannel_); + connected_subchannel_ = subchannel_->connected_subchannel(); // If the subchannel became disconnected between the time that READY // was reported and the time we got here (e.g., between when a // notification callback is scheduled and when it was actually run in @@ -518,7 +517,7 @@ SubchannelList::SubchannelList( SubchannelPoolInterface::CreateChannelArg(policy_->subchannel_pool())); const size_t subchannel_address_arg_index = args_to_add.size(); args_to_add.emplace_back( - grpc_create_subchannel_address_arg(&addresses[i].address())); + Subchannel::CreateSubchannelAddressArg(&addresses[i].address())); if (addresses[i].args() != nullptr) { for (size_t j = 0; j < addresses[i].args()->num_args; ++j) { args_to_add.emplace_back(addresses[i].args()->args[j]); @@ -528,7 +527,7 @@ 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[subchannel_address_arg_index].value.string); - grpc_subchannel* subchannel = grpc_client_channel_factory_create_subchannel( + Subchannel* subchannel = grpc_client_channel_factory_create_subchannel( client_channel_factory, new_args); grpc_channel_args_destroy(new_args); if (subchannel == nullptr) { diff --git a/src/core/ext/filters/client_channel/local_subchannel_pool.cc b/src/core/ext/filters/client_channel/local_subchannel_pool.cc index 145fa4e0374..d1c1cacb441 100644 --- a/src/core/ext/filters/client_channel/local_subchannel_pool.cc +++ b/src/core/ext/filters/client_channel/local_subchannel_pool.cc @@ -32,11 +32,11 @@ LocalSubchannelPool::~LocalSubchannelPool() { grpc_avl_unref(subchannel_map_, nullptr); } -grpc_subchannel* LocalSubchannelPool::RegisterSubchannel( - SubchannelKey* key, grpc_subchannel* constructed) { +Subchannel* LocalSubchannelPool::RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) { // Check to see if a subchannel already exists. - grpc_subchannel* c = static_cast( - grpc_avl_get(subchannel_map_, key, nullptr)); + Subchannel* c = + static_cast(grpc_avl_get(subchannel_map_, key, nullptr)); if (c != nullptr) { // The subchannel already exists. Reuse it. c = GRPC_SUBCHANNEL_REF(c, "subchannel_register+reuse"); @@ -54,9 +54,9 @@ void LocalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) { subchannel_map_ = grpc_avl_remove(subchannel_map_, key, nullptr); } -grpc_subchannel* LocalSubchannelPool::FindSubchannel(SubchannelKey* key) { - grpc_subchannel* c = static_cast( - grpc_avl_get(subchannel_map_, key, nullptr)); +Subchannel* LocalSubchannelPool::FindSubchannel(SubchannelKey* key) { + Subchannel* c = + static_cast(grpc_avl_get(subchannel_map_, key, nullptr)); return c == nullptr ? c : GRPC_SUBCHANNEL_REF(c, "found_from_pool"); } diff --git a/src/core/ext/filters/client_channel/local_subchannel_pool.h b/src/core/ext/filters/client_channel/local_subchannel_pool.h index 9929cdb3627..a6b7e259fbb 100644 --- a/src/core/ext/filters/client_channel/local_subchannel_pool.h +++ b/src/core/ext/filters/client_channel/local_subchannel_pool.h @@ -39,10 +39,10 @@ class LocalSubchannelPool final : public SubchannelPoolInterface { // Implements interface methods. // Thread-unsafe. Intended to be invoked within the client_channel combiner. - grpc_subchannel* RegisterSubchannel(SubchannelKey* key, - grpc_subchannel* constructed) override; + Subchannel* RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) override; void UnregisterSubchannel(SubchannelKey* key) override; - grpc_subchannel* FindSubchannel(SubchannelKey* key) override; + Subchannel* FindSubchannel(SubchannelKey* key) override; private: // The vtable for subchannel operations in an AVL tree. diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index d77bb3c286b..70285659aad 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -44,7 +44,6 @@ #include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" -#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/channel.h" @@ -55,153 +54,256 @@ #include "src/core/lib/transport/status_metadata.h" #include "src/core/lib/uri/uri_parser.h" +// Strong and weak refs. #define INTERNAL_REF_BITS 16 #define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1)) +// Backoff parameters. #define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1 #define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6 #define GRPC_SUBCHANNEL_RECONNECT_MIN_TIMEOUT_SECONDS 20 #define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120 #define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2 -typedef struct external_state_watcher { - grpc_subchannel* subchannel; - grpc_pollset_set* pollset_set; - grpc_closure* notify; - grpc_closure closure; - struct external_state_watcher* next; - struct external_state_watcher* prev; -} external_state_watcher; +// Conversion between subchannel call and call stack. +#define SUBCHANNEL_CALL_TO_CALL_STACK(call) \ + (grpc_call_stack*)((char*)(call) + \ + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall))) +#define CALL_STACK_TO_SUBCHANNEL_CALL(callstack) \ + (SubchannelCall*)(((char*)(call_stack)) - \ + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall))) namespace grpc_core { -class ConnectedSubchannelStateWatcher; - -} // namespace grpc_core +// +// ConnectedSubchannel +// -struct grpc_subchannel { - /** The subchannel pool this subchannel is in */ - grpc_core::RefCountedPtr subchannel_pool; +ConnectedSubchannel::ConnectedSubchannel( + grpc_channel_stack* channel_stack, const grpc_channel_args* args, + RefCountedPtr channelz_subchannel, + intptr_t socket_uuid) + : RefCounted(&grpc_trace_stream_refcount), + channel_stack_(channel_stack), + args_(grpc_channel_args_copy(args)), + channelz_subchannel_(std::move(channelz_subchannel)), + socket_uuid_(socket_uuid) {} - grpc_connector* connector; +ConnectedSubchannel::~ConnectedSubchannel() { + grpc_channel_args_destroy(args_); + GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor"); +} - /** refcount - - lower INTERNAL_REF_BITS bits are for internal references: - these do not keep the subchannel open. - - upper remaining bits are for public references: these do - keep the subchannel open */ - gpr_atm ref_pair; +void ConnectedSubchannel::NotifyOnStateChange( + grpc_pollset_set* interested_parties, grpc_connectivity_state* state, + grpc_closure* closure) { + grpc_transport_op* op = grpc_make_transport_op(nullptr); + grpc_channel_element* elem; + op->connectivity_state = state; + op->on_connectivity_state_change = closure; + op->bind_pollset_set = interested_parties; + elem = grpc_channel_stack_element(channel_stack_, 0); + elem->filter->start_transport_op(elem, op); +} - /** channel arguments */ - grpc_channel_args* args; +void ConnectedSubchannel::Ping(grpc_closure* on_initiate, + grpc_closure* on_ack) { + grpc_transport_op* op = grpc_make_transport_op(nullptr); + grpc_channel_element* elem; + op->send_ping.on_initiate = on_initiate; + op->send_ping.on_ack = on_ack; + elem = grpc_channel_stack_element(channel_stack_, 0); + elem->filter->start_transport_op(elem, op); +} - grpc_core::SubchannelKey* key; +namespace { - /** set during connection */ - grpc_connect_out_args connecting_result; +void SubchannelCallDestroy(void* arg, grpc_error* error) { + GPR_TIMER_SCOPE("subchannel_call_destroy", 0); + SubchannelCall* call = static_cast(arg); + grpc_closure* after_call_stack_destroy = call->after_call_stack_destroy(); + call->~SubchannelCall(); + // This should be the last step to destroy the subchannel call, because + // call->after_call_stack_destroy(), if not null, will free the call arena. + grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(call), nullptr, + after_call_stack_destroy); +} - /** callback for connection finishing */ - grpc_closure on_connected; +} // namespace - /** callback for our alarm */ - grpc_closure on_alarm; +RefCountedPtr ConnectedSubchannel::CreateCall( + const CallArgs& args, grpc_error** error) { + const size_t allocation_size = + GetInitialCallSizeEstimate(args.parent_data_size); + RefCountedPtr call( + new (gpr_arena_alloc(args.arena, allocation_size)) + SubchannelCall(Ref(DEBUG_LOCATION, "subchannel_call"), args)); + grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call.get()); + const grpc_call_element_args call_args = { + callstk, /* call_stack */ + nullptr, /* server_transport_data */ + args.context, /* context */ + args.path, /* path */ + args.start_time, /* start_time */ + args.deadline, /* deadline */ + args.arena, /* arena */ + args.call_combiner /* call_combiner */ + }; + *error = grpc_call_stack_init(channel_stack_, 1, SubchannelCallDestroy, + call.get(), &call_args); + if (GPR_UNLIKELY(*error != GRPC_ERROR_NONE)) { + const char* error_string = grpc_error_string(*error); + gpr_log(GPR_ERROR, "error: %s", error_string); + return call; + } + grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); + if (channelz_subchannel_ != nullptr) { + channelz_subchannel_->RecordCallStarted(); + } + return call; +} - /** pollset_set tracking who's interested in a connection - being setup */ - grpc_pollset_set* pollset_set; +size_t ConnectedSubchannel::GetInitialCallSizeEstimate( + size_t parent_data_size) const { + size_t allocation_size = + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)); + if (parent_data_size > 0) { + allocation_size += + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) + + parent_data_size; + } else { + allocation_size += channel_stack_->call_stack_size; + } + return allocation_size; +} - grpc_core::UniquePtr health_check_service_name; +// +// SubchannelCall +// - /** mutex protecting remaining elements */ - gpr_mu mu; +void SubchannelCall::StartTransportStreamOpBatch( + grpc_transport_stream_op_batch* batch) { + GPR_TIMER_SCOPE("subchannel_call_process_op", 0); + MaybeInterceptRecvTrailingMetadata(batch); + grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(this); + grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0); + GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch); + top_elem->filter->start_transport_stream_op_batch(top_elem, batch); +} - /** active connection, or null */ - grpc_core::RefCountedPtr connected_subchannel; - grpc_core::OrphanablePtr - connected_subchannel_watcher; +void* SubchannelCall::GetParentData() { + grpc_channel_stack* chanstk = connected_subchannel_->channel_stack(); + return (char*)this + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(SubchannelCall)) + + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(chanstk->call_stack_size); +} - /** have we seen a disconnection? */ - bool disconnected; - /** are we connecting */ - bool connecting; +grpc_call_stack* SubchannelCall::GetCallStack() { + return SUBCHANNEL_CALL_TO_CALL_STACK(this); +} - /** connectivity state tracking */ - grpc_connectivity_state_tracker state_tracker; - grpc_connectivity_state_tracker state_and_health_tracker; +void SubchannelCall::SetAfterCallStackDestroy(grpc_closure* closure) { + GPR_ASSERT(after_call_stack_destroy_ == nullptr); + GPR_ASSERT(closure != nullptr); + after_call_stack_destroy_ = closure; +} - external_state_watcher root_external_state_watcher; +RefCountedPtr SubchannelCall::Ref() { + IncrementRefCount(); + return RefCountedPtr(this); +} - /** backoff state */ - grpc_core::ManualConstructor backoff; - grpc_millis next_attempt_deadline; - grpc_millis min_connect_timeout_ms; +RefCountedPtr SubchannelCall::Ref( + const grpc_core::DebugLocation& location, const char* reason) { + IncrementRefCount(location, reason); + return RefCountedPtr(this); +} - /** do we have an active alarm? */ - bool have_alarm; - /** have we started the backoff loop */ - bool backoff_begun; - // reset_backoff() was called while alarm was pending - bool retry_immediately; - /** our alarm */ - grpc_timer alarm; +void SubchannelCall::Unref() { + GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), ""); +} - grpc_core::RefCountedPtr - channelz_subchannel; -}; +void SubchannelCall::Unref(const DebugLocation& location, const char* reason) { + GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason); +} -struct grpc_subchannel_call { - grpc_subchannel_call(grpc_core::ConnectedSubchannel* connection, - const grpc_core::ConnectedSubchannel::CallArgs& args) - : connection(connection), deadline(args.deadline) {} - - grpc_core::ConnectedSubchannel* connection; - grpc_closure* schedule_closure_after_destroy = nullptr; - // state needed to support channelz interception of recv trailing metadata. - grpc_closure recv_trailing_metadata_ready; - grpc_closure* original_recv_trailing_metadata; - grpc_metadata_batch* recv_trailing_metadata = nullptr; - grpc_millis deadline; -}; +void SubchannelCall::MaybeInterceptRecvTrailingMetadata( + grpc_transport_stream_op_batch* batch) { + // only intercept payloads with recv trailing. + if (!batch->recv_trailing_metadata) { + return; + } + // only add interceptor is channelz is enabled. + if (connected_subchannel_->channelz_subchannel() == nullptr) { + return; + } + GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready_, RecvTrailingMetadataReady, + this, grpc_schedule_on_exec_ctx); + // save some state needed for the interception callback. + GPR_ASSERT(recv_trailing_metadata_ == nullptr); + recv_trailing_metadata_ = + batch->payload->recv_trailing_metadata.recv_trailing_metadata; + original_recv_trailing_metadata_ = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &recv_trailing_metadata_ready_; +} -static void maybe_start_connecting_locked(grpc_subchannel* c); +namespace { -static const char* subchannel_connectivity_state_change_string( - grpc_connectivity_state state) { - switch (state) { - case GRPC_CHANNEL_IDLE: - return "Subchannel state change to IDLE"; - case GRPC_CHANNEL_CONNECTING: - return "Subchannel state change to CONNECTING"; - case GRPC_CHANNEL_READY: - return "Subchannel state change to READY"; - case GRPC_CHANNEL_TRANSIENT_FAILURE: - return "Subchannel state change to TRANSIENT_FAILURE"; - case GRPC_CHANNEL_SHUTDOWN: - return "Subchannel state change to SHUTDOWN"; +// Sets *status based on the rest of the parameters. +void GetCallStatus(grpc_status_code* status, grpc_millis deadline, + grpc_metadata_batch* md_batch, grpc_error* error) { + if (error != GRPC_ERROR_NONE) { + grpc_error_get_status(error, deadline, status, nullptr, nullptr, nullptr); + } else { + if (md_batch->idx.named.grpc_status != nullptr) { + *status = grpc_get_status_code_from_metadata( + md_batch->idx.named.grpc_status->md); + } else { + *status = GRPC_STATUS_UNKNOWN; + } } - GPR_UNREACHABLE_CODE(return "UNKNOWN"); + GRPC_ERROR_UNREF(error); } -static void set_subchannel_connectivity_state_locked( - grpc_subchannel* c, grpc_connectivity_state state, grpc_error* error, - const char* reason) { - if (c->channelz_subchannel != nullptr) { - c->channelz_subchannel->AddTraceEvent( - grpc_core::channelz::ChannelTrace::Severity::Info, - grpc_slice_from_static_string( - subchannel_connectivity_state_change_string(state))); +} // namespace + +void SubchannelCall::RecvTrailingMetadataReady(void* arg, grpc_error* error) { + SubchannelCall* call = static_cast(arg); + GPR_ASSERT(call->recv_trailing_metadata_ != nullptr); + grpc_status_code status = GRPC_STATUS_OK; + GetCallStatus(&status, call->deadline_, call->recv_trailing_metadata_, + GRPC_ERROR_REF(error)); + channelz::SubchannelNode* channelz_subchannel = + call->connected_subchannel_->channelz_subchannel(); + GPR_ASSERT(channelz_subchannel != nullptr); + if (status == GRPC_STATUS_OK) { + channelz_subchannel->RecordCallSucceeded(); + } else { + channelz_subchannel->RecordCallFailed(); } - grpc_connectivity_state_set(&c->state_tracker, state, error, reason); + GRPC_CLOSURE_RUN(call->original_recv_trailing_metadata_, + GRPC_ERROR_REF(error)); } -namespace grpc_core { +void SubchannelCall::IncrementRefCount() { + GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(this), ""); +} + +void SubchannelCall::IncrementRefCount(const grpc_core::DebugLocation& location, + const char* reason) { + GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason); +} + +// +// Subchannel::ConnectedSubchannelStateWatcher +// -class ConnectedSubchannelStateWatcher +class Subchannel::ConnectedSubchannelStateWatcher : public InternallyRefCounted { public: // Must be instantiated while holding c->mu. - explicit ConnectedSubchannelStateWatcher(grpc_subchannel* c) - : subchannel_(c) { + explicit ConnectedSubchannelStateWatcher(Subchannel* c) : subchannel_(c) { // Steal subchannel ref for connecting. GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "state_watcher"); GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "connecting"); @@ -209,15 +311,15 @@ class ConnectedSubchannelStateWatcher // Callback uses initial ref to this. GRPC_CLOSURE_INIT(&on_connectivity_changed_, OnConnectivityChanged, this, grpc_schedule_on_exec_ctx); - c->connected_subchannel->NotifyOnStateChange(c->pollset_set, - &pending_connectivity_state_, - &on_connectivity_changed_); + c->connected_subchannel_->NotifyOnStateChange(c->pollset_set_, + &pending_connectivity_state_, + &on_connectivity_changed_); // Start health check if needed. grpc_connectivity_state health_state = GRPC_CHANNEL_READY; - if (c->health_check_service_name != nullptr) { - health_check_client_ = grpc_core::MakeOrphanable( - c->health_check_service_name.get(), c->connected_subchannel, - c->pollset_set, c->channelz_subchannel); + if (c->health_check_service_name_ != nullptr) { + health_check_client_ = MakeOrphanable( + c->health_check_service_name_.get(), c->connected_subchannel_, + c->pollset_set_, c->channelz_node_); GRPC_CLOSURE_INIT(&on_health_changed_, OnHealthChanged, this, grpc_schedule_on_exec_ctx); Ref().release(); // Ref for health callback tracked manually. @@ -226,9 +328,9 @@ class ConnectedSubchannelStateWatcher health_state = GRPC_CHANNEL_CONNECTING; } // Report initial state. - set_subchannel_connectivity_state_locked( - c, GRPC_CHANNEL_READY, GRPC_ERROR_NONE, "subchannel_connected"); - grpc_connectivity_state_set(&c->state_and_health_tracker, health_state, + c->SetConnectivityStateLocked(GRPC_CHANNEL_READY, GRPC_ERROR_NONE, + "subchannel_connected"); + grpc_connectivity_state_set(&c->state_and_health_tracker_, health_state, GRPC_ERROR_NONE, "subchannel_connected"); } @@ -242,33 +344,33 @@ class ConnectedSubchannelStateWatcher private: static void OnConnectivityChanged(void* arg, grpc_error* error) { auto* self = static_cast(arg); - grpc_subchannel* c = self->subchannel_; + Subchannel* c = self->subchannel_; { - MutexLock lock(&c->mu); + MutexLock lock(&c->mu_); switch (self->pending_connectivity_state_) { case GRPC_CHANNEL_TRANSIENT_FAILURE: case GRPC_CHANNEL_SHUTDOWN: { - if (!c->disconnected && c->connected_subchannel != nullptr) { + if (!c->disconnected_ && c->connected_subchannel_ != nullptr) { if (grpc_trace_stream_refcount.enabled()) { gpr_log(GPR_INFO, "Connected subchannel %p of subchannel %p has gone into " "%s. Attempting to reconnect.", - c->connected_subchannel.get(), c, + c->connected_subchannel_.get(), c, grpc_connectivity_state_name( self->pending_connectivity_state_)); } - c->connected_subchannel.reset(); - c->connected_subchannel_watcher.reset(); + c->connected_subchannel_.reset(); + c->connected_subchannel_watcher_.reset(); self->last_connectivity_state_ = GRPC_CHANNEL_TRANSIENT_FAILURE; - set_subchannel_connectivity_state_locked( - c, GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), - "reflect_child"); - grpc_connectivity_state_set(&c->state_and_health_tracker, + c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, + GRPC_ERROR_REF(error), + "reflect_child"); + grpc_connectivity_state_set(&c->state_and_health_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), "reflect_child"); - c->backoff_begun = false; - c->backoff->Reset(); - maybe_start_connecting_locked(c); + c->backoff_begun_ = false; + c->backoff_.Reset(); + c->MaybeStartConnectingLocked(); } else { self->last_connectivity_state_ = GRPC_CHANNEL_SHUTDOWN; } @@ -281,15 +383,14 @@ class ConnectedSubchannelStateWatcher // this watch from. And a connected subchannel should never go // from READY to CONNECTING or IDLE. self->last_connectivity_state_ = self->pending_connectivity_state_; - set_subchannel_connectivity_state_locked( - c, self->pending_connectivity_state_, GRPC_ERROR_REF(error), - "reflect_child"); + c->SetConnectivityStateLocked(self->pending_connectivity_state_, + GRPC_ERROR_REF(error), "reflect_child"); if (self->pending_connectivity_state_ != GRPC_CHANNEL_READY) { - grpc_connectivity_state_set(&c->state_and_health_tracker, + grpc_connectivity_state_set(&c->state_and_health_tracker_, self->pending_connectivity_state_, GRPC_ERROR_REF(error), "reflect_child"); } - c->connected_subchannel->NotifyOnStateChange( + c->connected_subchannel_->NotifyOnStateChange( nullptr, &self->pending_connectivity_state_, &self->on_connectivity_changed_); self = nullptr; // So we don't unref below. @@ -303,14 +404,14 @@ class ConnectedSubchannelStateWatcher static void OnHealthChanged(void* arg, grpc_error* error) { auto* self = static_cast(arg); - grpc_subchannel* c = self->subchannel_; - MutexLock lock(&c->mu); + Subchannel* c = self->subchannel_; + MutexLock lock(&c->mu_); if (self->health_state_ == GRPC_CHANNEL_SHUTDOWN) { self->Unref(); return; } if (self->last_connectivity_state_ == GRPC_CHANNEL_READY) { - grpc_connectivity_state_set(&c->state_and_health_tracker, + grpc_connectivity_state_set(&c->state_and_health_tracker_, self->health_state_, GRPC_ERROR_REF(error), "health_changed"); } @@ -318,163 +419,63 @@ class ConnectedSubchannelStateWatcher &self->on_health_changed_); } - grpc_subchannel* subchannel_; + Subchannel* subchannel_; grpc_closure on_connectivity_changed_; grpc_connectivity_state pending_connectivity_state_ = GRPC_CHANNEL_READY; grpc_connectivity_state last_connectivity_state_ = GRPC_CHANNEL_READY; - grpc_core::OrphanablePtr health_check_client_; + OrphanablePtr health_check_client_; grpc_closure on_health_changed_; grpc_connectivity_state health_state_ = GRPC_CHANNEL_CONNECTING; }; -} // namespace grpc_core - -#define SUBCHANNEL_CALL_TO_CALL_STACK(call) \ - (grpc_call_stack*)((char*)(call) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \ - sizeof(grpc_subchannel_call))) -#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \ - (grpc_subchannel_call*)(((char*)(call_stack)) - \ - GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \ - sizeof(grpc_subchannel_call))) - -static void on_subchannel_connected(void* subchannel, grpc_error* error); - -#ifndef NDEBUG -#define REF_REASON reason -#define REF_MUTATE_EXTRA_ARGS \ - GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char* purpose -#define REF_MUTATE_PURPOSE(x) , file, line, reason, x -#else -#define REF_REASON "" -#define REF_MUTATE_EXTRA_ARGS -#define REF_MUTATE_PURPOSE(x) -#endif - -/* - * connection implementation - */ - -static void connection_destroy(void* arg, grpc_error* error) { - grpc_channel_stack* stk = static_cast(arg); - grpc_channel_stack_destroy(stk); - gpr_free(stk); -} - -/* - * grpc_subchannel implementation - */ - -static void subchannel_destroy(void* arg, grpc_error* error) { - grpc_subchannel* c = static_cast(arg); - if (c->channelz_subchannel != nullptr) { - c->channelz_subchannel->AddTraceEvent( - grpc_core::channelz::ChannelTrace::Severity::Info, - grpc_slice_from_static_string("Subchannel destroyed")); - c->channelz_subchannel->MarkSubchannelDestroyed(); - c->channelz_subchannel.reset(); - } - c->health_check_service_name.reset(); - grpc_channel_args_destroy(c->args); - grpc_connectivity_state_destroy(&c->state_tracker); - grpc_connectivity_state_destroy(&c->state_and_health_tracker); - grpc_connector_unref(c->connector); - grpc_pollset_set_destroy(c->pollset_set); - grpc_core::Delete(c->key); - gpr_mu_destroy(&c->mu); - gpr_free(c); -} +// +// Subchannel::ExternalStateWatcher +// -static gpr_atm ref_mutate(grpc_subchannel* c, gpr_atm delta, - int barrier REF_MUTATE_EXTRA_ARGS) { - gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&c->ref_pair, delta) - : gpr_atm_no_barrier_fetch_add(&c->ref_pair, delta); -#ifndef NDEBUG - if (grpc_trace_stream_refcount.enabled()) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", c, - purpose, old_val, old_val + delta, reason); +struct Subchannel::ExternalStateWatcher { + ExternalStateWatcher(Subchannel* subchannel, grpc_pollset_set* pollset_set, + grpc_closure* notify) + : subchannel(subchannel), pollset_set(pollset_set), notify(notify) { + GRPC_SUBCHANNEL_WEAK_REF(subchannel, "external_state_watcher+init"); + GRPC_CLOSURE_INIT(&on_state_changed, OnStateChanged, this, + grpc_schedule_on_exec_ctx); } -#endif - return old_val; -} - -grpc_subchannel* grpc_subchannel_ref( - grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = ref_mutate(c, (1 << INTERNAL_REF_BITS), - 0 REF_MUTATE_PURPOSE("STRONG_REF")); - GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0); - return c; -} - -grpc_subchannel* grpc_subchannel_weak_ref( - grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = ref_mutate(c, 1, 0 REF_MUTATE_PURPOSE("WEAK_REF")); - GPR_ASSERT(old_refs != 0); - return c; -} -grpc_subchannel* grpc_subchannel_ref_from_weak_ref( - grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - if (!c) return nullptr; - for (;;) { - gpr_atm old_refs = gpr_atm_acq_load(&c->ref_pair); - if (old_refs >= (1 << INTERNAL_REF_BITS)) { - gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS); - if (gpr_atm_rel_cas(&c->ref_pair, old_refs, new_refs)) { - return c; - } - } else { - return nullptr; + static void OnStateChanged(void* arg, grpc_error* error) { + ExternalStateWatcher* w = static_cast(arg); + grpc_closure* follow_up = w->notify; + if (w->pollset_set != nullptr) { + grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set_, + w->pollset_set); } + gpr_mu_lock(&w->subchannel->mu_); + if (w->subchannel->external_state_watcher_list_ == w) { + w->subchannel->external_state_watcher_list_ = w->next; + } + if (w->next != nullptr) w->next->prev = w->prev; + if (w->prev != nullptr) w->prev->next = w->next; + gpr_mu_unlock(&w->subchannel->mu_); + GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher+done"); + Delete(w); + GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); } -} -static void disconnect(grpc_subchannel* c) { - // The subchannel_pool is only used once here in this subchannel, so the - // access can be outside of the lock. - if (c->subchannel_pool != nullptr) { - c->subchannel_pool->UnregisterSubchannel(c->key); - c->subchannel_pool.reset(); - } - gpr_mu_lock(&c->mu); - GPR_ASSERT(!c->disconnected); - c->disconnected = true; - grpc_connector_shutdown(c->connector, GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Subchannel disconnected")); - c->connected_subchannel.reset(); - c->connected_subchannel_watcher.reset(); - gpr_mu_unlock(&c->mu); -} + Subchannel* subchannel; + grpc_pollset_set* pollset_set; + grpc_closure* notify; + grpc_closure on_state_changed; + ExternalStateWatcher* next = nullptr; + ExternalStateWatcher* prev = nullptr; +}; -void grpc_subchannel_unref(grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - // add a weak ref and subtract a strong ref (atomically) - old_refs = ref_mutate( - c, static_cast(1) - static_cast(1 << INTERNAL_REF_BITS), - 1 REF_MUTATE_PURPOSE("STRONG_UNREF")); - if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) { - disconnect(c); - } - GRPC_SUBCHANNEL_WEAK_UNREF(c, "strong-unref"); -} +// +// Subchannel +// -void grpc_subchannel_weak_unref( - grpc_subchannel* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = ref_mutate(c, -static_cast(1), - 1 REF_MUTATE_PURPOSE("WEAK_UNREF")); - if (old_refs == 1) { - GRPC_CLOSURE_SCHED( - GRPC_CLOSURE_CREATE(subchannel_destroy, c, grpc_schedule_on_exec_ctx), - GRPC_ERROR_NONE); - } -} +namespace { -static void parse_args_for_backoff_values( - const grpc_channel_args* args, grpc_core::BackOff::Options* backoff_options, - grpc_millis* min_connect_timeout_ms) { +BackOff::Options ParseArgsForBackoffValues( + const grpc_channel_args* args, grpc_millis* min_connect_timeout_ms) { grpc_millis initial_backoff_ms = GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000; *min_connect_timeout_ms = @@ -511,7 +512,8 @@ static void parse_args_for_backoff_values( } } } - backoff_options->set_initial_backoff(initial_backoff_ms) + return BackOff::Options() + .set_initial_backoff(initial_backoff_ms) .set_multiplier(fixed_reconnect_backoff ? 1.0 : GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER) @@ -520,9 +522,6 @@ static void parse_args_for_backoff_values( .set_max_backoff(max_backoff_ms); } -namespace grpc_core { -namespace { - struct HealthCheckParams { UniquePtr service_name; @@ -543,31 +542,19 @@ struct HealthCheckParams { }; } // namespace -} // namespace grpc_core -grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, - const grpc_channel_args* args) { - grpc_core::SubchannelKey* key = - grpc_core::New(args); - grpc_core::SubchannelPoolInterface* subchannel_pool = - grpc_core::SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs( - args); - GPR_ASSERT(subchannel_pool != nullptr); - grpc_subchannel* c = subchannel_pool->FindSubchannel(key); - if (c != nullptr) { - grpc_core::Delete(key); - return c; - } +Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector, + const grpc_channel_args* args) + : key_(key), + connector_(connector), + backoff_(ParseArgsForBackoffValues(args, &min_connect_timeout_ms_)) { GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED(); - c = static_cast(gpr_zalloc(sizeof(*c))); - c->key = key; - gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS); - c->connector = connector; - grpc_connector_ref(c->connector); - c->pollset_set = grpc_pollset_set_create(); + gpr_atm_no_barrier_store(&ref_pair_, 1 << INTERNAL_REF_BITS); + grpc_connector_ref(connector_); + pollset_set_ = grpc_pollset_set_create(); grpc_resolved_address* addr = static_cast(gpr_malloc(sizeof(*addr))); - grpc_get_subchannel_address_arg(args, addr); + GetAddressFromSubchannelAddressArg(args, addr); grpc_resolved_address* new_address = nullptr; grpc_channel_args* new_args = nullptr; if (grpc_proxy_mappers_map_address(addr, args, &new_address, &new_args)) { @@ -576,569 +563,492 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, addr = new_address; } static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS}; - grpc_arg new_arg = grpc_create_subchannel_address_arg(addr); + grpc_arg new_arg = CreateSubchannelAddressArg(addr); gpr_free(addr); - c->args = grpc_channel_args_copy_and_add_and_remove( + args_ = grpc_channel_args_copy_and_add_and_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); - c->root_external_state_watcher.next = c->root_external_state_watcher.prev = - &c->root_external_state_watcher; - GRPC_CLOSURE_INIT(&c->on_connected, on_subchannel_connected, c, + GRPC_CLOSURE_INIT(&on_connecting_finished_, OnConnectingFinished, this, grpc_schedule_on_exec_ctx); - grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE, + grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE, "subchannel"); - grpc_connectivity_state_init(&c->state_and_health_tracker, GRPC_CHANNEL_IDLE, + grpc_connectivity_state_init(&state_and_health_tracker_, GRPC_CHANNEL_IDLE, "subchannel"); - grpc_core::BackOff::Options 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); - + gpr_mu_init(&mu_); // Check whether we should enable health checking. const char* service_config_json = grpc_channel_arg_get_string( - grpc_channel_args_find(c->args, GRPC_ARG_SERVICE_CONFIG)); + grpc_channel_args_find(args_, GRPC_ARG_SERVICE_CONFIG)); if (service_config_json != nullptr) { - grpc_core::UniquePtr service_config = - grpc_core::ServiceConfig::Create(service_config_json); + UniquePtr service_config = + ServiceConfig::Create(service_config_json); if (service_config != nullptr) { - grpc_core::HealthCheckParams params; - service_config->ParseGlobalParams(grpc_core::HealthCheckParams::Parse, - ¶ms); - c->health_check_service_name = std::move(params.service_name); + HealthCheckParams params; + service_config->ParseGlobalParams(HealthCheckParams::Parse, ¶ms); + health_check_service_name_ = std::move(params.service_name); } } - - const grpc_arg* arg = - grpc_channel_args_find(c->args, GRPC_ARG_ENABLE_CHANNELZ); - bool channelz_enabled = + const grpc_arg* arg = grpc_channel_args_find(args_, GRPC_ARG_ENABLE_CHANNELZ); + const bool channelz_enabled = grpc_channel_arg_get_bool(arg, GRPC_ENABLE_CHANNELZ_DEFAULT); arg = grpc_channel_args_find( - c->args, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE); + args_, GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE); const grpc_integer_options options = { GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT, 0, INT_MAX}; size_t channel_tracer_max_memory = (size_t)grpc_channel_arg_get_integer(arg, options); if (channelz_enabled) { - c->channelz_subchannel = - grpc_core::MakeRefCounted( - c, channel_tracer_max_memory); - c->channelz_subchannel->AddTraceEvent( - grpc_core::channelz::ChannelTrace::Severity::Info, - grpc_slice_from_static_string("Subchannel created")); + channelz_node_ = MakeRefCounted( + this, channel_tracer_max_memory); + channelz_node_->AddTraceEvent( + channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("subchannel created")); + } +} + +Subchannel::~Subchannel() { + if (channelz_node_ != nullptr) { + channelz_node_->AddTraceEvent( + channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string("Subchannel destroyed")); + channelz_node_->MarkSubchannelDestroyed(); + } + grpc_channel_args_destroy(args_); + grpc_connectivity_state_destroy(&state_tracker_); + grpc_connectivity_state_destroy(&state_and_health_tracker_); + grpc_connector_unref(connector_); + grpc_pollset_set_destroy(pollset_set_); + Delete(key_); + gpr_mu_destroy(&mu_); +} + +Subchannel* Subchannel::Create(grpc_connector* connector, + const grpc_channel_args* args) { + SubchannelKey* key = New(args); + SubchannelPoolInterface* subchannel_pool = + SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs(args); + GPR_ASSERT(subchannel_pool != nullptr); + Subchannel* c = subchannel_pool->FindSubchannel(key); + if (c != nullptr) { + Delete(key); + return c; } + c = New(key, connector, args); // Try to register the subchannel before setting the subchannel pool. // Otherwise, in case of a registration race, unreffing c in - // RegisterSubchannel() will cause c to be tried to be unregistered, while its - // key maps to a different subchannel. - grpc_subchannel* registered = subchannel_pool->RegisterSubchannel(key, c); - if (registered == c) c->subchannel_pool = subchannel_pool->Ref(); + // RegisterSubchannel() will cause c to be tried to be unregistered, while + // its key maps to a different subchannel. + Subchannel* registered = subchannel_pool->RegisterSubchannel(key, c); + if (registered == c) c->subchannel_pool_ = subchannel_pool->Ref(); return registered; } -grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node( - grpc_subchannel* subchannel) { - return subchannel->channelz_subchannel.get(); +Subchannel* Subchannel::Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + old_refs = RefMutate((1 << INTERNAL_REF_BITS), + 0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_REF")); + GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0); + return this; } -intptr_t grpc_subchannel_get_child_socket_uuid(grpc_subchannel* subchannel) { - if (subchannel->connected_subchannel != nullptr) { - return subchannel->connected_subchannel->socket_uuid(); - } else { - return 0; +void Subchannel::Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + // add a weak ref and subtract a strong ref (atomically) + old_refs = RefMutate( + static_cast(1) - static_cast(1 << INTERNAL_REF_BITS), + 1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_UNREF")); + if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) { + Disconnect(); } + GRPC_SUBCHANNEL_WEAK_UNREF(this, "strong-unref"); } -static void continue_connect_locked(grpc_subchannel* c) { - grpc_connect_in_args args; - args.interested_parties = c->pollset_set; - const grpc_millis min_deadline = - c->min_connect_timeout_ms + grpc_core::ExecCtx::Get()->Now(); - c->next_attempt_deadline = c->backoff->NextAttemptTime(); - args.deadline = std::max(c->next_attempt_deadline, min_deadline); - args.channel_args = c->args; - set_subchannel_connectivity_state_locked(c, GRPC_CHANNEL_CONNECTING, - GRPC_ERROR_NONE, "connecting"); - grpc_connectivity_state_set(&c->state_and_health_tracker, - GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, - "connecting"); - grpc_connector_connect(c->connector, &args, &c->connecting_result, - &c->on_connected); +Subchannel* Subchannel::WeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + old_refs = RefMutate(1, 0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_REF")); + GPR_ASSERT(old_refs != 0); + return this; } -grpc_connectivity_state grpc_subchannel_check_connectivity( - grpc_subchannel* c, grpc_error** error, bool inhibit_health_checks) { - gpr_mu_lock(&c->mu); - grpc_connectivity_state_tracker* tracker = - inhibit_health_checks ? &c->state_tracker : &c->state_and_health_tracker; - grpc_connectivity_state state = grpc_connectivity_state_get(tracker, error); - gpr_mu_unlock(&c->mu); - return state; -} +namespace { -static void on_external_state_watcher_done(void* arg, grpc_error* error) { - external_state_watcher* w = static_cast(arg); - grpc_closure* follow_up = w->notify; - if (w->pollset_set != nullptr) { - grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set, - w->pollset_set); - } - gpr_mu_lock(&w->subchannel->mu); - w->next->prev = w->prev; - w->prev->next = w->next; - gpr_mu_unlock(&w->subchannel->mu); - GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher"); - gpr_free(w); - GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); +void subchannel_destroy(void* arg, grpc_error* error) { + Subchannel* self = static_cast(arg); + Delete(self); } -static void on_alarm(void* arg, grpc_error* error) { - grpc_subchannel* c = static_cast(arg); - gpr_mu_lock(&c->mu); - c->have_alarm = false; - if (c->disconnected) { - error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", - &error, 1); - } else if (c->retry_immediately) { - c->retry_immediately = false; - error = GRPC_ERROR_NONE; - } else { - GRPC_ERROR_REF(error); - } - if (error == GRPC_ERROR_NONE) { - gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); - continue_connect_locked(c); - gpr_mu_unlock(&c->mu); - } else { - gpr_mu_unlock(&c->mu); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); +} // namespace + +void Subchannel::WeakUnref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + gpr_atm old_refs; + old_refs = RefMutate(-static_cast(1), + 1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_UNREF")); + if (old_refs == 1) { + GRPC_CLOSURE_SCHED(GRPC_CLOSURE_CREATE(subchannel_destroy, this, + grpc_schedule_on_exec_ctx), + GRPC_ERROR_NONE); } - GRPC_ERROR_UNREF(error); } -static void maybe_start_connecting_locked(grpc_subchannel* c) { - if (c->disconnected) { - /* Don't try to connect if we're already disconnected */ - return; - } - if (c->connecting) { - /* Already connecting: don't restart */ - return; - } - if (c->connected_subchannel != nullptr) { - /* Already connected: don't restart */ - return; - } - if (!grpc_connectivity_state_has_watchers(&c->state_tracker) && - !grpc_connectivity_state_has_watchers(&c->state_and_health_tracker)) { - /* Nobody is interested in connecting: so don't just yet */ - return; - } - c->connecting = true; - GRPC_SUBCHANNEL_WEAK_REF(c, "connecting"); - if (!c->backoff_begun) { - c->backoff_begun = true; - continue_connect_locked(c); - } else { - GPR_ASSERT(!c->have_alarm); - c->have_alarm = true; - const grpc_millis time_til_next = - c->next_attempt_deadline - grpc_core::ExecCtx::Get()->Now(); - if (time_til_next <= 0) { - gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", c); +Subchannel* Subchannel::RefFromWeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { + for (;;) { + gpr_atm old_refs = gpr_atm_acq_load(&ref_pair_); + if (old_refs >= (1 << INTERNAL_REF_BITS)) { + gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS); + if (gpr_atm_rel_cas(&ref_pair_, old_refs, new_refs)) { + return this; + } } else { - gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRId64 " milliseconds", c, - time_til_next); + return nullptr; } - GRPC_CLOSURE_INIT(&c->on_alarm, on_alarm, c, grpc_schedule_on_exec_ctx); - grpc_timer_init(&c->alarm, c->next_attempt_deadline, &c->on_alarm); } } -void grpc_subchannel_notify_on_state_change( - grpc_subchannel* c, grpc_pollset_set* interested_parties, - grpc_connectivity_state* state, grpc_closure* notify, - bool inhibit_health_checks) { +intptr_t Subchannel::GetChildSocketUuid() { + if (connected_subchannel_ != nullptr) { + return connected_subchannel_->socket_uuid(); + } else { + return 0; + } +} + +const char* Subchannel::GetTargetAddress() { + const grpc_arg* addr_arg = + grpc_channel_args_find(args_, GRPC_ARG_SUBCHANNEL_ADDRESS); + const char* addr_str = grpc_channel_arg_get_string(addr_arg); + GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. + return addr_str; +} + +RefCountedPtr Subchannel::connected_subchannel() { + MutexLock lock(&mu_); + return connected_subchannel_; +} + +channelz::SubchannelNode* Subchannel::channelz_node() { + return channelz_node_.get(); +} + +grpc_connectivity_state Subchannel::CheckConnectivity( + grpc_error** error, bool inhibit_health_checks) { + MutexLock lock(&mu_); + grpc_connectivity_state_tracker* tracker = + inhibit_health_checks ? &state_tracker_ : &state_and_health_tracker_; + grpc_connectivity_state state = grpc_connectivity_state_get(tracker, error); + return state; +} + +void Subchannel::NotifyOnStateChange(grpc_pollset_set* interested_parties, + grpc_connectivity_state* state, + grpc_closure* notify, + bool inhibit_health_checks) { grpc_connectivity_state_tracker* tracker = - inhibit_health_checks ? &c->state_tracker : &c->state_and_health_tracker; - external_state_watcher* w; + inhibit_health_checks ? &state_tracker_ : &state_and_health_tracker_; + ExternalStateWatcher* w; if (state == nullptr) { - gpr_mu_lock(&c->mu); - for (w = c->root_external_state_watcher.next; - w != &c->root_external_state_watcher; w = w->next) { + MutexLock lock(&mu_); + for (w = external_state_watcher_list_; w != nullptr; w = w->next) { if (w->notify == notify) { grpc_connectivity_state_notify_on_state_change(tracker, nullptr, - &w->closure); + &w->on_state_changed); } } - gpr_mu_unlock(&c->mu); } else { - w = static_cast(gpr_malloc(sizeof(*w))); - w->subchannel = c; - w->pollset_set = interested_parties; - w->notify = notify; - GRPC_CLOSURE_INIT(&w->closure, on_external_state_watcher_done, w, - grpc_schedule_on_exec_ctx); + w = New(this, interested_parties, notify); if (interested_parties != nullptr) { - grpc_pollset_set_add_pollset_set(c->pollset_set, interested_parties); + grpc_pollset_set_add_pollset_set(pollset_set_, interested_parties); } - GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher"); - gpr_mu_lock(&c->mu); - w->next = &c->root_external_state_watcher; - w->prev = w->next->prev; - w->next->prev = w->prev->next = w; - grpc_connectivity_state_notify_on_state_change(tracker, state, &w->closure); - maybe_start_connecting_locked(c); - gpr_mu_unlock(&c->mu); + MutexLock lock(&mu_); + if (external_state_watcher_list_ != nullptr) { + w->next = external_state_watcher_list_; + w->next->prev = w; + } + external_state_watcher_list_ = w; + grpc_connectivity_state_notify_on_state_change(tracker, state, + &w->on_state_changed); + MaybeStartConnectingLocked(); } } -static bool publish_transport_locked(grpc_subchannel* c) { - /* construct channel stack */ - grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create(); - grpc_channel_stack_builder_set_channel_arguments( - builder, c->connecting_result.channel_args); - grpc_channel_stack_builder_set_transport(builder, - c->connecting_result.transport); - - if (!grpc_channel_init_create_stack(builder, GRPC_CLIENT_SUBCHANNEL)) { - grpc_channel_stack_builder_destroy(builder); - return false; - } - grpc_channel_stack* stk; - grpc_error* error = grpc_channel_stack_builder_finish( - builder, 0, 1, connection_destroy, nullptr, - reinterpret_cast(&stk)); - if (error != GRPC_ERROR_NONE) { - grpc_transport_destroy(c->connecting_result.transport); - gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", - grpc_error_string(error)); - GRPC_ERROR_UNREF(error); - return false; - } - intptr_t socket_uuid = c->connecting_result.socket_uuid; - memset(&c->connecting_result, 0, sizeof(c->connecting_result)); - - if (c->disconnected) { - grpc_channel_stack_destroy(stk); - gpr_free(stk); - return false; +void Subchannel::ResetBackoff() { + MutexLock lock(&mu_); + backoff_.Reset(); + if (have_retry_alarm_) { + retry_immediately_ = true; + grpc_timer_cancel(&retry_alarm_); + } else { + backoff_begun_ = false; + MaybeStartConnectingLocked(); } - - /* publish */ - c->connected_subchannel.reset(grpc_core::New( - stk, c->args, c->channelz_subchannel, socket_uuid)); - gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p", - c->connected_subchannel.get(), c); - - // Instantiate state watcher. Will clean itself up. - c->connected_subchannel_watcher = - grpc_core::MakeOrphanable(c); - - return true; } -static void on_subchannel_connected(void* arg, grpc_error* error) { - grpc_subchannel* c = static_cast(arg); - grpc_channel_args* delete_channel_args = c->connecting_result.channel_args; - - GRPC_SUBCHANNEL_WEAK_REF(c, "on_subchannel_connected"); - gpr_mu_lock(&c->mu); - c->connecting = false; - if (c->connecting_result.transport != nullptr && - publish_transport_locked(c)) { - /* do nothing, transport was published */ - } else if (c->disconnected) { - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); - } else { - set_subchannel_connectivity_state_locked( - c, GRPC_CHANNEL_TRANSIENT_FAILURE, - grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Connect Failed", &error, 1), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), - "connect_failed"); - grpc_connectivity_state_set( - &c->state_and_health_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, - grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Connect Failed", &error, 1), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), - "connect_failed"); - - const char* errmsg = grpc_error_string(error); - gpr_log(GPR_INFO, "Connect failed: %s", errmsg); - - maybe_start_connecting_locked(c); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); - } - gpr_mu_unlock(&c->mu); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connected"); - grpc_channel_args_destroy(delete_channel_args); +grpc_arg Subchannel::CreateSubchannelAddressArg( + const grpc_resolved_address* addr) { + return grpc_channel_arg_string_create( + (char*)GRPC_ARG_SUBCHANNEL_ADDRESS, + addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup("")); } -void grpc_subchannel_reset_backoff(grpc_subchannel* subchannel) { - gpr_mu_lock(&subchannel->mu); - subchannel->backoff->Reset(); - if (subchannel->have_alarm) { - subchannel->retry_immediately = true; - grpc_timer_cancel(&subchannel->alarm); - } else { - subchannel->backoff_begun = false; - maybe_start_connecting_locked(subchannel); - } - gpr_mu_unlock(&subchannel->mu); +const char* Subchannel::GetUriFromSubchannelAddressArg( + const grpc_channel_args* args) { + const grpc_arg* addr_arg = + grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); + const char* addr_str = grpc_channel_arg_get_string(addr_arg); + GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. + return addr_str; } -/* - * grpc_subchannel_call implementation - */ +namespace { -static void subchannel_call_destroy(void* call, grpc_error* error) { - GPR_TIMER_SCOPE("grpc_subchannel_call_unref.destroy", 0); - grpc_subchannel_call* c = static_cast(call); - grpc_core::ConnectedSubchannel* connection = c->connection; - grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(c), nullptr, - c->schedule_closure_after_destroy); - connection->Unref(DEBUG_LOCATION, "subchannel_call"); - c->~grpc_subchannel_call(); +void UriToSockaddr(const char* uri_str, grpc_resolved_address* addr) { + grpc_uri* uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */); + GPR_ASSERT(uri != nullptr); + if (!grpc_parse_uri(uri, addr)) memset(addr, 0, sizeof(*addr)); + grpc_uri_destroy(uri); } -void grpc_subchannel_call_set_cleanup_closure(grpc_subchannel_call* call, - grpc_closure* closure) { - GPR_ASSERT(call->schedule_closure_after_destroy == nullptr); - GPR_ASSERT(closure != nullptr); - call->schedule_closure_after_destroy = closure; -} +} // namespace -grpc_subchannel_call* grpc_subchannel_call_ref( - grpc_subchannel_call* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - GRPC_CALL_STACK_REF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON); - return c; +void Subchannel::GetAddressFromSubchannelAddressArg( + const grpc_channel_args* args, grpc_resolved_address* addr) { + const char* addr_uri_str = GetUriFromSubchannelAddressArg(args); + memset(addr, 0, sizeof(*addr)); + if (*addr_uri_str != '\0') { + UriToSockaddr(addr_uri_str, addr); + } } -void grpc_subchannel_call_unref( - grpc_subchannel_call* c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(c), REF_REASON); -} +namespace { -// Sets *status based on md_batch and error. -static void get_call_status(grpc_subchannel_call* call, - grpc_metadata_batch* md_batch, grpc_error* error, - grpc_status_code* status) { - if (error != GRPC_ERROR_NONE) { - grpc_error_get_status(error, call->deadline, status, nullptr, nullptr, - nullptr); - } else { - if (md_batch->idx.named.grpc_status != nullptr) { - *status = grpc_get_status_code_from_metadata( - md_batch->idx.named.grpc_status->md); - } else { - *status = GRPC_STATUS_UNKNOWN; - } +// Returns a string indicating the subchannel's connectivity state change to +// \a state. +const char* SubchannelConnectivityStateChangeString( + grpc_connectivity_state state) { + switch (state) { + case GRPC_CHANNEL_IDLE: + return "Subchannel state change to IDLE"; + case GRPC_CHANNEL_CONNECTING: + return "Subchannel state change to CONNECTING"; + case GRPC_CHANNEL_READY: + return "Subchannel state change to READY"; + case GRPC_CHANNEL_TRANSIENT_FAILURE: + return "Subchannel state change to TRANSIENT_FAILURE"; + case GRPC_CHANNEL_SHUTDOWN: + return "Subchannel state change to SHUTDOWN"; } - GRPC_ERROR_UNREF(error); + GPR_UNREACHABLE_CODE(return "UNKNOWN"); } -static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { - grpc_subchannel_call* call = static_cast(arg); - GPR_ASSERT(call->recv_trailing_metadata != nullptr); - grpc_status_code status = GRPC_STATUS_OK; - grpc_metadata_batch* md_batch = call->recv_trailing_metadata; - get_call_status(call, md_batch, GRPC_ERROR_REF(error), &status); - grpc_core::channelz::SubchannelNode* channelz_subchannel = - call->connection->channelz_subchannel(); - GPR_ASSERT(channelz_subchannel != nullptr); - if (status == GRPC_STATUS_OK) { - channelz_subchannel->RecordCallSucceeded(); - } else { - channelz_subchannel->RecordCallFailed(); +} // namespace + +void Subchannel::SetConnectivityStateLocked(grpc_connectivity_state state, + grpc_error* error, + const char* reason) { + if (channelz_node_ != nullptr) { + channelz_node_->AddTraceEvent( + channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string( + SubchannelConnectivityStateChangeString(state))); } - GRPC_CLOSURE_RUN(call->original_recv_trailing_metadata, - GRPC_ERROR_REF(error)); + grpc_connectivity_state_set(&state_tracker_, state, error, reason); } -// If channelz is enabled, intercept recv_trailing so that we may check the -// status and associate it to a subchannel. -static void maybe_intercept_recv_trailing_metadata( - grpc_subchannel_call* call, grpc_transport_stream_op_batch* batch) { - // only intercept payloads with recv trailing. - if (!batch->recv_trailing_metadata) { +void Subchannel::MaybeStartConnectingLocked() { + if (disconnected_) { + // Don't try to connect if we're already disconnected. return; } - // only add interceptor is channelz is enabled. - if (call->connection->channelz_subchannel() == nullptr) { + if (connecting_) { + // Already connecting: don't restart. return; } - GRPC_CLOSURE_INIT(&call->recv_trailing_metadata_ready, - recv_trailing_metadata_ready, call, - grpc_schedule_on_exec_ctx); - // save some state needed for the interception callback. - GPR_ASSERT(call->recv_trailing_metadata == nullptr); - call->recv_trailing_metadata = - batch->payload->recv_trailing_metadata.recv_trailing_metadata; - call->original_recv_trailing_metadata = - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = - &call->recv_trailing_metadata_ready; -} - -void grpc_subchannel_call_process_op(grpc_subchannel_call* call, - grpc_transport_stream_op_batch* batch) { - GPR_TIMER_SCOPE("grpc_subchannel_call_process_op", 0); - maybe_intercept_recv_trailing_metadata(call, batch); - grpc_call_stack* call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call); - grpc_call_element* top_elem = grpc_call_stack_element(call_stack, 0); - GRPC_CALL_LOG_OP(GPR_INFO, top_elem, batch); - top_elem->filter->start_transport_stream_op_batch(top_elem, batch); + if (connected_subchannel_ != nullptr) { + // Already connected: don't restart. + return; + } + if (!grpc_connectivity_state_has_watchers(&state_tracker_) && + !grpc_connectivity_state_has_watchers(&state_and_health_tracker_)) { + // Nobody is interested in connecting: so don't just yet. + return; + } + connecting_ = true; + GRPC_SUBCHANNEL_WEAK_REF(this, "connecting"); + if (!backoff_begun_) { + backoff_begun_ = true; + ContinueConnectingLocked(); + } else { + GPR_ASSERT(!have_retry_alarm_); + have_retry_alarm_ = true; + const grpc_millis time_til_next = + next_attempt_deadline_ - ExecCtx::Get()->Now(); + if (time_til_next <= 0) { + gpr_log(GPR_INFO, "Subchannel %p: Retry immediately", this); + } else { + gpr_log(GPR_INFO, "Subchannel %p: Retry in %" PRId64 " milliseconds", + this, time_til_next); + } + GRPC_CLOSURE_INIT(&on_retry_alarm_, OnRetryAlarm, this, + grpc_schedule_on_exec_ctx); + grpc_timer_init(&retry_alarm_, next_attempt_deadline_, &on_retry_alarm_); + } } -grpc_core::RefCountedPtr -grpc_subchannel_get_connected_subchannel(grpc_subchannel* c) { - gpr_mu_lock(&c->mu); - auto copy = c->connected_subchannel; - gpr_mu_unlock(&c->mu); - return copy; +void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { + Subchannel* c = static_cast(arg); + gpr_mu_lock(&c->mu_); + c->have_retry_alarm_ = false; + if (c->disconnected_) { + error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", + &error, 1); + } else if (c->retry_immediately_) { + c->retry_immediately_ = false; + error = GRPC_ERROR_NONE; + } else { + GRPC_ERROR_REF(error); + } + if (error == GRPC_ERROR_NONE) { + gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); + c->ContinueConnectingLocked(); + gpr_mu_unlock(&c->mu_); + } else { + gpr_mu_unlock(&c->mu_); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } + GRPC_ERROR_UNREF(error); } -void* grpc_connected_subchannel_call_get_parent_data( - grpc_subchannel_call* subchannel_call) { - grpc_channel_stack* chanstk = subchannel_call->connection->channel_stack(); - return (char*)subchannel_call + - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_subchannel_call)) + - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(chanstk->call_stack_size); +void Subchannel::ContinueConnectingLocked() { + grpc_connect_in_args args; + args.interested_parties = pollset_set_; + const grpc_millis min_deadline = + min_connect_timeout_ms_ + ExecCtx::Get()->Now(); + next_attempt_deadline_ = backoff_.NextAttemptTime(); + args.deadline = std::max(next_attempt_deadline_, min_deadline); + args.channel_args = args_; + SetConnectivityStateLocked(GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, + "connecting"); + grpc_connectivity_state_set(&state_and_health_tracker_, + GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE, + "connecting"); + grpc_connector_connect(connector_, &args, &connecting_result_, + &on_connecting_finished_); } -grpc_call_stack* grpc_subchannel_call_get_call_stack( - grpc_subchannel_call* subchannel_call) { - return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call); -} +void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) { + auto* c = static_cast(arg); + grpc_channel_args* delete_channel_args = c->connecting_result_.channel_args; + GRPC_SUBCHANNEL_WEAK_REF(c, "on_connecting_finished"); + gpr_mu_lock(&c->mu_); + c->connecting_ = false; + if (c->connecting_result_.transport != nullptr && + c->PublishTransportLocked()) { + // Do nothing, transport was published. + } else if (c->disconnected_) { + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } else { + c->SetConnectivityStateLocked( + GRPC_CHANNEL_TRANSIENT_FAILURE, + grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Connect Failed", &error, 1), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), + "connect_failed"); + grpc_connectivity_state_set( + &c->state_and_health_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE, + grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Connect Failed", &error, 1), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), + "connect_failed"); -static void grpc_uri_to_sockaddr(const char* uri_str, - grpc_resolved_address* addr) { - grpc_uri* uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */); - GPR_ASSERT(uri != nullptr); - if (!grpc_parse_uri(uri, addr)) memset(addr, 0, sizeof(*addr)); - grpc_uri_destroy(uri); -} + const char* errmsg = grpc_error_string(error); + gpr_log(GPR_INFO, "Connect failed: %s", errmsg); -void grpc_get_subchannel_address_arg(const grpc_channel_args* args, - grpc_resolved_address* addr) { - const char* addr_uri_str = grpc_get_subchannel_address_uri_arg(args); - memset(addr, 0, sizeof(*addr)); - if (*addr_uri_str != '\0') { - grpc_uri_to_sockaddr(addr_uri_str, addr); + c->MaybeStartConnectingLocked(); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); } + gpr_mu_unlock(&c->mu_); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "on_connecting_finished"); + grpc_channel_args_destroy(delete_channel_args); } -const char* grpc_subchannel_get_target(grpc_subchannel* subchannel) { - const grpc_arg* addr_arg = - grpc_channel_args_find(subchannel->args, GRPC_ARG_SUBCHANNEL_ADDRESS); - const char* addr_str = grpc_channel_arg_get_string(addr_arg); - GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. - return addr_str; -} - -const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args) { - const grpc_arg* addr_arg = - grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); - const char* addr_str = grpc_channel_arg_get_string(addr_arg); - GPR_ASSERT(addr_str != nullptr); // Should have been set by LB policy. - return addr_str; -} - -grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr) { - return grpc_channel_arg_string_create( - (char*)GRPC_ARG_SUBCHANNEL_ADDRESS, - addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup("")); -} - -namespace grpc_core { - -ConnectedSubchannel::ConnectedSubchannel( - grpc_channel_stack* channel_stack, const grpc_channel_args* args, - grpc_core::RefCountedPtr - channelz_subchannel, - intptr_t socket_uuid) - : RefCounted(&grpc_trace_stream_refcount), - channel_stack_(channel_stack), - args_(grpc_channel_args_copy(args)), - channelz_subchannel_(std::move(channelz_subchannel)), - socket_uuid_(socket_uuid) {} +namespace { -ConnectedSubchannel::~ConnectedSubchannel() { - grpc_channel_args_destroy(args_); - GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor"); +void ConnectionDestroy(void* arg, grpc_error* error) { + grpc_channel_stack* stk = static_cast(arg); + grpc_channel_stack_destroy(stk); + gpr_free(stk); } -void ConnectedSubchannel::NotifyOnStateChange( - grpc_pollset_set* interested_parties, grpc_connectivity_state* state, - grpc_closure* closure) { - grpc_transport_op* op = grpc_make_transport_op(nullptr); - grpc_channel_element* elem; - op->connectivity_state = state; - op->on_connectivity_state_change = closure; - op->bind_pollset_set = interested_parties; - elem = grpc_channel_stack_element(channel_stack_, 0); - elem->filter->start_transport_op(elem, op); -} +} // namespace -void ConnectedSubchannel::Ping(grpc_closure* on_initiate, - grpc_closure* on_ack) { - grpc_transport_op* op = grpc_make_transport_op(nullptr); - grpc_channel_element* elem; - op->send_ping.on_initiate = on_initiate; - op->send_ping.on_ack = on_ack; - elem = grpc_channel_stack_element(channel_stack_, 0); - elem->filter->start_transport_op(elem, op); +bool Subchannel::PublishTransportLocked() { + // Construct channel stack. + grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create(); + grpc_channel_stack_builder_set_channel_arguments( + builder, connecting_result_.channel_args); + grpc_channel_stack_builder_set_transport(builder, + connecting_result_.transport); + if (!grpc_channel_init_create_stack(builder, GRPC_CLIENT_SUBCHANNEL)) { + grpc_channel_stack_builder_destroy(builder); + return false; + } + grpc_channel_stack* stk; + grpc_error* error = grpc_channel_stack_builder_finish( + builder, 0, 1, ConnectionDestroy, nullptr, + reinterpret_cast(&stk)); + if (error != GRPC_ERROR_NONE) { + grpc_transport_destroy(connecting_result_.transport); + gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", + grpc_error_string(error)); + GRPC_ERROR_UNREF(error); + return false; + } + intptr_t socket_uuid = connecting_result_.socket_uuid; + memset(&connecting_result_, 0, sizeof(connecting_result_)); + if (disconnected_) { + grpc_channel_stack_destroy(stk); + gpr_free(stk); + return false; + } + // Publish. + connected_subchannel_.reset( + New(stk, args_, channelz_node_, socket_uuid)); + gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p", + connected_subchannel_.get(), this); + // Instantiate state watcher. Will clean itself up. + connected_subchannel_watcher_ = + MakeOrphanable(this); + return true; } -grpc_error* ConnectedSubchannel::CreateCall(const CallArgs& args, - grpc_subchannel_call** call) { - const size_t allocation_size = - GetInitialCallSizeEstimate(args.parent_data_size); - *call = new (gpr_arena_alloc(args.arena, allocation_size)) - grpc_subchannel_call(this, args); - grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call); - RefCountedPtr connection = - Ref(DEBUG_LOCATION, "subchannel_call"); - connection.release(); // Ref is passed to the grpc_subchannel_call object. - const grpc_call_element_args call_args = { - callstk, /* call_stack */ - nullptr, /* server_transport_data */ - args.context, /* context */ - args.path, /* path */ - args.start_time, /* start_time */ - args.deadline, /* deadline */ - args.arena, /* arena */ - args.call_combiner /* call_combiner */ - }; - grpc_error* error = grpc_call_stack_init( - channel_stack_, 1, subchannel_call_destroy, *call, &call_args); - if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { - const char* error_string = grpc_error_string(error); - gpr_log(GPR_ERROR, "error: %s", error_string); - return error; - } - grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); - if (channelz_subchannel_ != nullptr) { - channelz_subchannel_->RecordCallStarted(); +void Subchannel::Disconnect() { + // The subchannel_pool is only used once here in this subchannel, so the + // access can be outside of the lock. + if (subchannel_pool_ != nullptr) { + subchannel_pool_->UnregisterSubchannel(key_); + subchannel_pool_.reset(); } - return GRPC_ERROR_NONE; + MutexLock lock(&mu_); + GPR_ASSERT(!disconnected_); + disconnected_ = true; + grpc_connector_shutdown(connector_, GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Subchannel disconnected")); + connected_subchannel_.reset(); + connected_subchannel_watcher_.reset(); } -size_t ConnectedSubchannel::GetInitialCallSizeEstimate( - size_t parent_data_size) const { - size_t allocation_size = - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_subchannel_call)); - if (parent_data_size > 0) { - allocation_size += - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(channel_stack_->call_stack_size) + - parent_data_size; - } else { - allocation_size += channel_stack_->call_stack_size; +gpr_atm Subchannel::RefMutate( + gpr_atm delta, int barrier GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS) { + gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&ref_pair_, delta) + : gpr_atm_no_barrier_fetch_add(&ref_pair_, delta); +#ifndef NDEBUG + if (grpc_trace_stream_refcount.enabled()) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, + "SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", this, + purpose, old_val, old_val + delta, reason); } - return allocation_size; +#endif + return old_val; } } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index fac515eee5c..88282c9d95e 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -24,53 +24,49 @@ #include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/connector.h" #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" +#include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/gpr/arena.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/metadata.h" // Channel arg containing a grpc_resolved_address to connect to. #define GRPC_ARG_SUBCHANNEL_ADDRESS "grpc.subchannel_address" -/** A (sub-)channel that knows how to connect to exactly one target - address. Provides a target for load balancing. */ -typedef struct grpc_subchannel grpc_subchannel; -typedef struct grpc_subchannel_call grpc_subchannel_call; - +// For debugging refcounting. #ifndef NDEBUG -#define GRPC_SUBCHANNEL_REF(p, r) \ - grpc_subchannel_ref((p), __FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_REF(p, r) (p)->Ref(__FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \ - grpc_subchannel_ref_from_weak_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_UNREF(p, r) \ - grpc_subchannel_unref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_WEAK_REF(p, r) \ - grpc_subchannel_weak_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) \ - grpc_subchannel_weak_unref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_CALL_REF(p, r) \ - grpc_subchannel_call_ref((p), __FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_CALL_UNREF(p, r) \ - grpc_subchannel_call_unref((p), __FILE__, __LINE__, (r)) + (p)->RefFromWeakRef(__FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_UNREF(p, r) (p)->Unref(__FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_WEAK_REF(p, r) (p)->WeakRef(__FILE__, __LINE__, (r)) +#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) (p)->WeakUnref(__FILE__, __LINE__, (r)) #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS \ - , const char *file, int line, const char *reason + const char *file, int line, const char *reason +#define GRPC_SUBCHANNEL_REF_REASON reason +#define GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS \ + , GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char* purpose +#define GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE(x) , file, line, reason, x #else -#define GRPC_SUBCHANNEL_REF(p, r) grpc_subchannel_ref((p)) -#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \ - grpc_subchannel_ref_from_weak_ref((p)) -#define GRPC_SUBCHANNEL_UNREF(p, r) grpc_subchannel_unref((p)) -#define GRPC_SUBCHANNEL_WEAK_REF(p, r) grpc_subchannel_weak_ref((p)) -#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) grpc_subchannel_weak_unref((p)) -#define GRPC_SUBCHANNEL_CALL_REF(p, r) grpc_subchannel_call_ref((p)) -#define GRPC_SUBCHANNEL_CALL_UNREF(p, r) grpc_subchannel_call_unref((p)) +#define GRPC_SUBCHANNEL_REF(p, r) (p)->Ref() +#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) (p)->RefFromWeakRef() +#define GRPC_SUBCHANNEL_UNREF(p, r) (p)->Unref() +#define GRPC_SUBCHANNEL_WEAK_REF(p, r) (p)->WeakRef() +#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) (p)->WeakUnref() #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS +#define GRPC_SUBCHANNEL_REF_REASON "" +#define GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS +#define GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE(x) #endif namespace grpc_core { +class SubchannelCall; + class ConnectedSubchannel : public RefCounted { public: struct CallArgs { @@ -86,8 +82,7 @@ class ConnectedSubchannel : public RefCounted { ConnectedSubchannel( grpc_channel_stack* channel_stack, const grpc_channel_args* args, - grpc_core::RefCountedPtr - channelz_subchannel, + RefCountedPtr channelz_subchannel, intptr_t socket_uuid); ~ConnectedSubchannel(); @@ -95,7 +90,8 @@ class ConnectedSubchannel : public RefCounted { grpc_connectivity_state* state, grpc_closure* closure); void Ping(grpc_closure* on_initiate, grpc_closure* on_ack); - grpc_error* CreateCall(const CallArgs& args, grpc_subchannel_call** call); + RefCountedPtr CreateCall(const CallArgs& args, + grpc_error** error); grpc_channel_stack* channel_stack() const { return channel_stack_; } const grpc_channel_args* args() const { return args_; } @@ -111,91 +107,204 @@ class ConnectedSubchannel : public RefCounted { grpc_channel_args* args_; // ref counted pointer to the channelz node in this connected subchannel's // owning subchannel. - grpc_core::RefCountedPtr - channelz_subchannel_; + RefCountedPtr channelz_subchannel_; // uuid of this subchannel's socket. 0 if this subchannel is not connected. const intptr_t socket_uuid_; }; -} // namespace grpc_core +// Implements the interface of RefCounted<>. +class SubchannelCall { + public: + SubchannelCall(RefCountedPtr connected_subchannel, + const ConnectedSubchannel::CallArgs& args) + : connected_subchannel_(std::move(connected_subchannel)), + deadline_(args.deadline) {} + + // Continues processing a transport stream op batch. + void StartTransportStreamOpBatch(grpc_transport_stream_op_batch* batch); + + // Returns a pointer to the parent data associated with the subchannel call. + // The data will be of the size specified in \a parent_data_size field of + // the args passed to \a ConnectedSubchannel::CreateCall(). + void* GetParentData(); + + // Returns the call stack of the subchannel call. + grpc_call_stack* GetCallStack(); + + grpc_closure* after_call_stack_destroy() const { + return after_call_stack_destroy_; + } + + // Sets the 'then_schedule_closure' argument for call stack destruction. + // Must be called once per call. + void SetAfterCallStackDestroy(grpc_closure* closure); + + // Interface of RefCounted<>. + RefCountedPtr Ref() GRPC_MUST_USE_RESULT; + RefCountedPtr Ref(const DebugLocation& location, + const char* reason) GRPC_MUST_USE_RESULT; + // When refcount drops to 0, destroys itself and the associated call stack, + // but does NOT free the memory because it's in the call arena. + void Unref(); + void Unref(const DebugLocation& location, const char* reason); + + private: + // Allow RefCountedPtr<> to access IncrementRefCount(). + template + friend class RefCountedPtr; + + // If channelz is enabled, intercepts recv_trailing so that we may check the + // status and associate it to a subchannel. + void MaybeInterceptRecvTrailingMetadata( + grpc_transport_stream_op_batch* batch); + + static void RecvTrailingMetadataReady(void* arg, grpc_error* error); + + // Interface of RefCounted<>. + void IncrementRefCount(); + void IncrementRefCount(const DebugLocation& location, const char* reason); + + RefCountedPtr connected_subchannel_; + grpc_closure* after_call_stack_destroy_ = nullptr; + // State needed to support channelz interception of recv trailing metadata. + grpc_closure recv_trailing_metadata_ready_; + grpc_closure* original_recv_trailing_metadata_ = nullptr; + grpc_metadata_batch* recv_trailing_metadata_ = nullptr; + grpc_millis deadline_; +}; + +// A subchannel that knows how to connect to exactly one target address. It +// provides a target for load balancing. +class Subchannel { + public: + // The ctor and dtor are not intended to use directly. + Subchannel(SubchannelKey* key, grpc_connector* connector, + const grpc_channel_args* args); + ~Subchannel(); + + // Creates a subchannel given \a connector and \a args. + static Subchannel* Create(grpc_connector* connector, + const grpc_channel_args* args); + + // Strong and weak refcounting. + Subchannel* Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + void Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + Subchannel* WeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + void WeakUnref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + Subchannel* RefFromWeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); + + intptr_t GetChildSocketUuid(); -grpc_subchannel* grpc_subchannel_ref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -grpc_subchannel* grpc_subchannel_ref_from_weak_ref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -void grpc_subchannel_unref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -grpc_subchannel* grpc_subchannel_weak_ref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -void grpc_subchannel_weak_unref( - grpc_subchannel* channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -grpc_subchannel_call* grpc_subchannel_call_ref( - grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS); -void grpc_subchannel_call_unref( - grpc_subchannel_call* call GRPC_SUBCHANNEL_REF_EXTRA_ARGS); - -grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node( - grpc_subchannel* subchannel); - -intptr_t grpc_subchannel_get_child_socket_uuid(grpc_subchannel* subchannel); - -/** Returns a pointer to the parent data associated with \a subchannel_call. - The data will be of the size specified in \a parent_data_size - field of the args passed to \a grpc_connected_subchannel_create_call(). */ -void* grpc_connected_subchannel_call_get_parent_data( - grpc_subchannel_call* subchannel_call); - -/** poll the current connectivity state of a channel */ -grpc_connectivity_state grpc_subchannel_check_connectivity( - grpc_subchannel* channel, grpc_error** error, bool inhibit_health_checking); - -/** Calls notify when the connectivity state of a channel becomes different - from *state. Updates *state with the new state of the channel. */ -void grpc_subchannel_notify_on_state_change( - grpc_subchannel* channel, grpc_pollset_set* interested_parties, - grpc_connectivity_state* state, grpc_closure* notify, - bool inhibit_health_checks); - -/** retrieve the grpc_core::ConnectedSubchannel - or nullptr if not connected - * (which may happen before it initially connects or during transient failures) - * */ -grpc_core::RefCountedPtr -grpc_subchannel_get_connected_subchannel(grpc_subchannel* c); - -// Resets the connection backoff of the subchannel. -// TODO(roth): Move connection backoff out of subchannels and up into LB -// policy code (probably by adding a SubchannelGroup between -// SubchannelList and SubchannelData), at which point this method can -// go away. -void grpc_subchannel_reset_backoff(grpc_subchannel* subchannel); - -/** continue processing a transport op */ -void grpc_subchannel_call_process_op(grpc_subchannel_call* subchannel_call, - grpc_transport_stream_op_batch* op); - -/** Must be called once per call. Sets the 'then_schedule_closure' argument for - call stack destruction. */ -void grpc_subchannel_call_set_cleanup_closure( - grpc_subchannel_call* subchannel_call, grpc_closure* closure); - -grpc_call_stack* grpc_subchannel_call_get_call_stack( - grpc_subchannel_call* subchannel_call); - -/** create a subchannel given a connector */ -grpc_subchannel* grpc_subchannel_create(grpc_connector* connector, - const grpc_channel_args* args); - -/// Sets \a addr from \a args. -void grpc_get_subchannel_address_arg(const grpc_channel_args* args, - grpc_resolved_address* addr); - -const char* grpc_subchannel_get_target(grpc_subchannel* subchannel); - -/// Returns the URI string for the address to connect to. -const char* grpc_get_subchannel_address_uri_arg(const grpc_channel_args* args); - -/// Returns a new channel arg encoding the subchannel address as a string. -/// Caller is responsible for freeing the string. -grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr); + // Gets the string representing the subchannel address. + // Caller doesn't take ownership. + const char* GetTargetAddress(); + + // Gets the connected subchannel - or nullptr if not connected (which may + // happen before it initially connects or during transient failures). + RefCountedPtr connected_subchannel(); + + channelz::SubchannelNode* channelz_node(); + + // Polls the current connectivity state of the subchannel. + grpc_connectivity_state CheckConnectivity(grpc_error** error, + bool inhibit_health_checking); + + // When the connectivity state of the subchannel changes from \a *state, + // invokes \a notify and updates \a *state with the new state. + void NotifyOnStateChange(grpc_pollset_set* interested_parties, + grpc_connectivity_state* state, grpc_closure* notify, + bool inhibit_health_checks); + + // Resets the connection backoff of the subchannel. + // TODO(roth): Move connection backoff out of subchannels and up into LB + // policy code (probably by adding a SubchannelGroup between + // SubchannelList and SubchannelData), at which point this method can + // go away. + void ResetBackoff(); + + // Returns a new channel arg encoding the subchannel address as a URI + // string. Caller is responsible for freeing the string. + static grpc_arg CreateSubchannelAddressArg(const grpc_resolved_address* addr); + + // Returns the URI string from the subchannel address arg in \a args. + static const char* GetUriFromSubchannelAddressArg( + const grpc_channel_args* args); + + // Sets \a addr from the subchannel address arg in \a args. + static void GetAddressFromSubchannelAddressArg(const grpc_channel_args* args, + grpc_resolved_address* addr); + + private: + struct ExternalStateWatcher; + class ConnectedSubchannelStateWatcher; + + // Sets the subchannel's connectivity state to \a state. + void SetConnectivityStateLocked(grpc_connectivity_state state, + grpc_error* error, const char* reason); + + // Methods for connection. + void MaybeStartConnectingLocked(); + static void OnRetryAlarm(void* arg, grpc_error* error); + void ContinueConnectingLocked(); + static void OnConnectingFinished(void* arg, grpc_error* error); + bool PublishTransportLocked(); + void Disconnect(); + + gpr_atm RefMutate(gpr_atm delta, + int barrier GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS); + + // The subchannel pool this subchannel is in. + RefCountedPtr subchannel_pool_; + // TODO(juanlishen): Consider using args_ as key_ directly. + // Subchannel key that identifies this subchannel in the subchannel pool. + SubchannelKey* key_; + // Channel args. + grpc_channel_args* args_; + // pollset_set tracking who's interested in a connection being setup. + grpc_pollset_set* pollset_set_; + // Protects the other members. + gpr_mu mu_; + // Refcount + // - lower INTERNAL_REF_BITS bits are for internal references: + // these do not keep the subchannel open. + // - upper remaining bits are for public references: these do + // keep the subchannel open + gpr_atm ref_pair_; + + // Connection states. + grpc_connector* connector_ = nullptr; + // Set during connection. + grpc_connect_out_args connecting_result_; + grpc_closure on_connecting_finished_; + // Active connection, or null. + RefCountedPtr connected_subchannel_; + OrphanablePtr connected_subchannel_watcher_; + bool connecting_ = false; + bool disconnected_ = false; + + // Connectivity state tracking. + grpc_connectivity_state_tracker state_tracker_; + grpc_connectivity_state_tracker state_and_health_tracker_; + UniquePtr health_check_service_name_; + ExternalStateWatcher* external_state_watcher_list_ = nullptr; + + // Backoff state. + BackOff backoff_; + grpc_millis next_attempt_deadline_; + grpc_millis min_connect_timeout_ms_; + bool backoff_begun_ = false; + + // Retry alarm. + grpc_timer retry_alarm_; + grpc_closure on_retry_alarm_; + bool have_retry_alarm_ = false; + // reset_backoff() was called while alarm was pending. + bool retry_immediately_ = false; + + // Channelz tracking. + RefCountedPtr channelz_node_; +}; + +} // namespace grpc_core #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SUBCHANNEL_H */ diff --git a/src/core/ext/filters/client_channel/subchannel_pool_interface.h b/src/core/ext/filters/client_channel/subchannel_pool_interface.h index 21597bf4276..eeb56faf0c0 100644 --- a/src/core/ext/filters/client_channel/subchannel_pool_interface.h +++ b/src/core/ext/filters/client_channel/subchannel_pool_interface.h @@ -26,10 +26,10 @@ #include "src/core/lib/gprpp/abstract.h" #include "src/core/lib/gprpp/ref_counted.h" -struct grpc_subchannel; - namespace grpc_core { +class Subchannel; + extern TraceFlag grpc_subchannel_pool_trace; // A key that can uniquely identify a subchannel. @@ -69,15 +69,15 @@ class SubchannelPoolInterface : public RefCounted { // Registers a subchannel against a key. Returns the subchannel registered // with \a key, which may be different from \a constructed because we reuse // (instead of update) any existing subchannel already registered with \a key. - virtual grpc_subchannel* RegisterSubchannel( - SubchannelKey* key, grpc_subchannel* constructed) GRPC_ABSTRACT; + virtual Subchannel* RegisterSubchannel(SubchannelKey* key, + Subchannel* constructed) GRPC_ABSTRACT; // Removes the registered subchannel found by \a key. virtual void UnregisterSubchannel(SubchannelKey* key) GRPC_ABSTRACT; // Finds the subchannel registered for the given subchannel key. Returns NULL // if no such channel exists. Thread-safe. - virtual grpc_subchannel* FindSubchannel(SubchannelKey* key) GRPC_ABSTRACT; + virtual Subchannel* FindSubchannel(SubchannelKey* key) GRPC_ABSTRACT; // Creates a channel arg from \a subchannel pool. static grpc_arg CreateChannelArg(SubchannelPoolInterface* subchannel_pool); diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.cc b/src/core/ext/transport/chttp2/client/chttp2_connector.cc index 42a2e2e896c..1e9a75d0630 100644 --- a/src/core/ext/transport/chttp2/client/chttp2_connector.cc +++ b/src/core/ext/transport/chttp2/client/chttp2_connector.cc @@ -202,7 +202,8 @@ static void chttp2_connector_connect(grpc_connector* con, grpc_closure* notify) { chttp2_connector* c = reinterpret_cast(con); grpc_resolved_address addr; - grpc_get_subchannel_address_arg(args->channel_args, &addr); + grpc_core::Subchannel::GetAddressFromSubchannelAddressArg(args->channel_args, + &addr); gpr_mu_lock(&c->mu); GPR_ASSERT(c->notify == nullptr); c->notify = notify; 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 a5bf1bf21d4..8aabcfa2000 100644 --- a/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.cc @@ -39,11 +39,11 @@ static void client_channel_factory_ref( static void client_channel_factory_unref( grpc_client_channel_factory* cc_factory) {} -static grpc_subchannel* client_channel_factory_create_subchannel( +static grpc_core::Subchannel* client_channel_factory_create_subchannel( 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, new_args); + grpc_core::Subchannel* s = grpc_core::Subchannel::Create(connector, new_args); grpc_connector_unref(connector); 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 5985fa0cbdb..eb2fee2af91 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 @@ -76,7 +76,8 @@ static grpc_channel_args* get_secure_naming_channel_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); + const char* target_uri_str = + grpc_core::Subchannel::GetUriFromSubchannelAddressArg(args); grpc_uri* target_uri = grpc_uri_parse(target_uri_str, false /* suppress errors */); GPR_ASSERT(target_uri != nullptr); @@ -138,7 +139,7 @@ static grpc_channel_args* get_secure_naming_channel_args( return new_args; } -static grpc_subchannel* client_channel_factory_create_subchannel( +static grpc_core::Subchannel* client_channel_factory_create_subchannel( 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) { @@ -147,7 +148,7 @@ static grpc_subchannel* client_channel_factory_create_subchannel( return nullptr; } grpc_connector* connector = grpc_chttp2_connector_create(); - grpc_subchannel* s = grpc_subchannel_create(connector, new_args); + grpc_core::Subchannel* s = grpc_core::Subchannel::Create(connector, new_args); grpc_connector_unref(connector); grpc_channel_args_destroy(new_args); return s; diff --git a/test/core/util/debugger_macros.cc b/test/core/util/debugger_macros.cc index 05fb1461733..fed6ad97285 100644 --- a/test/core/util/debugger_macros.cc +++ b/test/core/util/debugger_macros.cc @@ -36,13 +36,14 @@ grpc_stream* grpc_transport_stream_from_call(grpc_call* call) { for (;;) { grpc_call_element* el = grpc_call_stack_element(cs, cs->count - 1); if (el->filter == &grpc_client_channel_filter) { - grpc_subchannel_call* scc = grpc_client_channel_get_subchannel_call(el); + grpc_core::RefCountedPtr scc = + grpc_client_channel_get_subchannel_call(el); if (scc == nullptr) { fprintf(stderr, "No subchannel-call"); fflush(stderr); return nullptr; } - cs = grpc_subchannel_call_get_call_stack(scc); + cs = scc->GetCallStack(); } else if (el->filter == &grpc_connected_filter) { return grpc_connected_channel_get_stream(el); } else { diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc index 125b1ce5c4e..973f47beaf7 100644 --- a/test/cpp/microbenchmarks/bm_call_create.cc +++ b/test/cpp/microbenchmarks/bm_call_create.cc @@ -325,8 +325,8 @@ class FakeClientChannelFactory : public grpc_client_channel_factory { private: 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_channel_args* args) { + static grpc_core::Subchannel* CreateSubchannel( + grpc_client_channel_factory* factory, const grpc_channel_args* args) { return nullptr; } static grpc_channel* CreateClientChannel(grpc_client_channel_factory* factory, From 452fb4a67b2efd50b1b4b83b7e2d04658b260b03 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Wed, 30 Jan 2019 15:10:51 -0800 Subject: [PATCH 112/218] Unify parameter name --- src/core/ext/filters/client_channel/subchannel.cc | 8 ++++---- src/core/ext/filters/client_channel/subchannel.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 70285659aad..1d188a655f8 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -731,10 +731,10 @@ channelz::SubchannelNode* Subchannel::channelz_node() { } grpc_connectivity_state Subchannel::CheckConnectivity( - grpc_error** error, bool inhibit_health_checks) { + grpc_error** error, bool inhibit_health_checking) { MutexLock lock(&mu_); grpc_connectivity_state_tracker* tracker = - inhibit_health_checks ? &state_tracker_ : &state_and_health_tracker_; + inhibit_health_checking ? &state_tracker_ : &state_and_health_tracker_; grpc_connectivity_state state = grpc_connectivity_state_get(tracker, error); return state; } @@ -742,9 +742,9 @@ grpc_connectivity_state Subchannel::CheckConnectivity( void Subchannel::NotifyOnStateChange(grpc_pollset_set* interested_parties, grpc_connectivity_state* state, grpc_closure* notify, - bool inhibit_health_checks) { + bool inhibit_health_checking) { grpc_connectivity_state_tracker* tracker = - inhibit_health_checks ? &state_tracker_ : &state_and_health_tracker_; + inhibit_health_checking ? &state_tracker_ : &state_and_health_tracker_; ExternalStateWatcher* w; if (state == nullptr) { MutexLock lock(&mu_); diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 88282c9d95e..47c21ff8680 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -213,7 +213,7 @@ class Subchannel { // invokes \a notify and updates \a *state with the new state. void NotifyOnStateChange(grpc_pollset_set* interested_parties, grpc_connectivity_state* state, grpc_closure* notify, - bool inhibit_health_checks); + bool inhibit_health_checking); // Resets the connection backoff of the subchannel. // TODO(roth): Move connection backoff out of subchannels and up into LB From 9b6389f05ab28ae416220fe55029f711436d3321 Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 30 Jan 2019 13:04:55 -0800 Subject: [PATCH 113/218] Handle null implementations --- src/compiler/csharp_generator.cc | 38 ++++++++++--- src/csharp/Grpc.Core/ServiceBinderBase.cs | 54 ++++++++++++++++++- src/csharp/Grpc.Examples/MathGrpc.cs | 13 ++--- src/csharp/Grpc.HealthCheck/HealthGrpc.cs | 9 ++-- .../BenchmarkServiceGrpc.cs | 15 +++--- .../EmptyServiceGrpc.cs | 5 +- .../Grpc.IntegrationTesting/MetricsGrpc.cs | 9 ++-- .../ReportQpsScenarioServiceGrpc.cs | 7 +-- .../Grpc.IntegrationTesting/TestGrpc.cs | 37 +++++++------ .../WorkerServiceGrpc.cs | 13 ++--- src/csharp/Grpc.Reflection/ReflectionGrpc.cs | 7 +-- 11 files changed, 147 insertions(+), 60 deletions(-) diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index 2a87463d2d0..ac0af336f93 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -199,6 +199,21 @@ std::string GetCSharpMethodType(MethodType method_type) { return ""; } +std::string GetCSharpServerMethodType(MethodType method_type) { + switch (method_type) { + case METHODTYPE_NO_STREAMING: + return "grpc::UnaryServerMethod"; + case METHODTYPE_CLIENT_STREAMING: + return "grpc::ClientStreamingServerMethod"; + case METHODTYPE_SERVER_STREAMING: + return "grpc::ServerStreamingServerMethod"; + case METHODTYPE_BIDI_STREAMING: + return "grpc::DuplexStreamingServerMethod"; + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return ""; +} + std::string GetServiceNameFieldName() { return "__ServiceName"; } std::string GetMarshallerFieldName(const Descriptor* message) { @@ -613,8 +628,8 @@ void GenerateBindServiceWithBinderMethod(Printer* out, const ServiceDescriptor* service) { out->Print( "/// Register service method with a service " - "binder without implementation. Useful when customizing the service " - "binding logic.\n" + "binder with or without implementation. Useful when customizing the " + "service binding logic.\n" "/// Note: this method is part of an experimental API that can change or " "be " "removed without any prior notice.\n"); @@ -623,15 +638,26 @@ void GenerateBindServiceWithBinderMethod(Printer* out, "calling AddMethod on this object." "\n"); out->Print( - "public static void BindService(grpc::ServiceBinderBase " - "serviceBinder)\n"); + "/// An object implementing the server-side" + " handling logic.\n"); + out->Print( + "public static void BindService(grpc::ServiceBinderBase serviceBinder, " + "$implclass$ " + "serviceImpl)\n", + "implclass", GetServerClassName(service)); out->Print("{\n"); out->Indent(); for (int i = 0; i < service->method_count(); i++) { const MethodDescriptor* method = service->method(i); - out->Print("serviceBinder.AddMethod($methodfield$);\n", "methodfield", - GetMethodFieldName(method)); + out->Print( + "serviceBinder.AddMethod($methodfield$, serviceImpl == null ? null : " + "new $servermethodtype$<$inputtype$, $outputtype$>(" + "serviceImpl.$methodname$));\n", + "methodfield", GetMethodFieldName(method), "servermethodtype", + GetCSharpServerMethodType(GetMethodType(method)), "inputtype", + GetClassName(method->input_type()), "outputtype", + GetClassName(method->output_type()), "methodname", method->name()); } out->Outdent(); diff --git a/src/csharp/Grpc.Core/ServiceBinderBase.cs b/src/csharp/Grpc.Core/ServiceBinderBase.cs index 318892cc5fb..d4909f4a269 100644 --- a/src/csharp/Grpc.Core/ServiceBinderBase.cs +++ b/src/csharp/Grpc.Core/ServiceBinderBase.cs @@ -35,13 +35,63 @@ namespace Grpc.Core public class ServiceBinderBase { /// - /// Adds a method without a handler. + /// Adds a definition for a single request - single response method. /// /// The request message class. /// The response message class. /// The method. + /// The method handler. public virtual void AddMethod( - Method method) + Method method, + UnaryServerMethod handler) + where TRequest : class + where TResponse : class + { + throw new NotImplementedException(); + } + + /// + /// Adds a definition for a client streaming method. + /// + /// The request message class. + /// The response message class. + /// The method. + /// The method handler. + public virtual void AddMethod( + Method method, + ClientStreamingServerMethod handler) + where TRequest : class + where TResponse : class + { + throw new NotImplementedException(); + } + + /// + /// Adds a definition for a server streaming method. + /// + /// The request message class. + /// The response message class. + /// The method. + /// The method handler. + public virtual void AddMethod( + Method method, + ServerStreamingServerMethod handler) + where TRequest : class + where TResponse : class + { + throw new NotImplementedException(); + } + + /// + /// Adds a definition for a bidirectional streaming method. + /// + /// The request message class. + /// The response message class. + /// The method. + /// The method handler. + public virtual void AddMethod( + Method method, + DuplexStreamingServerMethod handler) where TRequest : class where TResponse : class { diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index 85436ddc232..acd70b3714d 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -287,15 +287,16 @@ namespace Math { .AddMethod(__Method_Sum, serviceImpl.Sum).Build(); } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. - public static void BindService(grpc::ServiceBinderBase serviceBinder) + /// An object implementing the server-side handling logic. + public static void BindService(grpc::ServiceBinderBase serviceBinder, MathBase serviceImpl) { - serviceBinder.AddMethod(__Method_Div); - serviceBinder.AddMethod(__Method_DivMany); - serviceBinder.AddMethod(__Method_Fib); - serviceBinder.AddMethod(__Method_Sum); + serviceBinder.AddMethod(__Method_Div, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.Div)); + serviceBinder.AddMethod(__Method_DivMany, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.DivMany)); + serviceBinder.AddMethod(__Method_Fib, serviceImpl == null ? null : new grpc::ServerStreamingServerMethod(serviceImpl.Fib)); + serviceBinder.AddMethod(__Method_Sum, serviceImpl == null ? null : new grpc::ClientStreamingServerMethod(serviceImpl.Sum)); } } diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs index 5492600da9b..e13b1147cf8 100644 --- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs +++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs @@ -233,13 +233,14 @@ namespace Grpc.Health.V1 { .AddMethod(__Method_Watch, serviceImpl.Watch).Build(); } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. - public static void BindService(grpc::ServiceBinderBase serviceBinder) + /// An object implementing the server-side handling logic. + public static void BindService(grpc::ServiceBinderBase serviceBinder, HealthBase serviceImpl) { - serviceBinder.AddMethod(__Method_Check); - serviceBinder.AddMethod(__Method_Watch); + serviceBinder.AddMethod(__Method_Check, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.Check)); + serviceBinder.AddMethod(__Method_Watch, serviceImpl == null ? null : new grpc::ServerStreamingServerMethod(serviceImpl.Watch)); } } diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs index fcd0e3f89b3..5f18ba7accf 100644 --- a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs @@ -324,16 +324,17 @@ namespace Grpc.Testing { .AddMethod(__Method_StreamingBothWays, serviceImpl.StreamingBothWays).Build(); } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. - public static void BindService(grpc::ServiceBinderBase serviceBinder) + /// An object implementing the server-side handling logic. + public static void BindService(grpc::ServiceBinderBase serviceBinder, BenchmarkServiceBase serviceImpl) { - serviceBinder.AddMethod(__Method_UnaryCall); - serviceBinder.AddMethod(__Method_StreamingCall); - serviceBinder.AddMethod(__Method_StreamingFromClient); - serviceBinder.AddMethod(__Method_StreamingFromServer); - serviceBinder.AddMethod(__Method_StreamingBothWays); + serviceBinder.AddMethod(__Method_UnaryCall, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.UnaryCall)); + serviceBinder.AddMethod(__Method_StreamingCall, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.StreamingCall)); + serviceBinder.AddMethod(__Method_StreamingFromClient, serviceImpl == null ? null : new grpc::ClientStreamingServerMethod(serviceImpl.StreamingFromClient)); + serviceBinder.AddMethod(__Method_StreamingFromServer, serviceImpl == null ? null : new grpc::ServerStreamingServerMethod(serviceImpl.StreamingFromServer)); + serviceBinder.AddMethod(__Method_StreamingBothWays, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.StreamingBothWays)); } } diff --git a/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs index ba74c3a6016..01af6c24f41 100644 --- a/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs @@ -80,10 +80,11 @@ namespace Grpc.Testing { return grpc::ServerServiceDefinition.CreateBuilder().Build(); } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. - public static void BindService(grpc::ServiceBinderBase serviceBinder) + /// An object implementing the server-side handling logic. + public static void BindService(grpc::ServiceBinderBase serviceBinder, EmptyServiceBase serviceImpl) { } diff --git a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs index bc6ddf21f70..7b5b1a3aa7f 100644 --- a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs @@ -193,13 +193,14 @@ namespace Grpc.Testing { .AddMethod(__Method_GetGauge, serviceImpl.GetGauge).Build(); } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. - public static void BindService(grpc::ServiceBinderBase serviceBinder) + /// An object implementing the server-side handling logic. + public static void BindService(grpc::ServiceBinderBase serviceBinder, MetricsServiceBase serviceImpl) { - serviceBinder.AddMethod(__Method_GetAllGauges); - serviceBinder.AddMethod(__Method_GetGauge); + serviceBinder.AddMethod(__Method_GetAllGauges, serviceImpl == null ? null : new grpc::ServerStreamingServerMethod(serviceImpl.GetAllGauges)); + serviceBinder.AddMethod(__Method_GetGauge, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.GetGauge)); } } diff --git a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs index 096eb7e1d4b..04bb9c29d63 100644 --- a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs @@ -143,12 +143,13 @@ namespace Grpc.Testing { .AddMethod(__Method_ReportScenario, serviceImpl.ReportScenario).Build(); } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. - public static void BindService(grpc::ServiceBinderBase serviceBinder) + /// An object implementing the server-side handling logic. + public static void BindService(grpc::ServiceBinderBase serviceBinder, ReportQpsScenarioServiceBase serviceImpl) { - serviceBinder.AddMethod(__Method_ReportScenario); + serviceBinder.AddMethod(__Method_ReportScenario, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.ReportScenario)); } } diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index c8760583177..05e1e3ccc7d 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -539,19 +539,20 @@ namespace Grpc.Testing { .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build(); } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. - public static void BindService(grpc::ServiceBinderBase serviceBinder) + /// An object implementing the server-side handling logic. + public static void BindService(grpc::ServiceBinderBase serviceBinder, TestServiceBase serviceImpl) { - serviceBinder.AddMethod(__Method_EmptyCall); - serviceBinder.AddMethod(__Method_UnaryCall); - serviceBinder.AddMethod(__Method_CacheableUnaryCall); - serviceBinder.AddMethod(__Method_StreamingOutputCall); - serviceBinder.AddMethod(__Method_StreamingInputCall); - serviceBinder.AddMethod(__Method_FullDuplexCall); - serviceBinder.AddMethod(__Method_HalfDuplexCall); - serviceBinder.AddMethod(__Method_UnimplementedCall); + serviceBinder.AddMethod(__Method_EmptyCall, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.EmptyCall)); + serviceBinder.AddMethod(__Method_UnaryCall, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.UnaryCall)); + serviceBinder.AddMethod(__Method_CacheableUnaryCall, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.CacheableUnaryCall)); + serviceBinder.AddMethod(__Method_StreamingOutputCall, serviceImpl == null ? null : new grpc::ServerStreamingServerMethod(serviceImpl.StreamingOutputCall)); + serviceBinder.AddMethod(__Method_StreamingInputCall, serviceImpl == null ? null : new grpc::ClientStreamingServerMethod(serviceImpl.StreamingInputCall)); + serviceBinder.AddMethod(__Method_FullDuplexCall, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.FullDuplexCall)); + serviceBinder.AddMethod(__Method_HalfDuplexCall, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.HalfDuplexCall)); + serviceBinder.AddMethod(__Method_UnimplementedCall, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.UnimplementedCall)); } } @@ -676,12 +677,13 @@ namespace Grpc.Testing { .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build(); } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. - public static void BindService(grpc::ServiceBinderBase serviceBinder) + /// An object implementing the server-side handling logic. + public static void BindService(grpc::ServiceBinderBase serviceBinder, UnimplementedServiceBase serviceImpl) { - serviceBinder.AddMethod(__Method_UnimplementedCall); + serviceBinder.AddMethod(__Method_UnimplementedCall, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.UnimplementedCall)); } } @@ -802,13 +804,14 @@ namespace Grpc.Testing { .AddMethod(__Method_Stop, serviceImpl.Stop).Build(); } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. - public static void BindService(grpc::ServiceBinderBase serviceBinder) + /// An object implementing the server-side handling logic. + public static void BindService(grpc::ServiceBinderBase serviceBinder, ReconnectServiceBase serviceImpl) { - serviceBinder.AddMethod(__Method_Start); - serviceBinder.AddMethod(__Method_Stop); + serviceBinder.AddMethod(__Method_Start, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.Start)); + serviceBinder.AddMethod(__Method_Stop, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.Stop)); } } diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs index 7b2a9e8d481..a36f1d7a356 100644 --- a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs @@ -321,15 +321,16 @@ namespace Grpc.Testing { .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build(); } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. - public static void BindService(grpc::ServiceBinderBase serviceBinder) + /// An object implementing the server-side handling logic. + public static void BindService(grpc::ServiceBinderBase serviceBinder, WorkerServiceBase serviceImpl) { - serviceBinder.AddMethod(__Method_RunServer); - serviceBinder.AddMethod(__Method_RunClient); - serviceBinder.AddMethod(__Method_CoreCount); - serviceBinder.AddMethod(__Method_QuitWorker); + serviceBinder.AddMethod(__Method_RunServer, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.RunServer)); + serviceBinder.AddMethod(__Method_RunClient, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.RunClient)); + serviceBinder.AddMethod(__Method_CoreCount, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.CoreCount)); + serviceBinder.AddMethod(__Method_QuitWorker, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.QuitWorker)); } } diff --git a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs index 6c391361bc5..0b2bb2341b9 100644 --- a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs +++ b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs @@ -123,12 +123,13 @@ namespace Grpc.Reflection.V1Alpha { .AddMethod(__Method_ServerReflectionInfo, serviceImpl.ServerReflectionInfo).Build(); } - /// Register service method with a service binder without implementation. Useful when customizing the service binding logic. + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. /// Service methods will be bound by calling AddMethod on this object. - public static void BindService(grpc::ServiceBinderBase serviceBinder) + /// An object implementing the server-side handling logic. + public static void BindService(grpc::ServiceBinderBase serviceBinder, ServerReflectionBase serviceImpl) { - serviceBinder.AddMethod(__Method_ServerReflectionInfo); + serviceBinder.AddMethod(__Method_ServerReflectionInfo, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.ServerReflectionInfo)); } } From 9e652ebb2f1b2d8234a42b3add313da6f8748028 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 31 Jan 2019 11:52:18 +0100 Subject: [PATCH 114/218] review comments --- src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj | 2 +- src/csharp/Grpc.Core.Api/Properties/AssemblyInfo.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj b/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj index 6ad1ac85ffc..0dc73576bf5 100755 --- a/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj +++ b/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj @@ -4,7 +4,7 @@ - Copyright 2015, Google Inc. + Copyright 2019, Google Inc. gRPC C# Surface API $(GrpcCsharpVersion) Google Inc. diff --git a/src/csharp/Grpc.Core.Api/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core.Api/Properties/AssemblyInfo.cs index fa04d9328d4..ad38569908e 100644 --- a/src/csharp/Grpc.Core.Api/Properties/AssemblyInfo.cs +++ b/src/csharp/Grpc.Core.Api/Properties/AssemblyInfo.cs @@ -1,6 +1,6 @@ #region Copyright notice and license -// Copyright 2018 The gRPC Authors +// Copyright 2019 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. From c4e59973a24ac6a2f426190398eefb0763e9dc3d Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 31 Jan 2019 10:25:27 +0100 Subject: [PATCH 115/218] refactor ServerServiceDefinition and move to Grpc.Core.Api --- .../ServerServiceDefinition.cs | 41 +++++----- .../ServiceBinderBase.cs | 3 - src/csharp/Grpc.Core/ForwardedTypes.cs | 3 +- .../ServerServiceDefinitionExtensions.cs | 2 +- .../ServerServiceDefinitionExtensions.cs | 78 +++++++++++++++++++ src/csharp/Grpc.Core/Server.cs | 2 +- 6 files changed, 105 insertions(+), 24 deletions(-) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/ServerServiceDefinition.cs (74%) rename src/csharp/{Grpc.Core => Grpc.Core.Api}/ServiceBinderBase.cs (97%) create mode 100644 src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs diff --git a/src/csharp/Grpc.Core/ServerServiceDefinition.cs b/src/csharp/Grpc.Core.Api/ServerServiceDefinition.cs similarity index 74% rename from src/csharp/Grpc.Core/ServerServiceDefinition.cs rename to src/csharp/Grpc.Core.Api/ServerServiceDefinition.cs index b040ab379c8..8c76f0bcc97 100644 --- a/src/csharp/Grpc.Core/ServerServiceDefinition.cs +++ b/src/csharp/Grpc.Core.Api/ServerServiceDefinition.cs @@ -18,33 +18,31 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using Grpc.Core.Interceptors; -using Grpc.Core.Internal; -using Grpc.Core.Utils; namespace Grpc.Core { /// - /// Mapping of method names to server call handlers. + /// Stores mapping of methods to server call handlers. /// Normally, the ServerServiceDefinition objects will be created by the BindService factory method /// that is part of the autogenerated code for a protocol buffers service definition. /// public class ServerServiceDefinition { - readonly ReadOnlyDictionary callHandlers; + readonly IReadOnlyList> addMethodActions; - internal ServerServiceDefinition(Dictionary callHandlers) + internal ServerServiceDefinition(List> addMethodActions) { - this.callHandlers = new ReadOnlyDictionary(callHandlers); + this.addMethodActions = addMethodActions.AsReadOnly(); } - internal IDictionary CallHandlers + /// + /// Forwards all the previously stored AddMethod calls to the service binder. + /// + internal void BindService(ServiceBinderBase serviceBinder) { - get + foreach (var addMethodAction in addMethodActions) { - return this.callHandlers; + addMethodAction(serviceBinder); } } @@ -62,7 +60,10 @@ namespace Grpc.Core /// public class Builder { - readonly Dictionary callHandlers = new Dictionary(); + // to maintain legacy behavior, we need to detect duplicate keys and throw the same exception as before + readonly Dictionary duplicateDetector = new Dictionary(); + // for each AddMethod call, we store an action that will later register the method and handler with ServiceBinderBase + readonly List> addMethodActions = new List>(); /// /// Creates a new instance of builder. @@ -85,7 +86,8 @@ namespace Grpc.Core where TRequest : class where TResponse : class { - callHandlers.Add(method.FullName, ServerCalls.UnaryCall(method, handler)); + duplicateDetector.Add(method.FullName, null); + addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); return this; } @@ -103,7 +105,8 @@ namespace Grpc.Core where TRequest : class where TResponse : class { - callHandlers.Add(method.FullName, ServerCalls.ClientStreamingCall(method, handler)); + duplicateDetector.Add(method.FullName, null); + addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); return this; } @@ -121,7 +124,8 @@ namespace Grpc.Core where TRequest : class where TResponse : class { - callHandlers.Add(method.FullName, ServerCalls.ServerStreamingCall(method, handler)); + duplicateDetector.Add(method.FullName, null); + addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); return this; } @@ -139,7 +143,8 @@ namespace Grpc.Core where TRequest : class where TResponse : class { - callHandlers.Add(method.FullName, ServerCalls.DuplexStreamingCall(method, handler)); + duplicateDetector.Add(method.FullName, null); + addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); return this; } @@ -149,7 +154,7 @@ namespace Grpc.Core /// The ServerServiceDefinition object. public ServerServiceDefinition Build() { - return new ServerServiceDefinition(callHandlers); + return new ServerServiceDefinition(addMethodActions); } } } diff --git a/src/csharp/Grpc.Core/ServiceBinderBase.cs b/src/csharp/Grpc.Core.Api/ServiceBinderBase.cs similarity index 97% rename from src/csharp/Grpc.Core/ServiceBinderBase.cs rename to src/csharp/Grpc.Core.Api/ServiceBinderBase.cs index d4909f4a269..074bfae1ea0 100644 --- a/src/csharp/Grpc.Core/ServiceBinderBase.cs +++ b/src/csharp/Grpc.Core.Api/ServiceBinderBase.cs @@ -20,8 +20,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using Grpc.Core.Interceptors; -using Grpc.Core.Internal; using Grpc.Core.Utils; namespace Grpc.Core @@ -30,7 +28,6 @@ namespace Grpc.Core /// Allows binding server-side method implementations in alternative serving stacks. /// Instances of this class are usually populated by the BindService method /// that is part of the autogenerated code for a protocol buffers service definition. - /// /// public class ServiceBinderBase { diff --git a/src/csharp/Grpc.Core/ForwardedTypes.cs b/src/csharp/Grpc.Core/ForwardedTypes.cs index 8e104fd410d..e17696a626f 100644 --- a/src/csharp/Grpc.Core/ForwardedTypes.cs +++ b/src/csharp/Grpc.Core/ForwardedTypes.cs @@ -25,7 +25,6 @@ using Grpc.Core.Utils; // https://docs.microsoft.com/en-us/dotnet/framework/app-domains/type-forwarding-in-the-common-language-runtime // TODO(jtattermusch): move types needed for implementing a client -// TODO(jtattermusch): ServerServiceDefinition depends on IServerCallHandler (which depends on other stuff) [assembly:TypeForwardedToAttribute(typeof(ILogger))] [assembly:TypeForwardedToAttribute(typeof(LogLevel))] @@ -50,6 +49,8 @@ using Grpc.Core.Utils; [assembly:TypeForwardedToAttribute(typeof(ClientStreamingServerMethod<,>))] [assembly:TypeForwardedToAttribute(typeof(ServerStreamingServerMethod<,>))] [assembly:TypeForwardedToAttribute(typeof(DuplexStreamingServerMethod<,>))] +[assembly:TypeForwardedToAttribute(typeof(ServerServiceDefinition))] +[assembly:TypeForwardedToAttribute(typeof(ServiceBinderBase))] [assembly:TypeForwardedToAttribute(typeof(Status))] [assembly:TypeForwardedToAttribute(typeof(StatusCode))] [assembly:TypeForwardedToAttribute(typeof(WriteOptions))] diff --git a/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs b/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs index 56ead8a6a15..36eb08cf528 100644 --- a/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs +++ b/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs @@ -44,7 +44,7 @@ namespace Grpc.Core.Interceptors { GrpcPreconditions.CheckNotNull(serverServiceDefinition, nameof(serverServiceDefinition)); GrpcPreconditions.CheckNotNull(interceptor, nameof(interceptor)); - return new ServerServiceDefinition(serverServiceDefinition.CallHandlers.ToDictionary(x => x.Key, x => x.Value.Intercept(interceptor))); + return new ServerServiceDefinition(serverServiceDefinition.GetCallHandlers().ToDictionary(x => x.Key, x => x.Value.Intercept(interceptor))); } /// diff --git a/src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs b/src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs new file mode 100644 index 00000000000..d79b5007e87 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs @@ -0,0 +1,78 @@ +#region Copyright notice and license + +// Copyright 2019 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. + +#endregion + +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Grpc.Core.Internal; + +namespace Grpc.Core +{ + internal static class ServerServiceDefinitionExtensions + { + /// + /// Maps methods from ServerServiceDefinition to server call handlers. + /// + internal static ReadOnlyDictionary GetCallHandlers(this ServerServiceDefinition serviceDefinition) + { + var binder = new DefaultServiceBinder(); + serviceDefinition.BindService(binder); + return binder.GetCallHandlers(); + } + + /// + /// Helper for converting ServerServiceDefinition to server call handlers. + /// + private class DefaultServiceBinder : ServiceBinderBase + { + readonly Dictionary callHandlers = new Dictionary(); + + internal ReadOnlyDictionary GetCallHandlers() + { + return new ReadOnlyDictionary(this.callHandlers); + } + + public override void AddMethod( + Method method, + UnaryServerMethod handler) + { + callHandlers.Add(method.FullName, ServerCalls.UnaryCall(method, handler)); + } + + public override void AddMethod( + Method method, + ClientStreamingServerMethod handler) + { + callHandlers.Add(method.FullName, ServerCalls.ClientStreamingCall(method, handler)); + } + + public override void AddMethod( + Method method, + ServerStreamingServerMethod handler) + { + callHandlers.Add(method.FullName, ServerCalls.ServerStreamingCall(method, handler)); + } + + public override void AddMethod( + Method method, + DuplexStreamingServerMethod handler) + { + callHandlers.Add(method.FullName, ServerCalls.DuplexStreamingCall(method, handler)); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs index 64bb407c57f..26d182ae53b 100644 --- a/src/csharp/Grpc.Core/Server.cs +++ b/src/csharp/Grpc.Core/Server.cs @@ -257,7 +257,7 @@ namespace Grpc.Core lock (myLock) { GrpcPreconditions.CheckState(!startRequested); - foreach (var entry in serviceDefinition.CallHandlers) + foreach (var entry in serviceDefinition.GetCallHandlers()) { callHandlers.Add(entry.Key, entry.Value); } From 83a3b3b382d465575c93a51326fa5d80d6ae574c Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 31 Jan 2019 11:35:59 +0100 Subject: [PATCH 116/218] fix ServerServiceDefinition interception --- .../ServerServiceDefinitionExtensions.cs | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs b/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs index 36eb08cf528..321cf080faa 100644 --- a/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs +++ b/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs @@ -44,7 +44,10 @@ namespace Grpc.Core.Interceptors { GrpcPreconditions.CheckNotNull(serverServiceDefinition, nameof(serverServiceDefinition)); GrpcPreconditions.CheckNotNull(interceptor, nameof(interceptor)); - return new ServerServiceDefinition(serverServiceDefinition.GetCallHandlers().ToDictionary(x => x.Key, x => x.Value.Intercept(interceptor))); + + var binder = new InterceptingServiceBinder(interceptor); + serverServiceDefinition.BindService(binder); + return binder.GetInterceptedServerServiceDefinition(); } /// @@ -75,5 +78,52 @@ namespace Grpc.Core.Interceptors return serverServiceDefinition; } + + /// + /// Helper for creating ServerServiceDefinition with intercepted handlers. + /// + private class InterceptingServiceBinder : ServiceBinderBase + { + readonly ServerServiceDefinition.Builder builder = ServerServiceDefinition.CreateBuilder(); + readonly Interceptor interceptor; + + public InterceptingServiceBinder(Interceptor interceptor) + { + this.interceptor = GrpcPreconditions.CheckNotNull(interceptor, nameof(interceptor)); + } + + internal ServerServiceDefinition GetInterceptedServerServiceDefinition() + { + return builder.Build(); + } + + public override void AddMethod( + Method method, + UnaryServerMethod handler) + { + builder.AddMethod(method, (request, context) => interceptor.UnaryServerHandler(request, context, handler)); + } + + public override void AddMethod( + Method method, + ClientStreamingServerMethod handler) + { + builder.AddMethod(method, (requestStream, context) => interceptor.ClientStreamingServerHandler(requestStream, context, handler)); + } + + public override void AddMethod( + Method method, + ServerStreamingServerMethod handler) + { + builder.AddMethod(method, (request, responseStream, context) => interceptor.ServerStreamingServerHandler(request, responseStream, context, handler)); + } + + public override void AddMethod( + Method method, + DuplexStreamingServerMethod handler) + { + builder.AddMethod(method, (requestStream, responseStream, context) => interceptor.DuplexStreamingServerHandler(requestStream, responseStream, context, handler)); + } + } } } From 8a33ae4c520d9dd7fed6e6777b86e5613307ed60 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 31 Jan 2019 11:42:43 +0100 Subject: [PATCH 117/218] simplify IServerCallHandler --- .../Grpc.Core/Internal/ServerCallHandler.cs | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs index c3859f1de27..0c9297413c3 100644 --- a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs +++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs @@ -31,7 +31,6 @@ namespace Grpc.Core.Internal internal interface IServerCallHandler { Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq); - IServerCallHandler Intercept(Interceptor interceptor); } internal class UnaryServerCallHandler : IServerCallHandler @@ -91,11 +90,6 @@ namespace Grpc.Core.Internal } await finishedTask.ConfigureAwait(false); } - - public IServerCallHandler Intercept(Interceptor interceptor) - { - return new UnaryServerCallHandler(method, (request, context) => interceptor.UnaryServerHandler(request, context, handler)); - } } internal class ServerStreamingServerCallHandler : IServerCallHandler @@ -154,11 +148,6 @@ namespace Grpc.Core.Internal } await finishedTask.ConfigureAwait(false); } - - public IServerCallHandler Intercept(Interceptor interceptor) - { - return new ServerStreamingServerCallHandler(method, (request, responseStream, context) => interceptor.ServerStreamingServerHandler(request, responseStream, context, handler)); - } } internal class ClientStreamingServerCallHandler : IServerCallHandler @@ -217,11 +206,6 @@ namespace Grpc.Core.Internal } await finishedTask.ConfigureAwait(false); } - - public IServerCallHandler Intercept(Interceptor interceptor) - { - return new ClientStreamingServerCallHandler(method, (requestStream, context) => interceptor.ClientStreamingServerHandler(requestStream, context, handler)); - } } internal class DuplexStreamingServerCallHandler : IServerCallHandler @@ -277,11 +261,6 @@ namespace Grpc.Core.Internal } await finishedTask.ConfigureAwait(false); } - - public IServerCallHandler Intercept(Interceptor interceptor) - { - return new DuplexStreamingServerCallHandler(method, (requestStream, responseStream, context) => interceptor.DuplexStreamingServerHandler(requestStream, responseStream, context, handler)); - } } internal class UnimplementedMethodCallHandler : IServerCallHandler @@ -310,11 +289,6 @@ namespace Grpc.Core.Internal { return callHandlerImpl.HandleCall(newRpc, cq); } - - public IServerCallHandler Intercept(Interceptor interceptor) - { - return this; // Do not intercept unimplemented methods. - } } internal static class HandlerUtils From d8f2e99167ad73f46d9a4af8543945044b4440d4 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 31 Jan 2019 15:58:30 +0100 Subject: [PATCH 118/218] Increase VM timeout for grpc_ios_binary_size job --- tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg b/tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg index dc35ce81ffd..f639b4ef77c 100644 --- a/tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg +++ b/tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg @@ -16,7 +16,7 @@ # Location of the continuous shell script in repository. build_file: "grpc/tools/internal_ci/macos/grpc_ios_binary_size.sh" -timeout_mins: 60 +timeout_mins: 90 before_action { fetch_keystore { keystore_resource { From 5a382a3b59ddb2331ed4b8521ef9abbb551506f2 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Sat, 26 Jan 2019 17:42:02 -0500 Subject: [PATCH 119/218] Introduce weak and nonline attribute. This will be used to mark symbols such as nallocx as weak and replace with better implementation when available. --- include/grpc/impl/codegen/port_platform.h | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index aaeb23694e8..358e444e890 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -520,6 +520,35 @@ typedef unsigned __int64 uint64_t; #define CENSUSAPI GRPCAPI #endif +#ifndef GPR_HAS_ATTRIBUTE +#ifdef __has_attribute +#define GPR_HAS_ATTRIBUTE(a) __has_attribute(a) +#else +#define GPR_HAS_ATTRIBUTE(a) 0 +#endif +#endif /* GPR_HAS_ATTRIBUTE */ + +#ifndef GPR_ATTRIBUTE_NOINLINE +#if GPR_HAS_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) +#define GPR_ATTRIBUTE_NOINLINE __attribute__((noinline)) +#define GPR_HAS_ATTRIBUTE_NOINLINE 1 +#else +#define GPR_ATTRIBUTE_NOINLINE +#endif +#endif /* GPR_ATTRIBUTE_NOINLINE */ + +#ifndef GPR_ATTRIBUTE_WEAK +/* Attribute weak is broken on LLVM/windows: + * https://bugs.llvm.org/show_bug.cgi?id=37598 */ +#if (GPR_HAS_ATTRIBUTE(weak) || (defined(__GNUC__) && !defined(__clang__))) && \ + !(defined(__llvm__) && defined(_WIN32)) +#define GPR_ATTRIBUTE_WEAK __attribute__((weak)) +#define GPR_HAS_ATTRIBUTE_WEAK 1 +#else +#define GPR_ATTRIBUTE_WEAK +#endif +#endif /* GPR_ATTRIBUTE_WEAK */ + #ifndef GPR_ATTRIBUTE_NO_TSAN /* (1) */ #if defined(__has_feature) #if __has_feature(thread_sanitizer) From a4f8534a98748a0d29a8cfd93edcf8af2481f106 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Thu, 31 Jan 2019 10:45:02 -0800 Subject: [PATCH 120/218] Unref watcher after releasing lock --- .../ext/filters/client_channel/subchannel.cc | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 1d188a655f8..4276df3067f 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -405,18 +405,22 @@ class Subchannel::ConnectedSubchannelStateWatcher static void OnHealthChanged(void* arg, grpc_error* error) { auto* self = static_cast(arg); Subchannel* c = self->subchannel_; - MutexLock lock(&c->mu_); - if (self->health_state_ == GRPC_CHANNEL_SHUTDOWN) { - self->Unref(); - return; - } - if (self->last_connectivity_state_ == GRPC_CHANNEL_READY) { - grpc_connectivity_state_set(&c->state_and_health_tracker_, - self->health_state_, GRPC_ERROR_REF(error), - "health_changed"); + { + MutexLock lock(&c->mu_); + if (self->health_state_ != GRPC_CHANNEL_SHUTDOWN) { + if (self->last_connectivity_state_ == GRPC_CHANNEL_READY) { + grpc_connectivity_state_set(&c->state_and_health_tracker_, + self->health_state_, + GRPC_ERROR_REF(error), "health_changed"); + } + self->health_check_client_->NotifyOnHealthChange( + &self->health_state_, &self->on_health_changed_); + self = nullptr; // So we don't unref below. + } } - self->health_check_client_->NotifyOnHealthChange(&self->health_state_, - &self->on_health_changed_); + // Don't unref until we've released the lock, because this might + // cause the subchannel (which contains the lock) to be destroyed. + if (self != nullptr) self->Unref(); } Subchannel* subchannel_; From 8c02418caa84d938964f2c441b7ff565eedefc06 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 31 Jan 2019 11:55:42 -0800 Subject: [PATCH 121/218] Reset keepalive timer on reading bytes --- src/core/ext/transport/chttp2/transport/chttp2_transport.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index c2b57ed2905..a0ca89ec510 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -2554,6 +2554,10 @@ static void read_action_locked(void* tp, grpc_error* error) { } else if (t->closed_with_error == GRPC_ERROR_NONE) { keep_reading = true; GRPC_CHTTP2_REF_TRANSPORT(t, "keep_reading"); + /* Since we have read a byte, reset the keepalive timer */ + if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING) { + grpc_timer_cancel(&t->keepalive_ping_timer); + } } grpc_slice_buffer_reset_and_unref_internal(&t->read_buffer); From c372768feeef4991800b09607409f4af546a3684 Mon Sep 17 00:00:00 2001 From: Lidi Zheng Date: Thu, 31 Jan 2019 12:10:43 -0800 Subject: [PATCH 122/218] Install Bazel using its installation script --- templates/tools/dockerfile/bazel.include | 5 +++-- .../tools/dockerfile/test/sanity/Dockerfile.template | 1 + tools/dockerfile/test/bazel/Dockerfile | 5 +++-- tools/dockerfile/test/sanity/Dockerfile | 8 ++++++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/templates/tools/dockerfile/bazel.include b/templates/tools/dockerfile/bazel.include index c7714f56630..62d68607453 100644 --- a/templates/tools/dockerfile/bazel.include +++ b/templates/tools/dockerfile/bazel.include @@ -2,5 +2,6 @@ # Bazel installation RUN apt-get update && apt-get install -y wget && apt-get clean -RUN wget -q https://github.com/bazelbuild/bazel/releases/download/0.17.1/bazel-0.17.1-linux-x86_64 -O /usr/local/bin/bazel -RUN chmod 755 /usr/local/bin/bazel +RUN wget https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-installer-linux-x86_64.sh && ${'\\'} + bash ./bazel-0.20.0-installer-linux-x86_64.sh && ${'\\'} + rm bazel-0.20.0-installer-linux-x86_64.sh diff --git a/templates/tools/dockerfile/test/sanity/Dockerfile.template b/templates/tools/dockerfile/test/sanity/Dockerfile.template index a4f9183beac..2e4bdf537b7 100644 --- a/templates/tools/dockerfile/test/sanity/Dockerfile.template +++ b/templates/tools/dockerfile/test/sanity/Dockerfile.template @@ -32,6 +32,7 @@ RUN python3 -m pip install simplejson mako virtualenv lxml <%include file="../../clang5.include"/> + <%include file="../../bazel.include"/> # Define the default command. CMD ["bash"] diff --git a/tools/dockerfile/test/bazel/Dockerfile b/tools/dockerfile/test/bazel/Dockerfile index 22d5d7c71c2..7dee0051176 100644 --- a/tools/dockerfile/test/bazel/Dockerfile +++ b/tools/dockerfile/test/bazel/Dockerfile @@ -52,8 +52,9 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t # Bazel installation RUN apt-get update && apt-get install -y wget && apt-get clean -RUN wget -q https://github.com/bazelbuild/bazel/releases/download/0.17.1/bazel-0.17.1-linux-x86_64 -O /usr/local/bin/bazel -RUN chmod 755 /usr/local/bin/bazel +RUN wget https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-installer-linux-x86_64.sh && \ + bash ./bazel-0.20.0-installer-linux-x86_64.sh && \ + rm bazel-0.20.0-installer-linux-x86_64.sh RUN mkdir -p /var/local/jenkins diff --git a/tools/dockerfile/test/sanity/Dockerfile b/tools/dockerfile/test/sanity/Dockerfile index aeee02a50fa..7a6fbfee7f4 100644 --- a/tools/dockerfile/test/sanity/Dockerfile +++ b/tools/dockerfile/test/sanity/Dockerfile @@ -94,6 +94,14 @@ ENV CLANG_FORMAT=clang-format RUN ln -s /clang+llvm-5.0.0-linux-x86_64-ubuntu14.04/bin/clang-tidy /usr/local/bin/clang-tidy ENV CLANG_TIDY=clang-tidy +#======================== +# Bazel installation + +RUN apt-get update && apt-get install -y wget && apt-get clean +RUN wget https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-installer-linux-x86_64.sh && \ + bash ./bazel-0.20.0-installer-linux-x86_64.sh && \ + rm bazel-0.20.0-installer-linux-x86_64.sh + # Define the default command. CMD ["bash"] From bb73d8ce21a16307ac02ca551bcb47c8c4d88fd5 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 31 Jan 2019 14:58:18 -0800 Subject: [PATCH 123/218] Fix for 17338. Delay shutdown of buffer list till tcp_free to avoid races --- src/core/lib/iomgr/tcp_posix.cc | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index 792ffd27385..32ee10c185a 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -343,6 +343,13 @@ static void tcp_free(grpc_tcp* tcp) { grpc_slice_buffer_destroy_internal(&tcp->last_read_buffer); grpc_resource_user_unref(tcp->resource_user); gpr_free(tcp->peer_string); + /* The lock is not really necessary here, since all refs have been released */ + gpr_mu_lock(&tcp->tb_mu); + grpc_core::TracedBuffer::Shutdown( + &tcp->tb_head, tcp->outgoing_buffer_arg, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); + gpr_mu_unlock(&tcp->tb_mu); + tcp->outgoing_buffer_arg = nullptr; gpr_mu_destroy(&tcp->tb_mu); gpr_free(tcp); } @@ -389,12 +396,6 @@ static void tcp_destroy(grpc_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()) { - gpr_mu_lock(&tcp->tb_mu); - grpc_core::TracedBuffer::Shutdown( - &tcp->tb_head, tcp->outgoing_buffer_arg, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); - gpr_mu_unlock(&tcp->tb_mu); - tcp->outgoing_buffer_arg = nullptr; gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); grpc_fd_set_error(tcp->em_fd); } @@ -1184,12 +1185,6 @@ void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd, grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); if (grpc_event_engine_can_track_errors()) { /* Stop errors notification. */ - gpr_mu_lock(&tcp->tb_mu); - grpc_core::TracedBuffer::Shutdown( - &tcp->tb_head, tcp->outgoing_buffer_arg, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); - gpr_mu_unlock(&tcp->tb_mu); - tcp->outgoing_buffer_arg = nullptr; gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); grpc_fd_set_error(tcp->em_fd); } From 139d9f6e94ebe75220ae93fe4e84aa941aa62cdd Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Thu, 31 Jan 2019 15:06:34 -0800 Subject: [PATCH 124/218] Revert "Revert c-ares as the default resolvre" This reverts commit ca30b2240f6f8e86b51452097c3cb43c5d4f7117. --- .../client_channel/resolver/dns/c_ares/dns_resolver_ares.cc | 3 ++- .../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, 3 insertions(+), 4 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 fe245bfef09..bf8b0ea5f62 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 @@ -478,7 +478,8 @@ 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 || strlen(resolver_env) == 0 || + 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 f426eab9592..6f153cc9bf6 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 8a5b1f53dcf..a4438cb100e 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 adfe2238ef16008d6f61fd1f209c7783cc556de5 Mon Sep 17 00:00:00 2001 From: Yihua Zhang Date: Thu, 31 Jan 2019 20:56:13 -0800 Subject: [PATCH 125/218] ignore duplicate root cert in cert list instead of fail. --- src/core/tsi/ssl_transport_security.cc | 11 ++++++++--- test/core/tsi/ssl_transport_security_test.cc | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/core/tsi/ssl_transport_security.cc b/src/core/tsi/ssl_transport_security.cc index b18da575382..5ced404f39d 100644 --- a/src/core/tsi/ssl_transport_security.cc +++ b/src/core/tsi/ssl_transport_security.cc @@ -619,10 +619,15 @@ static tsi_result x509_store_load_certs(X509_STORE* cert_store, sk_X509_NAME_push(*root_names, root_name); root_name = nullptr; } + ERR_clear_error(); if (!X509_STORE_add_cert(cert_store, root)) { - gpr_log(GPR_ERROR, "Could not add root certificate to ssl context."); - result = TSI_INTERNAL_ERROR; - break; + size_t error = ERR_get_error(); + if (ERR_GET_LIB(error) != ERR_LIB_X509 || + ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { + gpr_log(GPR_ERROR, "Could not add root certificate to ssl context."); + result = TSI_INTERNAL_ERROR; + break; + } } X509_free(root); num_roots++; diff --git a/test/core/tsi/ssl_transport_security_test.cc b/test/core/tsi/ssl_transport_security_test.cc index fc6c6ba3208..bb69907527c 100644 --- a/test/core/tsi/ssl_transport_security_test.cc +++ b/test/core/tsi/ssl_transport_security_test.cc @@ -776,10 +776,24 @@ void ssl_tsi_test_handshaker_factory_internals() { test_tsi_ssl_client_handshaker_factory_bad_params(); } +void ssl_tsi_test_duplicate_root_certificates() { + const char* root_cert = load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "ca.pem"); + char* dup_root_cert = static_cast( + gpr_zalloc(sizeof(char) * (strlen(root_cert) * 2 + 1))); + memcpy(dup_root_cert, root_cert, strlen(root_cert)); + memcpy(dup_root_cert + strlen(root_cert), root_cert, strlen(root_cert)); + tsi_ssl_root_certs_store* root_store = + tsi_ssl_root_certs_store_create(dup_root_cert); + GPR_ASSERT(root_store != nullptr); + // Free memory. + tsi_ssl_root_certs_store_destroy(root_store); + gpr_free((void*)root_cert); + gpr_free((void*)dup_root_cert); +} + int main(int argc, char** argv) { grpc::testing::TestEnvironment env(argc, argv); grpc_init(); - ssl_tsi_test_do_handshake_tiny_handshake_buffer(); ssl_tsi_test_do_handshake_small_handshake_buffer(); ssl_tsi_test_do_handshake(); @@ -801,6 +815,7 @@ int main(int argc, char** argv) { ssl_tsi_test_do_round_trip_for_all_configs(); ssl_tsi_test_do_round_trip_odd_buffer_size(); ssl_tsi_test_handshaker_factory_internals(); + ssl_tsi_test_duplicate_root_certificates(); grpc_shutdown(); return 0; } From 73b846492aa26606c0cc5cfe0ecd14f633a533ad Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 1 Feb 2019 07:28:35 +0100 Subject: [PATCH 126/218] change namespace to internal --- .../Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs b/src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs index d79b5007e87..cc4654c9acf 100644 --- a/src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs +++ b/src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs @@ -20,7 +20,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using Grpc.Core.Internal; -namespace Grpc.Core +namespace Grpc.Core.Internal { internal static class ServerServiceDefinitionExtensions { From 64e095953a7adc37502dfb86c5dc96434bf375bf Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Fri, 1 Feb 2019 05:16:19 -0800 Subject: [PATCH 127/218] Remove an overly-conservative mutex from callback CQ implementation --- src/core/lib/surface/completion_queue.cc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc index 426a4a3f24e..f473b23788e 100644 --- a/src/core/lib/surface/completion_queue.cc +++ b/src/core/lib/surface/completion_queue.cc @@ -854,15 +854,11 @@ static void cq_end_op_for_callback( // for reserved storage. Invoke the done callback right away to release it. done(done_arg, storage); - gpr_mu_lock(cq->mu); - cq_check_tag(cq, tag, false); /* Used in debug builds only */ + cq_check_tag(cq, tag, true); /* Used in debug builds only */ gpr_atm_no_barrier_fetch_add(&cqd->things_queued_ever, 1); if (gpr_atm_full_fetch_add(&cqd->pending_events, -1) == 1) { - gpr_mu_unlock(cq->mu); cq_finish_shutdown_callback(cq); - } else { - gpr_mu_unlock(cq->mu); } GRPC_ERROR_UNREF(error); From ef208401747d76446531192ec742a77b2a735d14 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Fri, 7 Dec 2018 10:01:11 -0500 Subject: [PATCH 128/218] Reorder fields in slice to share the same bytes for length fields. Ref-counted and inlined slices both have a lenght value, but they are not in the same byte offset. As a result, we will have two different loads based on a branch. Instead move them to the same byteoffset, so that we will have one move and the same number of branches. Difference can be seen on: https://godbolt.org/z/kqFZcP --- include/grpc/impl/codegen/slice.h | 2 +- .../chttp2/transport/hpack_encoder.cc | 2 +- src/core/lib/transport/static_metadata.cc | 558 +++++++++--------- 3 files changed, 281 insertions(+), 281 deletions(-) diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h index 90dbfd3b1f8..62339daae5e 100644 --- a/include/grpc/impl/codegen/slice.h +++ b/include/grpc/impl/codegen/slice.h @@ -81,8 +81,8 @@ struct grpc_slice { struct grpc_slice_refcount* refcount; union grpc_slice_data { struct grpc_slice_refcounted { - uint8_t* bytes; size_t length; + uint8_t* bytes; } refcounted; struct grpc_slice_inlined { uint8_t length; diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc index dbe9df6ae38..9b4c3ce7e11 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc @@ -59,7 +59,7 @@ static grpc_slice_refcount terminal_slice_refcount = {nullptr, nullptr}; static const grpc_slice terminal_slice = { &terminal_slice_refcount, /* refcount */ - {{nullptr, 0}} /* data.refcounted */ + {{0, nullptr}} /* data.refcounted */ }; typedef struct { diff --git a/src/core/lib/transport/static_metadata.cc b/src/core/lib/transport/static_metadata.cc index 3dfaaaad5c8..963626a9dc9 100644 --- a/src/core/lib/transport/static_metadata.cc +++ b/src/core/lib/transport/static_metadata.cc @@ -236,113 +236,113 @@ grpc_slice_refcount grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT] = { }; const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = { - {&grpc_static_metadata_refcounts[0], {{g_bytes + 0, 5}}}, - {&grpc_static_metadata_refcounts[1], {{g_bytes + 5, 7}}}, - {&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[3], {{g_bytes + 19, 10}}}, - {&grpc_static_metadata_refcounts[4], {{g_bytes + 29, 7}}}, - {&grpc_static_metadata_refcounts[5], {{g_bytes + 36, 2}}}, - {&grpc_static_metadata_refcounts[6], {{g_bytes + 38, 12}}}, - {&grpc_static_metadata_refcounts[7], {{g_bytes + 50, 11}}}, - {&grpc_static_metadata_refcounts[8], {{g_bytes + 61, 16}}}, - {&grpc_static_metadata_refcounts[9], {{g_bytes + 77, 13}}}, - {&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[11], {{g_bytes + 110, 21}}}, - {&grpc_static_metadata_refcounts[12], {{g_bytes + 131, 13}}}, - {&grpc_static_metadata_refcounts[13], {{g_bytes + 144, 14}}}, - {&grpc_static_metadata_refcounts[14], {{g_bytes + 158, 12}}}, - {&grpc_static_metadata_refcounts[15], {{g_bytes + 170, 16}}}, - {&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[17], {{g_bytes + 201, 30}}}, - {&grpc_static_metadata_refcounts[18], {{g_bytes + 231, 37}}}, - {&grpc_static_metadata_refcounts[19], {{g_bytes + 268, 10}}}, - {&grpc_static_metadata_refcounts[20], {{g_bytes + 278, 4}}}, - {&grpc_static_metadata_refcounts[21], {{g_bytes + 282, 8}}}, - {&grpc_static_metadata_refcounts[22], {{g_bytes + 290, 26}}}, - {&grpc_static_metadata_refcounts[23], {{g_bytes + 316, 22}}}, - {&grpc_static_metadata_refcounts[24], {{g_bytes + 338, 12}}}, - {&grpc_static_metadata_refcounts[25], {{g_bytes + 350, 1}}}, - {&grpc_static_metadata_refcounts[26], {{g_bytes + 351, 1}}}, - {&grpc_static_metadata_refcounts[27], {{g_bytes + 352, 1}}}, - {&grpc_static_metadata_refcounts[28], {{g_bytes + 353, 1}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}, - {&grpc_static_metadata_refcounts[30], {{g_bytes + 354, 19}}}, - {&grpc_static_metadata_refcounts[31], {{g_bytes + 373, 12}}}, - {&grpc_static_metadata_refcounts[32], {{g_bytes + 385, 30}}}, - {&grpc_static_metadata_refcounts[33], {{g_bytes + 415, 31}}}, - {&grpc_static_metadata_refcounts[34], {{g_bytes + 446, 36}}}, - {&grpc_static_metadata_refcounts[35], {{g_bytes + 482, 28}}}, - {&grpc_static_metadata_refcounts[36], {{g_bytes + 510, 80}}}, - {&grpc_static_metadata_refcounts[37], {{g_bytes + 590, 7}}}, - {&grpc_static_metadata_refcounts[38], {{g_bytes + 597, 4}}}, - {&grpc_static_metadata_refcounts[39], {{g_bytes + 601, 11}}}, - {&grpc_static_metadata_refcounts[40], {{g_bytes + 612, 3}}}, - {&grpc_static_metadata_refcounts[41], {{g_bytes + 615, 4}}}, - {&grpc_static_metadata_refcounts[42], {{g_bytes + 619, 1}}}, - {&grpc_static_metadata_refcounts[43], {{g_bytes + 620, 11}}}, - {&grpc_static_metadata_refcounts[44], {{g_bytes + 631, 4}}}, - {&grpc_static_metadata_refcounts[45], {{g_bytes + 635, 5}}}, - {&grpc_static_metadata_refcounts[46], {{g_bytes + 640, 3}}}, - {&grpc_static_metadata_refcounts[47], {{g_bytes + 643, 3}}}, - {&grpc_static_metadata_refcounts[48], {{g_bytes + 646, 3}}}, - {&grpc_static_metadata_refcounts[49], {{g_bytes + 649, 3}}}, - {&grpc_static_metadata_refcounts[50], {{g_bytes + 652, 3}}}, - {&grpc_static_metadata_refcounts[51], {{g_bytes + 655, 3}}}, - {&grpc_static_metadata_refcounts[52], {{g_bytes + 658, 3}}}, - {&grpc_static_metadata_refcounts[53], {{g_bytes + 661, 14}}}, - {&grpc_static_metadata_refcounts[54], {{g_bytes + 675, 13}}}, - {&grpc_static_metadata_refcounts[55], {{g_bytes + 688, 15}}}, - {&grpc_static_metadata_refcounts[56], {{g_bytes + 703, 13}}}, - {&grpc_static_metadata_refcounts[57], {{g_bytes + 716, 6}}}, - {&grpc_static_metadata_refcounts[58], {{g_bytes + 722, 27}}}, - {&grpc_static_metadata_refcounts[59], {{g_bytes + 749, 3}}}, - {&grpc_static_metadata_refcounts[60], {{g_bytes + 752, 5}}}, - {&grpc_static_metadata_refcounts[61], {{g_bytes + 757, 13}}}, - {&grpc_static_metadata_refcounts[62], {{g_bytes + 770, 13}}}, - {&grpc_static_metadata_refcounts[63], {{g_bytes + 783, 19}}}, - {&grpc_static_metadata_refcounts[64], {{g_bytes + 802, 16}}}, - {&grpc_static_metadata_refcounts[65], {{g_bytes + 818, 14}}}, - {&grpc_static_metadata_refcounts[66], {{g_bytes + 832, 16}}}, - {&grpc_static_metadata_refcounts[67], {{g_bytes + 848, 13}}}, - {&grpc_static_metadata_refcounts[68], {{g_bytes + 861, 6}}}, - {&grpc_static_metadata_refcounts[69], {{g_bytes + 867, 4}}}, - {&grpc_static_metadata_refcounts[70], {{g_bytes + 871, 4}}}, - {&grpc_static_metadata_refcounts[71], {{g_bytes + 875, 6}}}, - {&grpc_static_metadata_refcounts[72], {{g_bytes + 881, 7}}}, - {&grpc_static_metadata_refcounts[73], {{g_bytes + 888, 4}}}, - {&grpc_static_metadata_refcounts[74], {{g_bytes + 892, 8}}}, - {&grpc_static_metadata_refcounts[75], {{g_bytes + 900, 17}}}, - {&grpc_static_metadata_refcounts[76], {{g_bytes + 917, 13}}}, - {&grpc_static_metadata_refcounts[77], {{g_bytes + 930, 8}}}, - {&grpc_static_metadata_refcounts[78], {{g_bytes + 938, 19}}}, - {&grpc_static_metadata_refcounts[79], {{g_bytes + 957, 13}}}, - {&grpc_static_metadata_refcounts[80], {{g_bytes + 970, 4}}}, - {&grpc_static_metadata_refcounts[81], {{g_bytes + 974, 8}}}, - {&grpc_static_metadata_refcounts[82], {{g_bytes + 982, 12}}}, - {&grpc_static_metadata_refcounts[83], {{g_bytes + 994, 18}}}, - {&grpc_static_metadata_refcounts[84], {{g_bytes + 1012, 19}}}, - {&grpc_static_metadata_refcounts[85], {{g_bytes + 1031, 5}}}, - {&grpc_static_metadata_refcounts[86], {{g_bytes + 1036, 7}}}, - {&grpc_static_metadata_refcounts[87], {{g_bytes + 1043, 7}}}, - {&grpc_static_metadata_refcounts[88], {{g_bytes + 1050, 11}}}, - {&grpc_static_metadata_refcounts[89], {{g_bytes + 1061, 6}}}, - {&grpc_static_metadata_refcounts[90], {{g_bytes + 1067, 10}}}, - {&grpc_static_metadata_refcounts[91], {{g_bytes + 1077, 25}}}, - {&grpc_static_metadata_refcounts[92], {{g_bytes + 1102, 17}}}, - {&grpc_static_metadata_refcounts[93], {{g_bytes + 1119, 4}}}, - {&grpc_static_metadata_refcounts[94], {{g_bytes + 1123, 3}}}, - {&grpc_static_metadata_refcounts[95], {{g_bytes + 1126, 16}}}, - {&grpc_static_metadata_refcounts[96], {{g_bytes + 1142, 1}}}, - {&grpc_static_metadata_refcounts[97], {{g_bytes + 1143, 8}}}, - {&grpc_static_metadata_refcounts[98], {{g_bytes + 1151, 8}}}, - {&grpc_static_metadata_refcounts[99], {{g_bytes + 1159, 16}}}, - {&grpc_static_metadata_refcounts[100], {{g_bytes + 1175, 4}}}, - {&grpc_static_metadata_refcounts[101], {{g_bytes + 1179, 3}}}, - {&grpc_static_metadata_refcounts[102], {{g_bytes + 1182, 11}}}, - {&grpc_static_metadata_refcounts[103], {{g_bytes + 1193, 16}}}, - {&grpc_static_metadata_refcounts[104], {{g_bytes + 1209, 13}}}, - {&grpc_static_metadata_refcounts[105], {{g_bytes + 1222, 12}}}, - {&grpc_static_metadata_refcounts[106], {{g_bytes + 1234, 21}}}, + {&grpc_static_metadata_refcounts[0], {{5, g_bytes + 0}}}, + {&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}}, + {&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[3], {{10, g_bytes + 19}}}, + {&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}}, + {&grpc_static_metadata_refcounts[5], {{2, g_bytes + 36}}}, + {&grpc_static_metadata_refcounts[6], {{12, g_bytes + 38}}}, + {&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}}, + {&grpc_static_metadata_refcounts[8], {{16, g_bytes + 61}}}, + {&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}}, + {&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[11], {{21, g_bytes + 110}}}, + {&grpc_static_metadata_refcounts[12], {{13, g_bytes + 131}}}, + {&grpc_static_metadata_refcounts[13], {{14, g_bytes + 144}}}, + {&grpc_static_metadata_refcounts[14], {{12, g_bytes + 158}}}, + {&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}}, + {&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[17], {{30, g_bytes + 201}}}, + {&grpc_static_metadata_refcounts[18], {{37, g_bytes + 231}}}, + {&grpc_static_metadata_refcounts[19], {{10, g_bytes + 268}}}, + {&grpc_static_metadata_refcounts[20], {{4, g_bytes + 278}}}, + {&grpc_static_metadata_refcounts[21], {{8, g_bytes + 282}}}, + {&grpc_static_metadata_refcounts[22], {{26, g_bytes + 290}}}, + {&grpc_static_metadata_refcounts[23], {{22, g_bytes + 316}}}, + {&grpc_static_metadata_refcounts[24], {{12, g_bytes + 338}}}, + {&grpc_static_metadata_refcounts[25], {{1, g_bytes + 350}}}, + {&grpc_static_metadata_refcounts[26], {{1, g_bytes + 351}}}, + {&grpc_static_metadata_refcounts[27], {{1, g_bytes + 352}}}, + {&grpc_static_metadata_refcounts[28], {{1, g_bytes + 353}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}, + {&grpc_static_metadata_refcounts[30], {{19, g_bytes + 354}}}, + {&grpc_static_metadata_refcounts[31], {{12, g_bytes + 373}}}, + {&grpc_static_metadata_refcounts[32], {{30, g_bytes + 385}}}, + {&grpc_static_metadata_refcounts[33], {{31, g_bytes + 415}}}, + {&grpc_static_metadata_refcounts[34], {{36, g_bytes + 446}}}, + {&grpc_static_metadata_refcounts[35], {{28, g_bytes + 482}}}, + {&grpc_static_metadata_refcounts[36], {{80, g_bytes + 510}}}, + {&grpc_static_metadata_refcounts[37], {{7, g_bytes + 590}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}, + {&grpc_static_metadata_refcounts[39], {{11, g_bytes + 601}}}, + {&grpc_static_metadata_refcounts[40], {{3, g_bytes + 612}}}, + {&grpc_static_metadata_refcounts[41], {{4, g_bytes + 615}}}, + {&grpc_static_metadata_refcounts[42], {{1, g_bytes + 619}}}, + {&grpc_static_metadata_refcounts[43], {{11, g_bytes + 620}}}, + {&grpc_static_metadata_refcounts[44], {{4, g_bytes + 631}}}, + {&grpc_static_metadata_refcounts[45], {{5, g_bytes + 635}}}, + {&grpc_static_metadata_refcounts[46], {{3, g_bytes + 640}}}, + {&grpc_static_metadata_refcounts[47], {{3, g_bytes + 643}}}, + {&grpc_static_metadata_refcounts[48], {{3, g_bytes + 646}}}, + {&grpc_static_metadata_refcounts[49], {{3, g_bytes + 649}}}, + {&grpc_static_metadata_refcounts[50], {{3, g_bytes + 652}}}, + {&grpc_static_metadata_refcounts[51], {{3, g_bytes + 655}}}, + {&grpc_static_metadata_refcounts[52], {{3, g_bytes + 658}}}, + {&grpc_static_metadata_refcounts[53], {{14, g_bytes + 661}}}, + {&grpc_static_metadata_refcounts[54], {{13, g_bytes + 675}}}, + {&grpc_static_metadata_refcounts[55], {{15, g_bytes + 688}}}, + {&grpc_static_metadata_refcounts[56], {{13, g_bytes + 703}}}, + {&grpc_static_metadata_refcounts[57], {{6, g_bytes + 716}}}, + {&grpc_static_metadata_refcounts[58], {{27, g_bytes + 722}}}, + {&grpc_static_metadata_refcounts[59], {{3, g_bytes + 749}}}, + {&grpc_static_metadata_refcounts[60], {{5, g_bytes + 752}}}, + {&grpc_static_metadata_refcounts[61], {{13, g_bytes + 757}}}, + {&grpc_static_metadata_refcounts[62], {{13, g_bytes + 770}}}, + {&grpc_static_metadata_refcounts[63], {{19, g_bytes + 783}}}, + {&grpc_static_metadata_refcounts[64], {{16, g_bytes + 802}}}, + {&grpc_static_metadata_refcounts[65], {{14, g_bytes + 818}}}, + {&grpc_static_metadata_refcounts[66], {{16, g_bytes + 832}}}, + {&grpc_static_metadata_refcounts[67], {{13, g_bytes + 848}}}, + {&grpc_static_metadata_refcounts[68], {{6, g_bytes + 861}}}, + {&grpc_static_metadata_refcounts[69], {{4, g_bytes + 867}}}, + {&grpc_static_metadata_refcounts[70], {{4, g_bytes + 871}}}, + {&grpc_static_metadata_refcounts[71], {{6, g_bytes + 875}}}, + {&grpc_static_metadata_refcounts[72], {{7, g_bytes + 881}}}, + {&grpc_static_metadata_refcounts[73], {{4, g_bytes + 888}}}, + {&grpc_static_metadata_refcounts[74], {{8, g_bytes + 892}}}, + {&grpc_static_metadata_refcounts[75], {{17, g_bytes + 900}}}, + {&grpc_static_metadata_refcounts[76], {{13, g_bytes + 917}}}, + {&grpc_static_metadata_refcounts[77], {{8, g_bytes + 930}}}, + {&grpc_static_metadata_refcounts[78], {{19, g_bytes + 938}}}, + {&grpc_static_metadata_refcounts[79], {{13, g_bytes + 957}}}, + {&grpc_static_metadata_refcounts[80], {{4, g_bytes + 970}}}, + {&grpc_static_metadata_refcounts[81], {{8, g_bytes + 974}}}, + {&grpc_static_metadata_refcounts[82], {{12, g_bytes + 982}}}, + {&grpc_static_metadata_refcounts[83], {{18, g_bytes + 994}}}, + {&grpc_static_metadata_refcounts[84], {{19, g_bytes + 1012}}}, + {&grpc_static_metadata_refcounts[85], {{5, g_bytes + 1031}}}, + {&grpc_static_metadata_refcounts[86], {{7, g_bytes + 1036}}}, + {&grpc_static_metadata_refcounts[87], {{7, g_bytes + 1043}}}, + {&grpc_static_metadata_refcounts[88], {{11, g_bytes + 1050}}}, + {&grpc_static_metadata_refcounts[89], {{6, g_bytes + 1061}}}, + {&grpc_static_metadata_refcounts[90], {{10, g_bytes + 1067}}}, + {&grpc_static_metadata_refcounts[91], {{25, g_bytes + 1077}}}, + {&grpc_static_metadata_refcounts[92], {{17, g_bytes + 1102}}}, + {&grpc_static_metadata_refcounts[93], {{4, g_bytes + 1119}}}, + {&grpc_static_metadata_refcounts[94], {{3, g_bytes + 1123}}}, + {&grpc_static_metadata_refcounts[95], {{16, g_bytes + 1126}}}, + {&grpc_static_metadata_refcounts[96], {{1, g_bytes + 1142}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}, + {&grpc_static_metadata_refcounts[98], {{8, g_bytes + 1151}}}, + {&grpc_static_metadata_refcounts[99], {{16, g_bytes + 1159}}}, + {&grpc_static_metadata_refcounts[100], {{4, g_bytes + 1175}}}, + {&grpc_static_metadata_refcounts[101], {{3, g_bytes + 1179}}}, + {&grpc_static_metadata_refcounts[102], {{11, g_bytes + 1182}}}, + {&grpc_static_metadata_refcounts[103], {{16, g_bytes + 1193}}}, + {&grpc_static_metadata_refcounts[104], {{13, g_bytes + 1209}}}, + {&grpc_static_metadata_refcounts[105], {{12, g_bytes + 1222}}}, + {&grpc_static_metadata_refcounts[106], {{21, g_bytes + 1234}}}, }; uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = { @@ -404,178 +404,178 @@ grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) { } grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = { - {{&grpc_static_metadata_refcounts[3], {{g_bytes + 19, 10}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[1], {{g_bytes + 5, 7}}}, - {&grpc_static_metadata_refcounts[40], {{g_bytes + 612, 3}}}}, - {{&grpc_static_metadata_refcounts[1], {{g_bytes + 5, 7}}}, - {&grpc_static_metadata_refcounts[41], {{g_bytes + 615, 4}}}}, - {{&grpc_static_metadata_refcounts[0], {{g_bytes + 0, 5}}}, - {&grpc_static_metadata_refcounts[42], {{g_bytes + 619, 1}}}}, - {{&grpc_static_metadata_refcounts[0], {{g_bytes + 0, 5}}}, - {&grpc_static_metadata_refcounts[43], {{g_bytes + 620, 11}}}}, - {{&grpc_static_metadata_refcounts[4], {{g_bytes + 29, 7}}}, - {&grpc_static_metadata_refcounts[44], {{g_bytes + 631, 4}}}}, - {{&grpc_static_metadata_refcounts[4], {{g_bytes + 29, 7}}}, - {&grpc_static_metadata_refcounts[45], {{g_bytes + 635, 5}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[46], {{g_bytes + 640, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[47], {{g_bytes + 643, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[48], {{g_bytes + 646, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[49], {{g_bytes + 649, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[50], {{g_bytes + 652, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[51], {{g_bytes + 655, 3}}}}, - {{&grpc_static_metadata_refcounts[2], {{g_bytes + 12, 7}}}, - {&grpc_static_metadata_refcounts[52], {{g_bytes + 658, 3}}}}, - {{&grpc_static_metadata_refcounts[53], {{g_bytes + 661, 14}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[54], {{g_bytes + 675, 13}}}}, - {{&grpc_static_metadata_refcounts[55], {{g_bytes + 688, 15}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[56], {{g_bytes + 703, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[57], {{g_bytes + 716, 6}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[58], {{g_bytes + 722, 27}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[59], {{g_bytes + 749, 3}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[60], {{g_bytes + 752, 5}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[61], {{g_bytes + 757, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[62], {{g_bytes + 770, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[63], {{g_bytes + 783, 19}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[15], {{g_bytes + 170, 16}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[64], {{g_bytes + 802, 16}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[65], {{g_bytes + 818, 14}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[66], {{g_bytes + 832, 16}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[67], {{g_bytes + 848, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[14], {{g_bytes + 158, 12}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[68], {{g_bytes + 861, 6}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[69], {{g_bytes + 867, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[70], {{g_bytes + 871, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[71], {{g_bytes + 875, 6}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[72], {{g_bytes + 881, 7}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[73], {{g_bytes + 888, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[20], {{g_bytes + 278, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[74], {{g_bytes + 892, 8}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[75], {{g_bytes + 900, 17}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[76], {{g_bytes + 917, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[77], {{g_bytes + 930, 8}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[78], {{g_bytes + 938, 19}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[79], {{g_bytes + 957, 13}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[80], {{g_bytes + 970, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[81], {{g_bytes + 974, 8}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[82], {{g_bytes + 982, 12}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[83], {{g_bytes + 994, 18}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[84], {{g_bytes + 1012, 19}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[85], {{g_bytes + 1031, 5}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[86], {{g_bytes + 1036, 7}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[87], {{g_bytes + 1043, 7}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[88], {{g_bytes + 1050, 11}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[89], {{g_bytes + 1061, 6}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[90], {{g_bytes + 1067, 10}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[91], {{g_bytes + 1077, 25}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[92], {{g_bytes + 1102, 17}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[19], {{g_bytes + 268, 10}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[93], {{g_bytes + 1119, 4}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[94], {{g_bytes + 1123, 3}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[95], {{g_bytes + 1126, 16}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[7], {{g_bytes + 50, 11}}}, - {&grpc_static_metadata_refcounts[96], {{g_bytes + 1142, 1}}}}, - {{&grpc_static_metadata_refcounts[7], {{g_bytes + 50, 11}}}, - {&grpc_static_metadata_refcounts[25], {{g_bytes + 350, 1}}}}, - {{&grpc_static_metadata_refcounts[7], {{g_bytes + 50, 11}}}, - {&grpc_static_metadata_refcounts[26], {{g_bytes + 351, 1}}}}, - {{&grpc_static_metadata_refcounts[9], {{g_bytes + 77, 13}}}, - {&grpc_static_metadata_refcounts[97], {{g_bytes + 1143, 8}}}}, - {{&grpc_static_metadata_refcounts[9], {{g_bytes + 77, 13}}}, - {&grpc_static_metadata_refcounts[38], {{g_bytes + 597, 4}}}}, - {{&grpc_static_metadata_refcounts[9], {{g_bytes + 77, 13}}}, - {&grpc_static_metadata_refcounts[37], {{g_bytes + 590, 7}}}}, - {{&grpc_static_metadata_refcounts[5], {{g_bytes + 36, 2}}}, - {&grpc_static_metadata_refcounts[98], {{g_bytes + 1151, 8}}}}, - {{&grpc_static_metadata_refcounts[14], {{g_bytes + 158, 12}}}, - {&grpc_static_metadata_refcounts[99], {{g_bytes + 1159, 16}}}}, - {{&grpc_static_metadata_refcounts[4], {{g_bytes + 29, 7}}}, - {&grpc_static_metadata_refcounts[100], {{g_bytes + 1175, 4}}}}, - {{&grpc_static_metadata_refcounts[1], {{g_bytes + 5, 7}}}, - {&grpc_static_metadata_refcounts[101], {{g_bytes + 1179, 3}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[15], {{g_bytes + 170, 16}}}, - {&grpc_static_metadata_refcounts[97], {{g_bytes + 1143, 8}}}}, - {{&grpc_static_metadata_refcounts[15], {{g_bytes + 170, 16}}}, - {&grpc_static_metadata_refcounts[38], {{g_bytes + 597, 4}}}}, - {{&grpc_static_metadata_refcounts[21], {{g_bytes + 282, 8}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[102], {{g_bytes + 1182, 11}}}, - {&grpc_static_metadata_refcounts[29], {{g_bytes + 354, 0}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[97], {{g_bytes + 1143, 8}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[37], {{g_bytes + 590, 7}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[103], {{g_bytes + 1193, 16}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[38], {{g_bytes + 597, 4}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[104], {{g_bytes + 1209, 13}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[105], {{g_bytes + 1222, 12}}}}, - {{&grpc_static_metadata_refcounts[10], {{g_bytes + 90, 20}}}, - {&grpc_static_metadata_refcounts[106], {{g_bytes + 1234, 21}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[97], {{g_bytes + 1143, 8}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[38], {{g_bytes + 597, 4}}}}, - {{&grpc_static_metadata_refcounts[16], {{g_bytes + 186, 15}}}, - {&grpc_static_metadata_refcounts[104], {{g_bytes + 1209, 13}}}}, + {{&grpc_static_metadata_refcounts[3], {{10, g_bytes + 19}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}}, + {&grpc_static_metadata_refcounts[40], {{3, g_bytes + 612}}}}, + {{&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}}, + {&grpc_static_metadata_refcounts[41], {{4, g_bytes + 615}}}}, + {{&grpc_static_metadata_refcounts[0], {{5, g_bytes + 0}}}, + {&grpc_static_metadata_refcounts[42], {{1, g_bytes + 619}}}}, + {{&grpc_static_metadata_refcounts[0], {{5, g_bytes + 0}}}, + {&grpc_static_metadata_refcounts[43], {{11, g_bytes + 620}}}}, + {{&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}}, + {&grpc_static_metadata_refcounts[44], {{4, g_bytes + 631}}}}, + {{&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}}, + {&grpc_static_metadata_refcounts[45], {{5, g_bytes + 635}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[46], {{3, g_bytes + 640}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[47], {{3, g_bytes + 643}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[48], {{3, g_bytes + 646}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[49], {{3, g_bytes + 649}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[50], {{3, g_bytes + 652}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[51], {{3, g_bytes + 655}}}}, + {{&grpc_static_metadata_refcounts[2], {{7, g_bytes + 12}}}, + {&grpc_static_metadata_refcounts[52], {{3, g_bytes + 658}}}}, + {{&grpc_static_metadata_refcounts[53], {{14, g_bytes + 661}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[54], {{13, g_bytes + 675}}}}, + {{&grpc_static_metadata_refcounts[55], {{15, g_bytes + 688}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[56], {{13, g_bytes + 703}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[57], {{6, g_bytes + 716}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[58], {{27, g_bytes + 722}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[59], {{3, g_bytes + 749}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[60], {{5, g_bytes + 752}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[61], {{13, g_bytes + 757}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[62], {{13, g_bytes + 770}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[63], {{19, g_bytes + 783}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[64], {{16, g_bytes + 802}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[65], {{14, g_bytes + 818}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[66], {{16, g_bytes + 832}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[67], {{13, g_bytes + 848}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[14], {{12, g_bytes + 158}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[68], {{6, g_bytes + 861}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[69], {{4, g_bytes + 867}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[70], {{4, g_bytes + 871}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[71], {{6, g_bytes + 875}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[72], {{7, g_bytes + 881}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[73], {{4, g_bytes + 888}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[20], {{4, g_bytes + 278}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[74], {{8, g_bytes + 892}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[75], {{17, g_bytes + 900}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[76], {{13, g_bytes + 917}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[77], {{8, g_bytes + 930}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[78], {{19, g_bytes + 938}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[79], {{13, g_bytes + 957}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[80], {{4, g_bytes + 970}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[81], {{8, g_bytes + 974}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[82], {{12, g_bytes + 982}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[83], {{18, g_bytes + 994}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[84], {{19, g_bytes + 1012}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[85], {{5, g_bytes + 1031}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[86], {{7, g_bytes + 1036}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[87], {{7, g_bytes + 1043}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[88], {{11, g_bytes + 1050}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[89], {{6, g_bytes + 1061}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[90], {{10, g_bytes + 1067}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[91], {{25, g_bytes + 1077}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[92], {{17, g_bytes + 1102}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[19], {{10, g_bytes + 268}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[93], {{4, g_bytes + 1119}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[94], {{3, g_bytes + 1123}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[95], {{16, g_bytes + 1126}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}}, + {&grpc_static_metadata_refcounts[96], {{1, g_bytes + 1142}}}}, + {{&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}}, + {&grpc_static_metadata_refcounts[25], {{1, g_bytes + 350}}}}, + {{&grpc_static_metadata_refcounts[7], {{11, g_bytes + 50}}}, + {&grpc_static_metadata_refcounts[26], {{1, g_bytes + 351}}}}, + {{&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}}, + {{&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}}, + {{&grpc_static_metadata_refcounts[9], {{13, g_bytes + 77}}}, + {&grpc_static_metadata_refcounts[37], {{7, g_bytes + 590}}}}, + {{&grpc_static_metadata_refcounts[5], {{2, g_bytes + 36}}}, + {&grpc_static_metadata_refcounts[98], {{8, g_bytes + 1151}}}}, + {{&grpc_static_metadata_refcounts[14], {{12, g_bytes + 158}}}, + {&grpc_static_metadata_refcounts[99], {{16, g_bytes + 1159}}}}, + {{&grpc_static_metadata_refcounts[4], {{7, g_bytes + 29}}}, + {&grpc_static_metadata_refcounts[100], {{4, g_bytes + 1175}}}}, + {{&grpc_static_metadata_refcounts[1], {{7, g_bytes + 5}}}, + {&grpc_static_metadata_refcounts[101], {{3, g_bytes + 1179}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}}, + {{&grpc_static_metadata_refcounts[15], {{16, g_bytes + 170}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}}, + {{&grpc_static_metadata_refcounts[21], {{8, g_bytes + 282}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[102], {{11, g_bytes + 1182}}}, + {&grpc_static_metadata_refcounts[29], {{0, g_bytes + 354}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[37], {{7, g_bytes + 590}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[103], {{16, g_bytes + 1193}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[104], {{13, g_bytes + 1209}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[105], {{12, g_bytes + 1222}}}}, + {{&grpc_static_metadata_refcounts[10], {{20, g_bytes + 90}}}, + {&grpc_static_metadata_refcounts[106], {{21, g_bytes + 1234}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[97], {{8, g_bytes + 1143}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[38], {{4, g_bytes + 597}}}}, + {{&grpc_static_metadata_refcounts[16], {{15, g_bytes + 186}}}, + {&grpc_static_metadata_refcounts[104], {{13, g_bytes + 1209}}}}, }; const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 76, 77, 78, 79, 80, 81, 82}; From c5255e9a5ee81a5c52f9815e5a88df56f1f8a913 Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Thu, 31 Jan 2019 21:59:43 -0800 Subject: [PATCH 129/218] python: do not store raised exception in _Context.abort() Python 3 exceptions include a `__traceback__` attribute that includes refs to all local variables. Saving the exception results in leaking references to the, among other things, the Cython grpc_call wrapper and prevents garbage collection and release of core resources, even after the server is shutdown. See https://www.python.org/dev/peps/pep-3134/#open-issue-garbage-collection --- src/python/grpcio/grpc/_server.py | 10 ++++---- .../grpcio_tests/tests/unit/_abort_test.py | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py index b44840272c9..6caaece82c4 100644 --- a/src/python/grpcio/grpc/_server.py +++ b/src/python/grpcio/grpc/_server.py @@ -100,7 +100,7 @@ class _RPCState(object): self.statused = False self.rpc_errors = [] self.callbacks = [] - self.abortion = None + self.aborted = False def _raise_rpc_error(state): @@ -287,8 +287,8 @@ class _Context(grpc.ServicerContext): with self._state.condition: self._state.code = code self._state.details = _common.encode(details) - self._state.abortion = Exception() - raise self._state.abortion + self._state.aborted = True + raise Exception() def abort_with_status(self, status): self._state.trailing_metadata = status.trailing_metadata @@ -392,7 +392,7 @@ def _call_behavior(rpc_event, state, behavior, argument, request_deserializer): return behavior(argument, context), True except Exception as exception: # pylint: disable=broad-except with state.condition: - if exception is state.abortion: + if state.aborted: _abort(state, rpc_event.call, cygrpc.StatusCode.unknown, b'RPC Aborted') elif exception not in state.rpc_errors: @@ -410,7 +410,7 @@ def _take_response_from_response_iterator(rpc_event, state, response_iterator): return None, True except Exception as exception: # pylint: disable=broad-except with state.condition: - if exception is state.abortion: + if state.aborted: _abort(state, rpc_event.call, cygrpc.StatusCode.unknown, b'RPC Aborted') elif exception not in state.rpc_errors: diff --git a/src/python/grpcio_tests/tests/unit/_abort_test.py b/src/python/grpcio_tests/tests/unit/_abort_test.py index 6438f6897a0..7acbf61031e 100644 --- a/src/python/grpcio_tests/tests/unit/_abort_test.py +++ b/src/python/grpcio_tests/tests/unit/_abort_test.py @@ -16,6 +16,7 @@ import unittest import collections import logging +import weakref import grpc @@ -39,7 +40,15 @@ class _Status( pass +class _Object(object): + pass + + +do_not_leak_me = _Object() + + def abort_unary_unary(request, servicer_context): + this_should_not_be_leaked = do_not_leak_me servicer_context.abort( grpc.StatusCode.INTERNAL, _ABORT_DETAILS, @@ -101,6 +110,22 @@ class AbortTest(unittest.TestCase): self.assertEqual(rpc_error.code(), grpc.StatusCode.INTERNAL) self.assertEqual(rpc_error.details(), _ABORT_DETAILS) + # This test ensures that abort() does not store the raised exception, which + # on Python 3 (via the `__traceback__` attribute) holds a reference to + # all local vars. Storing the raised exception can prevent GC and stop the + # grpc_call from being unref'ed, even after server shutdown. + def test_abort_does_not_leak_local_vars(self): + global do_not_leak_me # pylint: disable=global-statement + weak_ref = weakref.ref(do_not_leak_me) + + # Servicer will abort() after creating a local ref to do_not_leak_me. + with self.assertRaises(grpc.RpcError) as exception_context: + self._channel.unary_unary(_ABORT)(_REQUEST) + rpc_error = exception_context.exception + + do_not_leak_me = None + self.assertIsNone(weak_ref()) + def test_abort_with_status(self): with self.assertRaises(grpc.RpcError) as exception_context: self._channel.unary_unary(_ABORT_WITH_STATUS)(_REQUEST) From c215e8e3593b08ea6a81727f187a68efc2d30d1f Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 1 Feb 2019 12:14:06 -0800 Subject: [PATCH 130/218] Fix internal build --- test/cpp/util/channel_trace_proto_helper.cc | 40 +++++++-------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc index ff9d8873858..da858b6bb7e 100644 --- a/test/cpp/util/channel_trace_proto_helper.cc +++ b/test/cpp/util/channel_trace_proto_helper.cc @@ -16,53 +16,37 @@ * */ -#include "test/cpp/util/channel_trace_proto_helper.h" +#include -#include -#include +#include "test/cpp/util/channel_trace_proto_helper.h" #include #include +#include +#include #include #include "src/proto/grpc/channelz/channelz.pb.h" namespace grpc { -namespace testing { - -namespace { // Generic helper that takes in a json string, converts it to a proto, and // then back to json. This ensures that the json string was correctly formatted // according to https://developers.google.com/protocol-buffers/docs/proto3#json template void VaidateProtoJsonTranslation(char* json_c_str) { - std::string json_str(json_c_str); + grpc::string json_str(json_c_str); Message msg; - google::protobuf::util::JsonParseOptions parse_options; - // If the following line is failing, then uncomment the last line of the - // comment, and uncomment the lines that print the two strings. You can - // then compare the output, and determine what fields are missing. - // - // parse_options.ignore_unknown_fields = true; - EXPECT_EQ(google::protobuf::util::JsonStringToMessage(json_str, &msg, - parse_options), - google::protobuf::util::Status::OK); - std::string proto_json_str; - google::protobuf::util::JsonPrintOptions print_options; - // We usually do not want this to be true, however it can be helpful to - // uncomment and see the output produced then all fields are printed. - // print_options.always_print_primitive_fields = true; - EXPECT_EQ(google::protobuf::util::MessageToJsonString(msg, &proto_json_str, - print_options), - google::protobuf::util::Status::OK); - // uncomment these to compare the the json strings. - // gpr_log(GPR_ERROR, "tracer json: %s", json_str.c_str()); - // gpr_log(GPR_ERROR, "proto json: %s", proto_json_str.c_str()); + grpc::protobuf::util::Status s = + grpc::protobuf::json::JsonStringToMessage(json_str, &msg); + EXPECT_TRUE(s.ok()); + grpc::string proto_json_str; + s = grpc::protobuf::json::MessageToJsonString(msg, &proto_json_str); + EXPECT_TRUE(s.ok()); EXPECT_EQ(json_str, proto_json_str); } -} // namespace +namespace testing { void ValidateChannelTraceProtoJsonTranslation(char* json_c_str) { VaidateProtoJsonTranslation(json_c_str); From 632aa8125f8614a3ea68dec8d27d42cefcaf0237 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 1 Feb 2019 13:15:19 -0800 Subject: [PATCH 131/218] reintroduce anon namespace --- test/cpp/util/channel_trace_proto_helper.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc index da858b6bb7e..4cb1a5d0f44 100644 --- a/test/cpp/util/channel_trace_proto_helper.cc +++ b/test/cpp/util/channel_trace_proto_helper.cc @@ -29,6 +29,8 @@ #include "src/proto/grpc/channelz/channelz.pb.h" namespace grpc { + +namespace { // Generic helper that takes in a json string, converts it to a proto, and // then back to json. This ensures that the json string was correctly formatted @@ -46,6 +48,8 @@ void VaidateProtoJsonTranslation(char* json_c_str) { EXPECT_EQ(json_str, proto_json_str); } +} // namespace + namespace testing { void ValidateChannelTraceProtoJsonTranslation(char* json_c_str) { From fa74259769507e084795065627470f643acaaa34 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 1 Feb 2019 13:19:34 -0800 Subject: [PATCH 132/218] Reintroduce commented debugging tips --- test/cpp/util/channel_trace_proto_helper.cc | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc index 4cb1a5d0f44..80d084f585b 100644 --- a/test/cpp/util/channel_trace_proto_helper.cc +++ b/test/cpp/util/channel_trace_proto_helper.cc @@ -29,7 +29,7 @@ #include "src/proto/grpc/channelz/channelz.pb.h" namespace grpc { - + namespace { // Generic helper that takes in a json string, converts it to a proto, and @@ -39,12 +39,25 @@ template void VaidateProtoJsonTranslation(char* json_c_str) { grpc::string json_str(json_c_str); Message msg; + grpc::protobuf::json::JsonParseOptions parse_options; + // If the following line is failing, then uncomment the last line of the + // comment, and uncomment the lines that print the two strings. You can + // then compare the output, and determine what fields are missing. + // + // parse_options.ignore_unknown_fields = true; grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, &msg); + grpc::protobuf::json::JsonStringToMessage(json_str, &msg, parse_options); EXPECT_TRUE(s.ok()); grpc::string proto_json_str; + grpc::protobuf::json::JsonPrintOptions print_options; + // We usually do not want this to be true, however it can be helpful to + // uncomment and see the output produced then all fields are printed. + // print_options.always_print_primitive_fields = true; s = grpc::protobuf::json::MessageToJsonString(msg, &proto_json_str); EXPECT_TRUE(s.ok()); + // uncomment these to compare the the json strings. + // gpr_log(GPR_ERROR, "tracer json: %s", json_str.c_str()); + // gpr_log(GPR_ERROR, "proto json: %s", proto_json_str.c_str()); EXPECT_EQ(json_str, proto_json_str); } From e56c832c0d538d7c21da7258fd7167fd4bfce7b3 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Fri, 1 Feb 2019 13:44:50 -0800 Subject: [PATCH 133/218] Replace list of outstanding callback requests with count only --- include/grpcpp/server.h | 26 ++++----- src/cpp/server/server_cc.cc | 104 +++++++++++++++--------------------- 2 files changed, 53 insertions(+), 77 deletions(-) diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index df68cf31441..d1717ce87d2 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -248,22 +249,15 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { /// the \a sync_server_cqs) std::vector> sync_req_mgrs_; - // Outstanding callback requests. The vector is indexed by method with a list - // per method. Each element should store its own iterator in the list and - // should erase it when the request is actually bound to an RPC. Synchronize - // this list with its own mu_ (not the server mu_) since these must be active - // at Shutdown when the server mu_ is locked. - // TODO(vjpai): Merge with the core request matcher to avoid duplicate work - struct MethodReqList { - std::mutex reqs_mu; - // Maintain our own list size count since list::size is still linear - // for some libraries (supposed to be constant since C++11) - // TODO(vjpai): Remove reqs_list_sz and use list::size when possible - size_t reqs_list_sz{0}; - std::list reqs_list; - using iterator = decltype(reqs_list)::iterator; - }; - std::vector callback_reqs_; + // Outstanding unmatched callback requests, indexed by method. + // NOTE: Using a gpr_atm rather than atomic_int because atomic_int isn't + // copyable or movable and thus will cause compilation errors. We + // actually only want to extend the vector before the threaded use + // starts, but this is still a limitation. + std::vector callback_unmatched_reqs_count_; + + // List of callback requests to start when server actually starts + std::list callback_reqs_to_start_; // Server status std::mutex mu_; diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 1e642681467..cd747b3b430 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -350,10 +350,10 @@ class Server::SyncRequest final : public internal::CompletionQueueTag { class Server::CallbackRequest final : public internal::CompletionQueueTag { public: - CallbackRequest(Server* server, Server::MethodReqList* list, + CallbackRequest(Server* server, size_t method_idx, internal::RpcServiceMethod* method, void* method_tag) : server_(server), - req_list_(list), + method_index_(method_idx), method_(method), method_tag_(method_tag), has_request_payload_( @@ -428,46 +428,31 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { GPR_ASSERT(!req_->FinalizeResult(&ignored, &new_ok)); GPR_ASSERT(ignored == req_); - bool spawn_new = false; - { - std::unique_lock l(req_->req_list_->reqs_mu); - req_->req_list_->reqs_list.erase(req_->req_list_iterator_); - req_->req_list_->reqs_list_sz--; - if (!ok) { - // The call has been shutdown. - // Delete its contents to free up the request. - // First release the lock in case the deletion of the request - // completes the full server shutdown and allows the destructor - // of the req_list to proceed. - l.unlock(); - delete req_; - return; - } - - // If this was the last request in the list or it is below the soft - // minimum and there are spare requests available, set up a new one, but - // do it outside the lock since the Request could otherwise deadlock - if (req_->req_list_->reqs_list_sz == 0 || - (req_->req_list_->reqs_list_sz < - SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD && - req_->server_->callback_reqs_outstanding_ < - SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING)) { - spawn_new = true; - } + auto count = + static_cast(gpr_atm_no_barrier_fetch_add( + &req_->server_ + ->callback_unmatched_reqs_count_[req_->method_index_], + static_cast(-1))) - + 1; + if (!ok) { + // The call has been shutdown. + // Delete its contents to free up the request. + delete req_; + return; } - if (spawn_new) { - auto* new_req = new CallbackRequest(req_->server_, req_->req_list_, + + // If this was the last request in the list or it is below the soft + // minimum and there are spare requests available, set up a new one. + if (count == 0 || (count < SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD && + count < SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING)) { + auto* new_req = new CallbackRequest(req_->server_, req_->method_index_, req_->method_, req_->method_tag_); if (!new_req->Request()) { - // The server must have just decided to shutdown. Erase - // from the list under lock but release the lock before - // deleting the new_req (in case that request was what - // would allow the destruction of the req_list) - { - std::lock_guard l(new_req->req_list_->reqs_mu); - new_req->req_list_->reqs_list.erase(new_req->req_list_iterator_); - new_req->req_list_->reqs_list_sz--; - } + // The server must have just decided to shutdown. + gpr_atm_no_barrier_fetch_add( + &new_req->server_ + ->callback_unmatched_reqs_count_[new_req->method_index_], + static_cast(-1)); delete new_req; } } @@ -557,20 +542,18 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { } void Setup() { + gpr_atm_no_barrier_fetch_add( + &server_->callback_unmatched_reqs_count_[method_index_], + static_cast(1)); grpc_metadata_array_init(&request_metadata_); ctx_.Setup(gpr_inf_future(GPR_CLOCK_REALTIME)); request_payload_ = nullptr; request_ = nullptr; request_status_ = Status(); - std::lock_guard l(req_list_->reqs_mu); - req_list_->reqs_list.push_front(this); - req_list_->reqs_list_sz++; - req_list_iterator_ = req_list_->reqs_list.begin(); } Server* const server_; - Server::MethodReqList* req_list_; - Server::MethodReqList::iterator req_list_iterator_; + size_t method_index_; internal::RpcServiceMethod* const method_; void* const method_tag_; const bool has_request_payload_; @@ -791,12 +774,11 @@ Server::~Server() { } grpc_server_destroy(server_); - for (auto* method_list : callback_reqs_) { - // The entries of the method_list should have already been emptied - // during Shutdown as each request is failed by Shutdown. Check that - // this actually happened. - GPR_ASSERT(method_list->reqs_list.empty()); - delete method_list; + for (auto per_method_count : callback_unmatched_reqs_count_) { + // There should be no more unmatched callbacks for any method + // as each request is failed by Shutdown. Check that this actually + // happened + GPR_ASSERT(static_cast(per_method_count) == 0); } } @@ -852,6 +834,7 @@ bool Server::RegisterService(const grpc::string* host, Service* service) { } const char* method_name = nullptr; + for (auto it = service->methods_.begin(); it != service->methods_.end(); ++it) { if (it->get() == nullptr) { // Handled by generic service if any. @@ -877,15 +860,15 @@ bool Server::RegisterService(const grpc::string* host, Service* service) { } } else { // a callback method. Register at least some callback requests - callback_reqs_.push_back(new Server::MethodReqList); - auto* method_req_list = callback_reqs_.back(); + callback_unmatched_reqs_count_.push_back(static_cast(0)); + auto method_index = callback_unmatched_reqs_count_.size() - 1; // TODO(vjpai): Register these dynamically based on need for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) { - new CallbackRequest(this, method_req_list, method, - method_registration_tag); + callback_reqs_to_start_.push_back(new CallbackRequest( + this, method_index, method, method_registration_tag)); } - // Enqueue it so that it will be Request'ed later once - // all request matchers are created at core server startup + // Enqueue it so that it will be Request'ed later after all request + // matchers are created at core server startup } method_name = method->name(); @@ -974,11 +957,10 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { (*it)->Start(); } - for (auto* cbmethods : callback_reqs_) { - for (auto* cbreq : cbmethods->reqs_list) { - GPR_ASSERT(cbreq->Request()); - } + for (auto* cbreq : callback_reqs_to_start_) { + GPR_ASSERT(cbreq->Request()); } + callback_reqs_to_start_.clear(); if (default_health_check_service_impl != nullptr) { default_health_check_service_impl->StartServingThread(); From 09cd07cfa066fc0925f5437cec172e1140898868 Mon Sep 17 00:00:00 2001 From: Yihua Zhang Date: Fri, 1 Feb 2019 14:13:19 -0800 Subject: [PATCH 134/218] revision 1 --- src/core/tsi/ssl_transport_security.cc | 3 +-- test/core/tsi/ssl_transport_security_test.cc | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/core/tsi/ssl_transport_security.cc b/src/core/tsi/ssl_transport_security.cc index 5ced404f39d..2107bcaa748 100644 --- a/src/core/tsi/ssl_transport_security.cc +++ b/src/core/tsi/ssl_transport_security.cc @@ -621,7 +621,7 @@ static tsi_result x509_store_load_certs(X509_STORE* cert_store, } ERR_clear_error(); if (!X509_STORE_add_cert(cert_store, root)) { - size_t error = ERR_get_error(); + unsigned long error = ERR_get_error(); if (ERR_GET_LIB(error) != ERR_LIB_X509 || ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { gpr_log(GPR_ERROR, "Could not add root certificate to ssl context."); @@ -632,7 +632,6 @@ static tsi_result x509_store_load_certs(X509_STORE* cert_store, X509_free(root); num_roots++; } - if (num_roots == 0) { gpr_log(GPR_ERROR, "Could not load any root certificate."); result = TSI_INVALID_ARGUMENT; diff --git a/test/core/tsi/ssl_transport_security_test.cc b/test/core/tsi/ssl_transport_security_test.cc index bb69907527c..033618a2d42 100644 --- a/test/core/tsi/ssl_transport_security_test.cc +++ b/test/core/tsi/ssl_transport_security_test.cc @@ -777,7 +777,7 @@ void ssl_tsi_test_handshaker_factory_internals() { } void ssl_tsi_test_duplicate_root_certificates() { - const char* root_cert = load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "ca.pem"); + char* root_cert = load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "ca.pem"); char* dup_root_cert = static_cast( gpr_zalloc(sizeof(char) * (strlen(root_cert) * 2 + 1))); memcpy(dup_root_cert, root_cert, strlen(root_cert)); @@ -787,8 +787,8 @@ void ssl_tsi_test_duplicate_root_certificates() { GPR_ASSERT(root_store != nullptr); // Free memory. tsi_ssl_root_certs_store_destroy(root_store); - gpr_free((void*)root_cert); - gpr_free((void*)dup_root_cert); + gpr_free(root_cert); + gpr_free(dup_root_cert); } int main(int argc, char** argv) { From 3492539b32f84b60f122757777d4255a89507fb9 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Fri, 1 Feb 2019 15:46:32 -0500 Subject: [PATCH 135/218] Use full_fetch_add for ref counting the backup poller. There were spurious TSAN errors on PR #17823 because TSAN doesn't really understand how `g_uncovered_notifications_pending` works. It's odd in the sense that we destroy the backup poller, when the ref count reaches 1 (instead of 0 which is commonly used). Prior to PR #17823, TSAN doesn't complain because we (unnecessarily) always grab the pollset's lock, which TSAN understands. This commit uses full_fetch_add to explain the synchronization primitive to TSAN. --- src/core/lib/iomgr/tcp_posix.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index 792ffd27385..448e5f7b558 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -195,7 +195,7 @@ static void run_poller(void* bp, grpc_error* error_ignored) { static void drop_uncovered(grpc_tcp* tcp) { backup_poller* p = (backup_poller*)gpr_atm_acq_load(&g_backup_poller); gpr_atm old_count = - gpr_atm_no_barrier_fetch_add(&g_uncovered_notifications_pending, -1); + gpr_atm_full_fetch_add(&g_uncovered_notifications_pending, -1); if (grpc_tcp_trace.enabled()) { gpr_log(GPR_INFO, "BACKUP_POLLER:%p uncover cnt %d->%d", p, static_cast(old_count), static_cast(old_count) - 1); From 8521c0394bd950b97aef68d69cc16471aab1472f Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Fri, 1 Feb 2019 15:21:13 -0800 Subject: [PATCH 136/218] Address optional reviewer comments --- include/grpcpp/server.h | 2 +- src/cpp/server/server_cc.cc | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index d1717ce87d2..885bd8de8d7 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -256,7 +256,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { // starts, but this is still a limitation. std::vector callback_unmatched_reqs_count_; - // List of callback requests to start when server actually starts + // List of callback requests to start when server actually starts. std::list callback_reqs_to_start_; // Server status diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index cd747b3b430..21f84de5c1e 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -428,11 +428,11 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { GPR_ASSERT(!req_->FinalizeResult(&ignored, &new_ok)); GPR_ASSERT(ignored == req_); - auto count = + int count = static_cast(gpr_atm_no_barrier_fetch_add( &req_->server_ ->callback_unmatched_reqs_count_[req_->method_index_], - static_cast(-1))) - + -1)) - 1; if (!ok) { // The call has been shutdown. @@ -452,7 +452,7 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { gpr_atm_no_barrier_fetch_add( &new_req->server_ ->callback_unmatched_reqs_count_[new_req->method_index_], - static_cast(-1)); + -1); delete new_req; } } @@ -543,8 +543,7 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { void Setup() { gpr_atm_no_barrier_fetch_add( - &server_->callback_unmatched_reqs_count_[method_index_], - static_cast(1)); + &server_->callback_unmatched_reqs_count_[method_index_], 1); grpc_metadata_array_init(&request_metadata_); ctx_.Setup(gpr_inf_future(GPR_CLOCK_REALTIME)); request_payload_ = nullptr; @@ -774,11 +773,12 @@ Server::~Server() { } grpc_server_destroy(server_); - for (auto per_method_count : callback_unmatched_reqs_count_) { + for (auto& per_method_count : callback_unmatched_reqs_count_) { // There should be no more unmatched callbacks for any method // as each request is failed by Shutdown. Check that this actually // happened - GPR_ASSERT(static_cast(per_method_count) == 0); + GPR_ASSERT(static_cast(gpr_atm_no_barrier_load(&per_method_count)) == + 0); } } @@ -860,7 +860,7 @@ bool Server::RegisterService(const grpc::string* host, Service* service) { } } else { // a callback method. Register at least some callback requests - callback_unmatched_reqs_count_.push_back(static_cast(0)); + callback_unmatched_reqs_count_.push_back(0); auto method_index = callback_unmatched_reqs_count_.size() - 1; // TODO(vjpai): Register these dynamically based on need for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) { From fd185cd1ea07ac282c6ce6e4aed1536e94ce078f Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Thu, 31 Jan 2019 13:28:42 -0800 Subject: [PATCH 137/218] Disable c-ares on iOS --- include/grpc/impl/codegen/port_platform.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index aaeb23694e8..45371847c7a 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -189,6 +189,8 @@ #define GPR_PLATFORM_STRING "ios" #define GPR_CPU_IPHONE 1 #define GPR_PTHREAD_TLS 1 +/* the c-ares resolver isnt safe to enable on iOS */ +#define GRPC_ARES 0 #else /* TARGET_OS_IPHONE */ #define GPR_PLATFORM_STRING "osx" #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED From 82171553cfda63af93077de3e0d47223dfbc517f Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 1 Feb 2019 15:23:44 -0800 Subject: [PATCH 138/218] clang fmt --- test/cpp/util/channel_trace_proto_helper.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc index 80d084f585b..b473b7d7aa5 100644 --- a/test/cpp/util/channel_trace_proto_helper.cc +++ b/test/cpp/util/channel_trace_proto_helper.cc @@ -61,7 +61,7 @@ void VaidateProtoJsonTranslation(char* json_c_str) { EXPECT_EQ(json_str, proto_json_str); } -} // namespace +} // namespace namespace testing { From 28252eb0ddba424b49873d0e7f002eba4a05aecd Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Fri, 1 Feb 2019 15:32:34 -0800 Subject: [PATCH 139/218] force gc in test --- src/python/grpcio_tests/tests/unit/_abort_test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/python/grpcio_tests/tests/unit/_abort_test.py b/src/python/grpcio_tests/tests/unit/_abort_test.py index 7acbf61031e..636f1379ad8 100644 --- a/src/python/grpcio_tests/tests/unit/_abort_test.py +++ b/src/python/grpcio_tests/tests/unit/_abort_test.py @@ -15,6 +15,7 @@ import unittest import collections +import gc import logging import weakref @@ -124,6 +125,8 @@ class AbortTest(unittest.TestCase): rpc_error = exception_context.exception do_not_leak_me = None + # Force garbage collection + gc.collect() self.assertIsNone(weak_ref()) def test_abort_with_status(self): From 6b19927bc4cfeffc617509681d1e5b9d097ac252 Mon Sep 17 00:00:00 2001 From: Prashant Jaikumar Date: Thu, 3 Jan 2019 13:27:20 -0800 Subject: [PATCH 140/218] Bad connection test --- CMakeLists.txt | 39 + Makefile | 36 + build.yaml | 15 + test/core/bad_connection/BUILD | 32 + test/core/bad_connection/close_fd_test.cc | 764 ++++++++++++++++++ .../generated/sources_and_headers.json | 16 + tools/run_tests/generated/tests.json | 24 + 7 files changed, 926 insertions(+) create mode 100644 test/core/bad_connection/BUILD create mode 100644 test/core/bad_connection/close_fd_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 9813eec7062..ad7911ce702 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -257,6 +257,9 @@ add_dependencies(buildtests_c channel_create_test) add_dependencies(buildtests_c chttp2_hpack_encoder_test) add_dependencies(buildtests_c chttp2_stream_map_test) add_dependencies(buildtests_c chttp2_varint_test) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) +add_dependencies(buildtests_c close_fd_test) +endif() add_dependencies(buildtests_c cmdline_test) add_dependencies(buildtests_c combiner_test) add_dependencies(buildtests_c compression_test) @@ -6302,6 +6305,42 @@ target_link_libraries(chttp2_varint_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + +add_executable(close_fd_test + test/core/bad_connection/close_fd_test.cc +) + + +target_include_directories(close_fd_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(close_fd_test + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr +) + + # avoid dependency on libstdc++ + if (_gRPC_CORE_NOSTDCXX_FLAGS) + set_target_properties(close_fd_test PROPERTIES LINKER_LANGUAGE C) + target_compile_options(close_fd_test PRIVATE $<$:${_gRPC_CORE_NOSTDCXX_FLAGS}>) + endif() + +endif() +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) add_executable(cmdline_test test/core/util/cmdline_test.cc diff --git a/Makefile b/Makefile index b9b7ab4c254..2eea2337e54 100644 --- a/Makefile +++ b/Makefile @@ -986,6 +986,7 @@ chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test client_fuzzer: $(BINDIR)/$(CONFIG)/client_fuzzer +close_fd_test: $(BINDIR)/$(CONFIG)/close_fd_test cmdline_test: $(BINDIR)/$(CONFIG)/cmdline_test combiner_test: $(BINDIR)/$(CONFIG)/combiner_test compression_test: $(BINDIR)/$(CONFIG)/compression_test @@ -1450,6 +1451,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \ $(BINDIR)/$(CONFIG)/chttp2_stream_map_test \ $(BINDIR)/$(CONFIG)/chttp2_varint_test \ + $(BINDIR)/$(CONFIG)/close_fd_test \ $(BINDIR)/$(CONFIG)/cmdline_test \ $(BINDIR)/$(CONFIG)/combiner_test \ $(BINDIR)/$(CONFIG)/compression_test \ @@ -1988,6 +1990,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/chttp2_stream_map_test || ( echo test chttp2_stream_map_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_varint_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_varint_test || ( echo test chttp2_varint_test failed ; exit 1 ) + $(E) "[RUN] Testing close_fd_test" + $(Q) $(BINDIR)/$(CONFIG)/close_fd_test || ( echo test close_fd_test failed ; exit 1 ) $(E) "[RUN] Testing cmdline_test" $(Q) $(BINDIR)/$(CONFIG)/cmdline_test || ( echo test cmdline_test failed ; exit 1 ) $(E) "[RUN] Testing combiner_test" @@ -11123,6 +11127,38 @@ endif endif +CLOSE_FD_TEST_SRC = \ + test/core/bad_connection/close_fd_test.cc \ + +CLOSE_FD_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CLOSE_FD_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/close_fd_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/close_fd_test: $(CLOSE_FD_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) $(CLOSE_FD_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/close_fd_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/bad_connection/close_fd_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_close_fd_test: $(CLOSE_FD_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CLOSE_FD_TEST_OBJS:.o=.dep) +endif +endif + + CMDLINE_TEST_SRC = \ test/core/util/cmdline_test.cc \ diff --git a/build.yaml b/build.yaml index 0946e853d1b..f9085f3ee5b 100644 --- a/build.yaml +++ b/build.yaml @@ -2246,6 +2246,21 @@ targets: - test/core/end2end/fuzzers/client_fuzzer_corpus dict: test/core/end2end/fuzzers/hpack.dictionary maxlen: 2048 +- name: close_fd_test + build: test + language: c + src: + - test/core/bad_connection/close_fd_test.cc + deps: + - grpc_test_util + - grpc + - gpr + exclude_configs: + - tsan + platforms: + - mac + - linux + - posix - name: cmdline_test build: test language: c diff --git a/test/core/bad_connection/BUILD b/test/core/bad_connection/BUILD new file mode 100644 index 00000000000..8ada933e796 --- /dev/null +++ b/test/core/bad_connection/BUILD @@ -0,0 +1,32 @@ +# 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. + +load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary", "grpc_package") + +licenses(["notice"]) # Apache v2 + +grpc_package(name = "test/core/bad_connection") + +grpc_cc_binary( + name = "close_fd_test", + srcs = [ + "close_fd_test.cc", + ], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:grpc_test_util", + ], +) diff --git a/test/core/bad_connection/close_fd_test.cc b/test/core/bad_connection/close_fd_test.cc new file mode 100644 index 00000000000..317526a563a --- /dev/null +++ b/test/core/bad_connection/close_fd_test.cc @@ -0,0 +1,764 @@ +/* + * + * Copyright 2019 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. + * + * close_fd_test tests the behavior of grpc core when the transport gets + * disconnected. + * The test creates an http2 transport over a socket pair and closes the + * client or server file descriptor to simulate connection breakage while + * an RPC call is in progress. + * + */ +#include "src/core/lib/iomgr/port.h" + +// This test won't work except with posix sockets enabled +#ifdef GRPC_POSIX_SOCKET + +#include "test/core/util/test_config.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/iomgr/endpoint_pair.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/completion_queue.h" +#include "src/core/lib/surface/server.h" + +static void* tag(intptr_t t) { return (void*)t; } + +typedef struct test_ctx test_ctx; + +struct test_ctx { + /* completion queue for call notifications on the server */ + grpc_completion_queue* cq; + /* completion queue registered to server for shutdown events */ + grpc_completion_queue* shutdown_cq; + /* client's completion queue */ + grpc_completion_queue* client_cq; + /* completion queue bound to call on the server */ + grpc_completion_queue* bound_cq; + /* Server responds to client calls */ + grpc_server* server; + /* Client calls are sent over the channel */ + grpc_channel* client; + /* encapsulates client, server endpoints */ + grpc_endpoint_pair* ep; +}; + +static test_ctx g_ctx; + +/* chttp2 transport that is immediately available (used for testing + connected_channel without a client_channel */ + +static void server_setup_transport(grpc_transport* transport) { + grpc_core::ExecCtx exec_ctx; + grpc_endpoint_add_to_pollset(g_ctx.ep->server, grpc_cq_pollset(g_ctx.cq)); + grpc_server_setup_transport(g_ctx.server, transport, nullptr, + grpc_server_get_channel_args(g_ctx.server), + nullptr); +} + +static void client_setup_transport(grpc_transport* transport) { + grpc_core::ExecCtx exec_ctx; + grpc_endpoint_add_to_pollset(g_ctx.ep->client, + grpc_cq_pollset(g_ctx.client_cq)); + grpc_arg authority_arg = grpc_channel_arg_string_create( + const_cast(GRPC_ARG_DEFAULT_AUTHORITY), + const_cast("test-authority")); + grpc_channel_args* args = + grpc_channel_args_copy_and_add(nullptr, &authority_arg, 1); + /* TODO (pjaikumar): use GRPC_CLIENT_CHANNEL instead of + * GRPC_CLIENT_DIRECT_CHANNEL */ + g_ctx.client = grpc_channel_create("socketpair-target", args, + GRPC_CLIENT_DIRECT_CHANNEL, transport); + grpc_channel_args_destroy(args); +} + +static void init_client() { + grpc_core::ExecCtx exec_ctx; + grpc_transport* transport; + transport = grpc_create_chttp2_transport(nullptr, g_ctx.ep->client, true); + client_setup_transport(transport); + GPR_ASSERT(g_ctx.client); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); +} + +static void init_server() { + grpc_core::ExecCtx exec_ctx; + grpc_transport* transport; + GPR_ASSERT(!g_ctx.server); + g_ctx.server = grpc_server_create(nullptr, nullptr); + grpc_server_register_completion_queue(g_ctx.server, g_ctx.cq, nullptr); + grpc_server_start(g_ctx.server); + transport = grpc_create_chttp2_transport(nullptr, g_ctx.ep->server, false); + server_setup_transport(transport); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); +} + +static void test_init() { + grpc_endpoint_pair* sfd = + static_cast(gpr_malloc(sizeof(grpc_endpoint_pair))); + memset(&g_ctx, 0, sizeof(g_ctx)); + g_ctx.ep = sfd; + g_ctx.cq = grpc_completion_queue_create_for_next(nullptr); + g_ctx.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr); + g_ctx.bound_cq = grpc_completion_queue_create_for_next(nullptr); + g_ctx.client_cq = grpc_completion_queue_create_for_next(nullptr); + + /* Create endpoints */ + *sfd = grpc_iomgr_create_endpoint_pair("fixture", nullptr); + /* Create client, server and setup transport over endpoint pair */ + init_server(); + init_client(); +} + +static void drain_cq(grpc_completion_queue* cq) { + grpc_event event; + do { + event = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(1), + nullptr); + } while (event.type != GRPC_QUEUE_SHUTDOWN); +} + +static void drain_and_destroy_cq(grpc_completion_queue* cq) { + grpc_completion_queue_shutdown(cq); + drain_cq(cq); + grpc_completion_queue_destroy(cq); +} + +static void shutdown_server() { + if (!g_ctx.server) return; + grpc_server_shutdown_and_notify(g_ctx.server, g_ctx.shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(g_ctx.shutdown_cq, tag(1000), + grpc_timeout_seconds_to_deadline(1), + nullptr) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(g_ctx.server); + g_ctx.server = nullptr; +} + +static void shutdown_client() { + if (!g_ctx.client) return; + grpc_channel_destroy(g_ctx.client); + g_ctx.client = nullptr; +} + +static void end_test() { + shutdown_server(); + shutdown_client(); + + drain_and_destroy_cq(g_ctx.cq); + drain_and_destroy_cq(g_ctx.client_cq); + drain_and_destroy_cq(g_ctx.bound_cq); + grpc_completion_queue_destroy(g_ctx.shutdown_cq); + gpr_free(g_ctx.ep); +} + +typedef enum fd_type { CLIENT_FD, SERVER_FD } fd_type; + +static const char* fd_type_str(fd_type fdtype) { + if (fdtype == CLIENT_FD) { + return "client"; + } else if (fdtype == SERVER_FD) { + return "server"; + } else { + gpr_log(GPR_ERROR, "Unexpected fd_type %d", fdtype); + abort(); + } +} + +static void _test_close_before_server_recv(fd_type fdtype) { + grpc_core::ExecCtx exec_ctx; + grpc_call* call; + grpc_call* server_call; + grpc_event event; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer* request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer* response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + gpr_log(GPR_INFO, "Running test: test_close_%s_before_server_recv", + fd_type_str(fdtype)); + test_init(); + + 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_byte_buffer* response_payload_recv = nullptr; + grpc_call_details call_details; + grpc_status_code status = GRPC_STATUS__DO_NOT_USE; + grpc_call_error error; + grpc_slice details; + + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(1); + call = grpc_channel_create_call( + g_ctx.client, nullptr, GRPC_PROPAGATE_DEFAULTS, g_ctx.client_cq, + grpc_slice_from_static_string("/foo"), nullptr, deadline, nullptr); + GPR_ASSERT(call); + + 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_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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(call, ops, static_cast(op - ops), + tag(1), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + error = grpc_server_request_call(g_ctx.server, &server_call, &call_details, + &request_metadata_recv, g_ctx.bound_cq, + g_ctx.cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + event = grpc_completion_queue_next( + g_ctx.cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.tag == tag(101)); + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + + 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_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + + grpc_endpoint_pair* sfd = g_ctx.ep; + int fd; + if (fdtype == SERVER_FD) { + fd = sfd->server->vtable->get_fd(sfd->server); + } else { + GPR_ASSERT(fdtype == CLIENT_FD); + fd = sfd->client->vtable->get_fd(sfd->client); + } + /* Connection is closed before the server receives the client's message. */ + close(fd); + + error = grpc_call_start_batch(server_call, ops, static_cast(op - ops), + tag(102), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + event = grpc_completion_queue_next( + g_ctx.bound_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + + /* Batch operation completes on the server side. + * event.success will be true if the op completes successfully. + * event.success will be false if the op completes with an error. This can + * happen due to a race with closing the fd resulting in pending writes + * failing due to stream closure. + * */ + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + GPR_ASSERT(event.tag == tag(102)); + + event = grpc_completion_queue_next( + g_ctx.client_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + /* When the client fd is closed, the server gets EPIPE. + * When server fd is closed, server gets EBADF. + * In both cases server sends GRPC_STATUS_UNAVALABLE to the client. However, + * the client may not receive this grpc_status as it's socket is being closed. + * If the client didn't get grpc_status from the server it will time out + * waiting on the completion queue. So there 2 2 possibilities: + * 1. client times out waiting for server's response + * 2. client receives GRPC_STATUS_UNAVAILABLE from server + */ + if (event.type == GRPC_QUEUE_TIMEOUT) { + GPR_ASSERT(event.success == 0); + GPR_ASSERT(event.tag == nullptr); + /* status is not initialized */ + GPR_ASSERT(status == GRPC_STATUS__DO_NOT_USE); + } else { + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.tag == tag(1)); + GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + } + + 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(call); + grpc_call_unref(server_call); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + + end_test(); +} + +static void test_close_before_server_recv() { + /* Close client side of the connection before server receives message from + * client */ + _test_close_before_server_recv(CLIENT_FD); + /* Close server side of the connection before server receives message from + * client */ + _test_close_before_server_recv(SERVER_FD); +} + +static void _test_close_before_server_send(fd_type fdtype) { + grpc_core::ExecCtx exec_ctx; + grpc_call* call; + grpc_call* server_call; + grpc_event event; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer* request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer* response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + gpr_log(GPR_INFO, "Running test: test_close_%s_before_server_send", + fd_type_str(fdtype)); + test_init(); + + 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_byte_buffer* response_payload_recv = nullptr; + grpc_call_details call_details; + grpc_status_code status = GRPC_STATUS__DO_NOT_USE; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(1); + call = grpc_channel_create_call( + g_ctx.client, nullptr, GRPC_PROPAGATE_DEFAULTS, g_ctx.client_cq, + grpc_slice_from_static_string("/foo"), nullptr, deadline, nullptr); + GPR_ASSERT(call); + + 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_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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(call, ops, static_cast(op - ops), + tag(1), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + error = grpc_server_request_call(g_ctx.server, &server_call, &call_details, + &request_metadata_recv, g_ctx.bound_cq, + g_ctx.cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + event = grpc_completion_queue_next( + g_ctx.cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.tag == tag(101)); + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + + 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_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(server_call, ops, static_cast(op - ops), + tag(102), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + event = grpc_completion_queue_next( + g_ctx.bound_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.tag == tag(102)); + + memset(ops, 0, sizeof(ops)); + 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_MESSAGE; + op->data.send_message.send_message = response_payload; + 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++; + + grpc_endpoint_pair* sfd = g_ctx.ep; + int fd; + if (fdtype == SERVER_FD) { + fd = sfd->server->vtable->get_fd(sfd->server); + } else { + GPR_ASSERT(fdtype == CLIENT_FD); + fd = sfd->client->vtable->get_fd(sfd->client); + } + + /* Connection is closed before the server sends message and status to the + * client. */ + close(fd); + error = grpc_call_start_batch(server_call, ops, static_cast(op - ops), + tag(103), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* Batch operation succeeds on the server side */ + event = grpc_completion_queue_next( + g_ctx.bound_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.tag == tag(103)); + + event = grpc_completion_queue_next( + g_ctx.client_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + /* In both cases server sends GRPC_STATUS_UNAVALABLE to the client. However, + * the client may not receive this grpc_status as it's socket is being closed. + * If the client didn't get grpc_status from the server it will time out + * waiting on the completion queue + */ + if (event.type == GRPC_OP_COMPLETE) { + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.tag == tag(1)); + GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + } else { + GPR_ASSERT(event.type == GRPC_QUEUE_TIMEOUT); + GPR_ASSERT(event.success == 0); + GPR_ASSERT(event.tag == nullptr); + /* status is not initialized */ + GPR_ASSERT(status == GRPC_STATUS__DO_NOT_USE); + } + GPR_ASSERT(was_cancelled == 0); + + 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(call); + grpc_call_unref(server_call); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + + end_test(); +} + +static void test_close_before_server_send() { + /* Close client side of the connection before server sends message to client + * */ + _test_close_before_server_send(CLIENT_FD); + /* Close server side of the connection before server sends message to client + * */ + _test_close_before_server_send(SERVER_FD); +} + +static void _test_close_before_client_send(fd_type fdtype) { + grpc_core::ExecCtx exec_ctx; + grpc_call* call; + grpc_event event; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + grpc_byte_buffer* request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer* response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + gpr_log(GPR_INFO, "Running test: test_close_%s_before_client_send", + fd_type_str(fdtype)); + test_init(); + + 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_byte_buffer* response_payload_recv = nullptr; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + + gpr_timespec deadline = grpc_timeout_seconds_to_deadline(1); + call = grpc_channel_create_call( + g_ctx.client, nullptr, GRPC_PROPAGATE_DEFAULTS, g_ctx.client_cq, + grpc_slice_from_static_string("/foo"), nullptr, deadline, nullptr); + GPR_ASSERT(call); + + 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_MESSAGE; + op->data.recv_message.recv_message = &response_payload_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++; + + grpc_endpoint_pair* sfd = g_ctx.ep; + int fd; + if (fdtype == SERVER_FD) { + fd = sfd->server->vtable->get_fd(sfd->server); + } else { + GPR_ASSERT(fdtype == CLIENT_FD); + fd = sfd->client->vtable->get_fd(sfd->client); + } + /* Connection is closed before the client sends a batch to the server */ + close(fd); + + error = grpc_call_start_batch(call, ops, static_cast(op - ops), + tag(1), nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* Status unavailable is returned to the client when client or server fd is + * closed */ + event = grpc_completion_queue_next( + g_ctx.client_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.success == 1); + GPR_ASSERT(event.type == GRPC_OP_COMPLETE); + GPR_ASSERT(event.tag == tag(1)); + GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + + /* No event is received on the server */ + event = grpc_completion_queue_next( + g_ctx.cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.success == 0); + GPR_ASSERT(event.type == GRPC_QUEUE_TIMEOUT); + GPR_ASSERT(event.tag == nullptr); + + 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(call); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + + end_test(); +} +static void test_close_before_client_send() { + /* Close client side of the connection before client sends message to server + * */ + _test_close_before_client_send(CLIENT_FD); + /* Close server side of the connection before client sends message to server + * */ + _test_close_before_client_send(SERVER_FD); +} + +static void _test_close_before_call_create(fd_type fdtype) { + grpc_core::ExecCtx exec_ctx; + grpc_call* call; + grpc_event event; + test_init(); + + gpr_timespec deadline = grpc_timeout_milliseconds_to_deadline(100); + + grpc_endpoint_pair* sfd = g_ctx.ep; + int fd; + if (fdtype == SERVER_FD) { + fd = sfd->server->vtable->get_fd(sfd->server); + } else { + GPR_ASSERT(fdtype == CLIENT_FD); + fd = sfd->client->vtable->get_fd(sfd->client); + } + /* Connection is closed before the client creates a call */ + close(fd); + + call = grpc_channel_create_call( + g_ctx.client, nullptr, GRPC_PROPAGATE_DEFAULTS, g_ctx.client_cq, + grpc_slice_from_static_string("/foo"), nullptr, deadline, nullptr); + GPR_ASSERT(call); + + /* Client and server time out waiting on their completion queues and nothing + * is sent or received */ + event = grpc_completion_queue_next( + g_ctx.client_cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.type == GRPC_QUEUE_TIMEOUT); + GPR_ASSERT(event.success == 0); + GPR_ASSERT(event.tag == nullptr); + + event = grpc_completion_queue_next( + g_ctx.cq, grpc_timeout_milliseconds_to_deadline(100), nullptr); + GPR_ASSERT(event.type == GRPC_QUEUE_TIMEOUT); + GPR_ASSERT(event.success == 0); + GPR_ASSERT(event.tag == nullptr); + + grpc_call_unref(call); + end_test(); +} + +static void test_close_before_call_create() { + /* Close client side of the connection before client creates a call */ + _test_close_before_call_create(CLIENT_FD); + /* Close server side of the connection before client creates a call */ + _test_close_before_call_create(SERVER_FD); +} + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + /* Init grpc */ + grpc_init(); + int iterations = 10; + + for (int i = 0; i < iterations; ++i) { + test_close_before_call_create(); + test_close_before_client_send(); + test_close_before_server_recv(); + test_close_before_server_send(); + } + + grpc_shutdown(); + + return 0; +} + +#else /* GRPC_POSIX_SOCKET */ + +int main(int argc, char** argv) { return 1; } + +#endif /* GRPC_POSIX_SOCKET */ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 9e07c548b69..506b64c19fc 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -271,6 +271,22 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "close_fd_test", + "src": [ + "test/core/bad_connection/close_fd_test.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 b41fef6b795..9a1ff126a29 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -311,6 +311,30 @@ ], "uses_polling": false }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "close_fd_test", + "platforms": [ + "linux", + "mac", + "posix" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, From c0125a7cd4eda6cb7cf9e35733c6671cb8addc53 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Fri, 1 Feb 2019 16:58:21 -0800 Subject: [PATCH 141/218] Unskip google default creds for Go and Java in cloud to prod tests --- tools/run_tests/run_interop_tests.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index 603977545ce..11bd959052e 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -229,7 +229,7 @@ class JavaLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_GOOGLE_DEFAULT_CREDS + return [] def unimplemented_test_cases_server(self): return _SKIP_COMPRESSION @@ -254,7 +254,7 @@ class JavaOkHttpClient: return {} def unimplemented_test_cases(self): - return _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS + return _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE def __str__(self): return 'javaokhttp' @@ -285,7 +285,7 @@ class GoLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_COMPRESSION + _SKIP_GOOGLE_DEFAULT_CREDS + return _SKIP_COMPRESSION def unimplemented_test_cases_server(self): return _SKIP_COMPRESSION From 95fe85f090a2c3a26156ce1c1f96368abb9494db Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Fri, 1 Feb 2019 23:32:37 -0800 Subject: [PATCH 142/218] Revert "Fix for 17338. Delay shutdown of buffer list till tcp_free to avoid races" --- src/core/lib/iomgr/tcp_posix.cc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index 61db36bd99e..448e5f7b558 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -343,13 +343,6 @@ static void tcp_free(grpc_tcp* tcp) { grpc_slice_buffer_destroy_internal(&tcp->last_read_buffer); grpc_resource_user_unref(tcp->resource_user); gpr_free(tcp->peer_string); - /* The lock is not really necessary here, since all refs have been released */ - gpr_mu_lock(&tcp->tb_mu); - grpc_core::TracedBuffer::Shutdown( - &tcp->tb_head, tcp->outgoing_buffer_arg, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); - gpr_mu_unlock(&tcp->tb_mu); - tcp->outgoing_buffer_arg = nullptr; gpr_mu_destroy(&tcp->tb_mu); gpr_free(tcp); } @@ -396,6 +389,12 @@ static void tcp_destroy(grpc_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()) { + gpr_mu_lock(&tcp->tb_mu); + grpc_core::TracedBuffer::Shutdown( + &tcp->tb_head, tcp->outgoing_buffer_arg, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); + gpr_mu_unlock(&tcp->tb_mu); + tcp->outgoing_buffer_arg = nullptr; gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); grpc_fd_set_error(tcp->em_fd); } @@ -1185,6 +1184,12 @@ void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd, grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); if (grpc_event_engine_can_track_errors()) { /* Stop errors notification. */ + gpr_mu_lock(&tcp->tb_mu); + grpc_core::TracedBuffer::Shutdown( + &tcp->tb_head, tcp->outgoing_buffer_arg, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); + gpr_mu_unlock(&tcp->tb_mu); + tcp->outgoing_buffer_arg = nullptr; gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); grpc_fd_set_error(tcp->em_fd); } From 92d37b1273bff03156803f8431903461c799983c Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Sat, 2 Feb 2019 09:14:05 -0800 Subject: [PATCH 143/218] SOFT_MAXIMUM is supposed to be per-server, not per-method --- src/cpp/server/server_cc.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 21f84de5c1e..05f78dbe6fe 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -444,7 +444,8 @@ class Server::CallbackRequest final : public internal::CompletionQueueTag { // If this was the last request in the list or it is below the soft // minimum and there are spare requests available, set up a new one. if (count == 0 || (count < SOFT_MINIMUM_SPARE_CALLBACK_REQS_PER_METHOD && - count < SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING)) { + req_->server_->callback_reqs_outstanding_ < + SOFT_MAXIMUM_CALLBACK_REQS_OUTSTANDING)) { auto* new_req = new CallbackRequest(req_->server_, req_->method_index_, req_->method_, req_->method_tag_); if (!new_req->Request()) { From f37e18b8fd1728c8bfadfd139e324438e964a981 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Sat, 2 Feb 2019 10:09:36 -0800 Subject: [PATCH 144/218] Dummy Shutdown should still unref the error --- src/core/lib/iomgr/buffer_list.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/lib/iomgr/buffer_list.h b/src/core/lib/iomgr/buffer_list.h index 215ab03a563..3dba15312d6 100644 --- a/src/core/lib/iomgr/buffer_list.h +++ b/src/core/lib/iomgr/buffer_list.h @@ -148,7 +148,9 @@ class TracedBuffer { public: /* Dummy shutdown function */ static void Shutdown(grpc_core::TracedBuffer** head, void* remaining, - grpc_error* shutdown_err) {} + grpc_error* shutdown_err) { + GRPC_ERROR_UNREF(shutdown_err); + } }; #endif /* GRPC_LINUX_ERRQUEUE */ From e83e463b5a14cf0de5d8c9e1197d06f925160111 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Sat, 26 Jan 2019 16:23:30 -0500 Subject: [PATCH 145/218] Track the pollsets of an FD in PO_MULTI mode for pollex. Each pollset in pollex has a lock, grabbed upon adding an FD to the pollset. Since this is called on a per-call basis, there is a flat array caching the FDs of the pollset, to avoid unnecessarily calling epoll_ctl multiple times for the same FD. This has two problems: 1) When multiple threads add FDs to the same pollset, we will have contention on the pollset lock. 2) When we have many FDs we simply run out of cache storage, and call epoll_ctl(). This commit changes the caching strategy by simply storing the pollsets of an FD inside that FD, when we are in PO_MULTI mode. This results in address in both (1) and (2). Moreover, this commit fixes another performance bug. When we have a release FD callback, we do not call close(). That FD will remain in our epollset, until the new owner of the FD actually call close(). This results in a lot of spurious wake ups when we simply hand off gRPC FDs to other FDs. --- src/core/lib/iomgr/ev_epollex_linux.cc | 300 ++++++++++++------------- 1 file changed, 138 insertions(+), 162 deletions(-) diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index 0a0891013af..d6947d00e84 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -45,6 +45,7 @@ #include "src/core/lib/gpr/spinlock.h" #include "src/core/lib/gpr/tls.h" #include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/iomgr/block_annotate.h" @@ -78,18 +79,6 @@ typedef enum { PO_MULTI, PO_FD, PO_EMPTY } pollable_type; typedef struct pollable pollable; -typedef struct cached_fd { - // Set to the grpc_fd's salt value. See 'salt' variable' in grpc_fd for more - // details - intptr_t salt; - - // The underlying fd - int fd; - - // A recency time counter that helps to determine the LRU fd in the cache - uint64_t last_used; -} cached_fd; - /// A pollable is something that can be polled: it has an epoll set to poll on, /// and a wakeup fd for kicks /// There are three broad types: @@ -120,33 +109,6 @@ struct pollable { int event_cursor; int event_count; struct epoll_event events[MAX_EPOLL_EVENTS]; - - // We may be calling pollable_add_fd() on the same (pollable, fd) multiple - // times. To prevent pollable_add_fd() from making multiple sys calls to - // epoll_ctl() to add the fd, we maintain a cache of what fds are already - // present in the underlying epoll-set. - // - // Since this is not a correctness issue, we do not need to maintain all the - // fds in the cache. Hence we just use an LRU cache of size 'MAX_FDS_IN_CACHE' - // - // NOTE: An ideal implementation of this should do the following: - // 1) Add fds to the cache in pollable_add_fd() function (i.e whenever the fd - // is added to the pollable's epoll set) - // 2) Remove the fd from the cache whenever the fd is removed from the - // underlying epoll set (i.e whenever fd_orphan() is called). - // - // Implementing (2) above (i.e removing fds from cache on fd_orphan) adds a - // lot of complexity since an fd can be present in multiple pollables. So our - // implementation ONLY DOES (1) and NOT (2). - // - // The cache_fd.salt variable helps here to maintain correctness (it serves as - // an epoch that differentiates one grpc_fd from the other even though both of - // them may have the same fd number) - // - // The following implements LRU-eviction cache of fds in this pollable - cached_fd fd_cache[MAX_FDS_IN_CACHE]; - int fd_cache_size; - uint64_t fd_cache_counter; // Recency timer tick counter }; static const char* pollable_type_string(pollable_type t) { @@ -189,37 +151,86 @@ static void pollable_unref(pollable* p, int line, const char* reason); * Fd Declarations */ -// Monotonically increasing Epoch counter that is assinged to each grpc_fd. See -// the description of 'salt' variable in 'grpc_fd' for more details -// TODO: (sreek/kpayson) gpr_atm is intptr_t which may not be wide-enough on -// 32-bit systems. Change this to int_64 - atleast on 32-bit systems -static gpr_atm g_fd_salt; - struct grpc_fd { - int fd; + grpc_fd(int fd, const char* name, bool track_err) + : fd(fd), track_err(track_err) { + gpr_mu_init(&orphan_mu); + gpr_mu_init(&pollable_mu); + read_closure.InitEvent(); + write_closure.InitEvent(); + error_closure.InitEvent(); + + char* fd_name; + gpr_asprintf(&fd_name, "%s fd=%d", name, fd); + grpc_iomgr_register_object(&iomgr_object, fd_name); +#ifndef NDEBUG + if (grpc_trace_fd_refcount.enabled()) { + gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, this, fd_name); + } +#endif + gpr_free(fd_name); + } + + // This is really the dtor, but the poller threads waking up from + // epoll_wait() may access the (read|write|error)_closure after destruction. + // Since the object will be added to the free pool, this behavior is + // not going to cause issues, except spurious events if the FD is reused + // while the race happens. + void destroy() { + grpc_iomgr_unregister_object(&iomgr_object); + + POLLABLE_UNREF(pollable_obj, "fd_pollable"); + pollsets.clear(); + gpr_mu_destroy(&pollable_mu); + gpr_mu_destroy(&orphan_mu); + + read_closure.DestroyEvent(); + write_closure.DestroyEvent(); + error_closure.DestroyEvent(); + + invalidate(); + } - // Since fd numbers can be reused (after old fds are closed), this serves as - // an epoch that uniquely identifies this fd (i.e the pair (salt, fd) is - // unique (until the salt counter (i.e g_fd_salt) overflows) - intptr_t salt; +#ifndef NDEBUG + /* Since an fd is never really destroyed (i.e gpr_free() is not called), it is + * hard-to-debug cases where fd fields are accessed even after calling + * fd_destroy(). The following invalidates fd fields to make catching such + * errors easier */ + void invalidate() { + fd = -1; + gpr_atm_no_barrier_store(&refst, -1); + memset(&orphan_mu, -1, sizeof(orphan_mu)); + memset(&pollable_mu, -1, sizeof(pollable_mu)); + pollable_obj = nullptr; + on_done_closure = nullptr; + memset(&iomgr_object, -1, sizeof(iomgr_object)); + track_err = false; + } +#else + void invalidate() {} +#endif + + int fd; // refst format: // bit 0 : 1=Active / 0=Orphaned // bits 1-n : refcount // Ref/Unref by two to avoid altering the orphaned bit - gpr_atm refst; + gpr_atm refst = 1; gpr_mu orphan_mu; + // Protects pollable_obj and pollsets. gpr_mu pollable_mu; - pollable* pollable_obj; + grpc_core::InlinedVector pollsets; // Used in PO_MULTI. + pollable* pollable_obj = nullptr; // Used in PO_FD. - grpc_core::ManualConstructor read_closure; - grpc_core::ManualConstructor write_closure; - grpc_core::ManualConstructor error_closure; + grpc_core::LockfreeEvent read_closure; + grpc_core::LockfreeEvent write_closure; + grpc_core::LockfreeEvent error_closure; - struct grpc_fd* freelist_next; - grpc_closure* on_done_closure; + struct grpc_fd* freelist_next = nullptr; + grpc_closure* on_done_closure = nullptr; grpc_iomgr_object iomgr_object; @@ -258,6 +269,7 @@ struct grpc_pollset_worker { struct grpc_pollset { gpr_mu mu; gpr_atm worker_count; + gpr_atm active_pollable_type; pollable* active_pollable; bool kicked_without_poller; grpc_closure* shutdown_closure; @@ -337,39 +349,10 @@ static void ref_by(grpc_fd* fd, int n) { GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); } -#ifndef NDEBUG -#define INVALIDATE_FD(fd) invalidate_fd(fd) -/* Since an fd is never really destroyed (i.e gpr_free() is not called), it is - * hard to cases where fd fields are accessed even after calling fd_destroy(). - * The following invalidates fd fields to make catching such errors easier */ -static void invalidate_fd(grpc_fd* fd) { - fd->fd = -1; - fd->salt = -1; - gpr_atm_no_barrier_store(&fd->refst, -1); - memset(&fd->orphan_mu, -1, sizeof(fd->orphan_mu)); - memset(&fd->pollable_mu, -1, sizeof(fd->pollable_mu)); - fd->pollable_obj = nullptr; - fd->on_done_closure = nullptr; - memset(&fd->iomgr_object, -1, sizeof(fd->iomgr_object)); - fd->track_err = false; -} -#else -#define INVALIDATE_FD(fd) -#endif - /* Uninitialize and add to the freelist */ static void fd_destroy(void* arg, grpc_error* error) { grpc_fd* fd = static_cast(arg); - grpc_iomgr_unregister_object(&fd->iomgr_object); - POLLABLE_UNREF(fd->pollable_obj, "fd_pollable"); - gpr_mu_destroy(&fd->pollable_mu); - gpr_mu_destroy(&fd->orphan_mu); - - fd->read_closure->DestroyEvent(); - fd->write_closure->DestroyEvent(); - fd->error_closure->DestroyEvent(); - - INVALIDATE_FD(fd); + fd->destroy(); /* Add the fd to the freelist */ gpr_mu_lock(&fd_freelist_mu); @@ -429,35 +412,9 @@ static grpc_fd* fd_create(int fd, const char* name, bool track_err) { if (new_fd == nullptr) { new_fd = static_cast(gpr_malloc(sizeof(grpc_fd))); - new_fd->read_closure.Init(); - new_fd->write_closure.Init(); - new_fd->error_closure.Init(); - } - - new_fd->fd = fd; - new_fd->salt = gpr_atm_no_barrier_fetch_add(&g_fd_salt, 1); - gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); - gpr_mu_init(&new_fd->orphan_mu); - gpr_mu_init(&new_fd->pollable_mu); - new_fd->pollable_obj = nullptr; - new_fd->read_closure->InitEvent(); - new_fd->write_closure->InitEvent(); - new_fd->error_closure->InitEvent(); - new_fd->freelist_next = nullptr; - new_fd->on_done_closure = nullptr; - - char* fd_name; - gpr_asprintf(&fd_name, "%s fd=%d", name, fd); - grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); -#ifndef NDEBUG - if (grpc_trace_fd_refcount.enabled()) { - gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, new_fd, fd_name); } -#endif - gpr_free(fd_name); - new_fd->track_err = track_err; - return new_fd; + return new (new_fd) grpc_fd(fd, name, track_err); } static int fd_wrapped_fd(grpc_fd* fd) { @@ -465,6 +422,7 @@ static int fd_wrapped_fd(grpc_fd* fd) { return (gpr_atm_acq_load(&fd->refst) & 1) ? ret_fd : -1; } +static int pollset_epoll_fd_locked(grpc_pollset* pollset); static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, const char* reason) { bool is_fd_closed = false; @@ -475,7 +433,6 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, // true so that the pollable will no longer access its owner_fd field. gpr_mu_lock(&fd->pollable_mu); pollable* pollable_obj = fd->pollable_obj; - gpr_mu_unlock(&fd->pollable_mu); if (pollable_obj) { gpr_mu_lock(&pollable_obj->owner_orphan_mu); @@ -487,6 +444,20 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, /* If release_fd is not NULL, we should be relinquishing control of the file descriptor fd->fd (but we still own the grpc_fd structure). */ if (release_fd != nullptr) { + // Remove the FD from all epolls sets, before releasing it. + // Otherwise, we will receive epoll events after we release the FD. + epoll_event ev_fd; + memset(&ev_fd, 0, sizeof(ev_fd)); + if (release_fd != nullptr) { + if (pollable_obj != nullptr) { // For PO_FD. + epoll_ctl(pollable_obj->epfd, EPOLL_CTL_DEL, fd->fd, &ev_fd); + } + for (size_t i = 0; i < fd->pollsets.size(); ++i) { // For PO_MULTI. + grpc_pollset* pollset = fd->pollsets[i]; + const int epfd = pollset_epoll_fd_locked(pollset); + epoll_ctl(epfd, EPOLL_CTL_DEL, fd->fd, &ev_fd); + } + } *release_fd = fd->fd; } else { close(fd->fd); @@ -508,40 +479,56 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, gpr_mu_unlock(&pollable_obj->owner_orphan_mu); } + gpr_mu_unlock(&fd->pollable_mu); gpr_mu_unlock(&fd->orphan_mu); UNREF_BY(fd, 2, reason); /* Drop the reference */ } static bool fd_is_shutdown(grpc_fd* fd) { - return fd->read_closure->IsShutdown(); + return fd->read_closure.IsShutdown(); } /* Might be called multiple times */ static void fd_shutdown(grpc_fd* fd, grpc_error* why) { - if (fd->read_closure->SetShutdown(GRPC_ERROR_REF(why))) { + if (fd->read_closure.SetShutdown(GRPC_ERROR_REF(why))) { if (shutdown(fd->fd, SHUT_RDWR)) { if (errno != ENOTCONN) { gpr_log(GPR_ERROR, "Error shutting down fd %d. errno: %d", grpc_fd_wrapped_fd(fd), errno); } } - fd->write_closure->SetShutdown(GRPC_ERROR_REF(why)); - fd->error_closure->SetShutdown(GRPC_ERROR_REF(why)); + fd->write_closure.SetShutdown(GRPC_ERROR_REF(why)); + fd->error_closure.SetShutdown(GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } static void fd_notify_on_read(grpc_fd* fd, grpc_closure* closure) { - fd->read_closure->NotifyOn(closure); + fd->read_closure.NotifyOn(closure); } static void fd_notify_on_write(grpc_fd* fd, grpc_closure* closure) { - fd->write_closure->NotifyOn(closure); + fd->write_closure.NotifyOn(closure); } static void fd_notify_on_error(grpc_fd* fd, grpc_closure* closure) { - fd->error_closure->NotifyOn(closure); + fd->error_closure.NotifyOn(closure); +} + +static bool fd_has_pollset(grpc_fd* fd, grpc_pollset* pollset) { + grpc_core::MutexLock lock(&fd->pollable_mu); + for (size_t i = 0; i < fd->pollsets.size(); ++i) { + if (fd->pollsets[i] == pollset) { + return true; + } + } + return false; +} + +static void fd_add_pollset(grpc_fd* fd, grpc_pollset* pollset) { + grpc_core::MutexLock lock(&fd->pollable_mu); + fd->pollsets.push_back(pollset); } /******************************************************************************* @@ -594,8 +581,6 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) { (*p)->root_worker = nullptr; (*p)->event_cursor = 0; (*p)->event_count = 0; - (*p)->fd_cache_size = 0; - (*p)->fd_cache_counter = 0; return GRPC_ERROR_NONE; } @@ -637,39 +622,6 @@ static grpc_error* pollable_add_fd(pollable* p, grpc_fd* fd) { grpc_error* error = GRPC_ERROR_NONE; static const char* err_desc = "pollable_add_fd"; const int epfd = p->epfd; - gpr_mu_lock(&p->mu); - p->fd_cache_counter++; - - // Handle the case of overflow for our cache counter by - // reseting the recency-counter on all cache objects - if (p->fd_cache_counter == 0) { - for (int i = 0; i < p->fd_cache_size; i++) { - p->fd_cache[i].last_used = 0; - } - } - - int lru_idx = 0; - for (int i = 0; i < p->fd_cache_size; i++) { - if (p->fd_cache[i].fd == fd->fd && p->fd_cache[i].salt == fd->salt) { - GRPC_STATS_INC_POLLSET_FD_CACHE_HITS(); - p->fd_cache[i].last_used = p->fd_cache_counter; - gpr_mu_unlock(&p->mu); - return GRPC_ERROR_NONE; - } else if (p->fd_cache[i].last_used < p->fd_cache[lru_idx].last_used) { - lru_idx = i; - } - } - - // Add to cache - if (p->fd_cache_size < MAX_FDS_IN_CACHE) { - lru_idx = p->fd_cache_size; - p->fd_cache_size++; - } - p->fd_cache[lru_idx].fd = fd->fd; - p->fd_cache[lru_idx].salt = fd->salt; - p->fd_cache[lru_idx].last_used = p->fd_cache_counter; - gpr_mu_unlock(&p->mu); - if (grpc_polling_trace.enabled()) { gpr_log(GPR_INFO, "add fd %p (%d) to pollable %p", fd, fd->fd, p); } @@ -849,6 +801,7 @@ static grpc_error* pollset_kick_all(grpc_pollset* pollset) { static void pollset_init(grpc_pollset* pollset, gpr_mu** mu) { gpr_mu_init(&pollset->mu); gpr_atm_no_barrier_store(&pollset->worker_count, 0); + gpr_atm_no_barrier_store(&pollset->active_pollable_type, PO_EMPTY); pollset->active_pollable = POLLABLE_REF(g_empty_pollable, "pollset"); pollset->kicked_without_poller = false; pollset->shutdown_closure = nullptr; @@ -869,11 +822,11 @@ static int poll_deadline_to_millis_timeout(grpc_millis millis) { return static_cast(delta); } -static void fd_become_readable(grpc_fd* fd) { fd->read_closure->SetReady(); } +static void fd_become_readable(grpc_fd* fd) { fd->read_closure.SetReady(); } -static void fd_become_writable(grpc_fd* fd) { fd->write_closure->SetReady(); } +static void fd_become_writable(grpc_fd* fd) { fd->write_closure.SetReady(); } -static void fd_has_errors(grpc_fd* fd) { fd->error_closure->SetReady(); } +static void fd_has_errors(grpc_fd* fd) { fd->error_closure.SetReady(); } /* Get the pollable_obj attached to this fd. If none is attached, create a new * pollable object (of type PO_FD), attach it to the fd and return it @@ -1283,6 +1236,8 @@ static grpc_error* pollset_add_fd_locked(grpc_pollset* pollset, grpc_fd* fd) { POLLABLE_UNREF(pollset->active_pollable, "pollset"); pollset->active_pollable = po_at_start; } else { + gpr_atm_rel_store(&pollset->active_pollable_type, + pollset->active_pollable->type); POLLABLE_UNREF(po_at_start, "pollset_add_fd"); } return error; @@ -1329,17 +1284,38 @@ static grpc_error* pollset_as_multipollable_locked(grpc_pollset* pollset, pollset->active_pollable = po_at_start; *pollable_obj = nullptr; } else { + gpr_atm_rel_store(&pollset->active_pollable_type, + pollset->active_pollable->type); *pollable_obj = POLLABLE_REF(pollset->active_pollable, "pollset_set"); POLLABLE_UNREF(po_at_start, "pollset_as_multipollable"); } return error; } +// Caller must hold the lock for `pollset->mu`. +static int pollset_epoll_fd_locked(grpc_pollset* pollset) { + return pollset->active_pollable->epfd; +} + static void pollset_add_fd(grpc_pollset* pollset, grpc_fd* fd) { GPR_TIMER_SCOPE("pollset_add_fd", 0); - gpr_mu_lock(&pollset->mu); + + // We never transition from PO_MULTI to other modes (i.e., PO_FD or PO_EMOPTY) + // and, thus, it is safe to simply store and check whether the FD has already + // been added to the active pollable previously. + if (gpr_atm_acq_load(&pollset->active_pollable_type) == PO_MULTI && + fd_has_pollset(fd, pollset)) { + return; + } + + grpc_core::MutexLock lock(&pollset->mu); grpc_error* error = pollset_add_fd_locked(pollset, fd); - gpr_mu_unlock(&pollset->mu); + + // If we are in PO_MULTI mode, we should update the pollsets of the FD. + if (gpr_atm_no_barrier_load(&pollset->active_pollable_type) == PO_MULTI) { + fd_add_pollset(fd, pollset); + } + GRPC_LOG_IF_ERROR("pollset_add_fd", error); } From cc19a553386064c8436915f9b4fbbf9711f1803a Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 4 Feb 2019 07:50:29 -0800 Subject: [PATCH 146/218] Revert "Revert "Fix for 17338. Delay shutdown of buffer list till tcp_free to avoid races"" --- src/core/lib/iomgr/tcp_posix.cc | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index 448e5f7b558..61db36bd99e 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -343,6 +343,13 @@ static void tcp_free(grpc_tcp* tcp) { grpc_slice_buffer_destroy_internal(&tcp->last_read_buffer); grpc_resource_user_unref(tcp->resource_user); gpr_free(tcp->peer_string); + /* The lock is not really necessary here, since all refs have been released */ + gpr_mu_lock(&tcp->tb_mu); + grpc_core::TracedBuffer::Shutdown( + &tcp->tb_head, tcp->outgoing_buffer_arg, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); + gpr_mu_unlock(&tcp->tb_mu); + tcp->outgoing_buffer_arg = nullptr; gpr_mu_destroy(&tcp->tb_mu); gpr_free(tcp); } @@ -389,12 +396,6 @@ static void tcp_destroy(grpc_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()) { - gpr_mu_lock(&tcp->tb_mu); - grpc_core::TracedBuffer::Shutdown( - &tcp->tb_head, tcp->outgoing_buffer_arg, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); - gpr_mu_unlock(&tcp->tb_mu); - tcp->outgoing_buffer_arg = nullptr; gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); grpc_fd_set_error(tcp->em_fd); } @@ -1184,12 +1185,6 @@ void grpc_tcp_destroy_and_release_fd(grpc_endpoint* ep, int* fd, grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer); if (grpc_event_engine_can_track_errors()) { /* Stop errors notification. */ - gpr_mu_lock(&tcp->tb_mu); - grpc_core::TracedBuffer::Shutdown( - &tcp->tb_head, tcp->outgoing_buffer_arg, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("endpoint destroyed")); - gpr_mu_unlock(&tcp->tb_mu); - tcp->outgoing_buffer_arg = nullptr; gpr_atm_no_barrier_store(&tcp->stop_error_notification, true); grpc_fd_set_error(tcp->em_fd); } From b23abe832ca53f0e0aa1259c73a33385f36cd39d Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Mon, 4 Feb 2019 11:40:53 -0800 Subject: [PATCH 147/218] GPR_ARRAY_SIZE is meant for arrays --- test/core/iomgr/timer_heap_test.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/core/iomgr/timer_heap_test.cc b/test/core/iomgr/timer_heap_test.cc index 872cf17486f..b574e0a680e 100644 --- a/test/core/iomgr/timer_heap_test.cc +++ b/test/core/iomgr/timer_heap_test.cc @@ -164,13 +164,13 @@ static void test2(void) { size_t num_inserted = 0; grpc_timer_heap_init(&pq); - memset(elems, 0, elems_size); + memset(elems, 0, elems_size * sizeof(elems[0])); for (size_t round = 0; round < 10000; round++) { int r = rand() % 1000; if (r <= 550) { /* 55% of the time we try to add something */ - elem_struct* el = search_elems(elems, GPR_ARRAY_SIZE(elems), false); + elem_struct* el = search_elems(elems, elems_size, false); if (el != nullptr) { el->elem.deadline = random_deadline(); grpc_timer_heap_add(&pq, &el->elem); @@ -180,7 +180,7 @@ static void test2(void) { } } else if (r <= 650) { /* 10% of the time we try to remove something */ - elem_struct* el = search_elems(elems, GPR_ARRAY_SIZE(elems), true); + elem_struct* el = search_elems(elems, elems_size, true); if (el != nullptr) { grpc_timer_heap_remove(&pq, &el->elem); el->inserted = false; From d6ca2c9c9546c2b562a777bc8c26bdd30284c7d6 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 5 Feb 2019 16:52:31 +0100 Subject: [PATCH 148/218] v4 kokoro perf image changes --- .../gce/create_linux_kokoro_performance_worker_from_image.sh | 2 +- tools/gce/linux_kokoro_performance_worker_init.sh | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/gce/create_linux_kokoro_performance_worker_from_image.sh b/tools/gce/create_linux_kokoro_performance_worker_from_image.sh index 28c49a66f24..903166122eb 100755 --- a/tools/gce/create_linux_kokoro_performance_worker_from_image.sh +++ b/tools/gce/create_linux_kokoro_performance_worker_from_image.sh @@ -22,7 +22,7 @@ cd "$(dirname "$0")" CLOUD_PROJECT=grpc-testing ZONE=us-central1-b # this zone allows 32core machines -LATEST_PERF_WORKER_IMAGE=grpc-performance-kokoro-v3 # update if newer image exists +LATEST_PERF_WORKER_IMAGE=grpc-performance-kokoro-v4 # update if newer image exists INSTANCE_NAME="${1:-grpc-kokoro-performance-server}" MACHINE_TYPE="${2:-n1-standard-32}" diff --git a/tools/gce/linux_kokoro_performance_worker_init.sh b/tools/gce/linux_kokoro_performance_worker_init.sh index d67ff58506f..1bf2228279e 100755 --- a/tools/gce/linux_kokoro_performance_worker_init.sh +++ b/tools/gce/linux_kokoro_performance_worker_init.sh @@ -215,6 +215,11 @@ sudo mkdir /tmpfs sudo chown kbuilder /tmpfs touch /tmpfs/READY +# Disable automatic updates to prevent spurious apt-get install failures +# See https://github.com/grpc/grpc/issues/17794 +sudo sed -i 's/APT::Periodic::Update-Package-Lists "1"/APT::Periodic::Update-Package-Lists "0"/' /etc/apt/apt.conf.d/10periodic +sudo sed -i 's/APT::Periodic::AutocleanInterval "1"/APT::Periodic::AutocleanInterval "0"/' /etc/apt/apt.conf.d/10periodic + # Restart for VM to pick up kernel update echo 'Successfully initialized the linux worker, going for reboot in 10 seconds' sleep 10 From 5a20b60cda22b17af2580759fd5f4dcc620f3a30 Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Tue, 5 Feb 2019 09:17:41 -0800 Subject: [PATCH 149/218] fix flake in test_abort_does_not_leak_local_vars --- src/python/grpcio_tests/tests/unit/_abort_test.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/python/grpcio_tests/tests/unit/_abort_test.py b/src/python/grpcio_tests/tests/unit/_abort_test.py index 636f1379ad8..64952c899e4 100644 --- a/src/python/grpcio_tests/tests/unit/_abort_test.py +++ b/src/python/grpcio_tests/tests/unit/_abort_test.py @@ -120,13 +120,13 @@ class AbortTest(unittest.TestCase): weak_ref = weakref.ref(do_not_leak_me) # Servicer will abort() after creating a local ref to do_not_leak_me. - with self.assertRaises(grpc.RpcError) as exception_context: + with self.assertRaises(grpc.RpcError): self._channel.unary_unary(_ABORT)(_REQUEST) - rpc_error = exception_context.exception + # Server may still have a stack frame reference to the exception even + # after client sees error, so ensure server has shutdown. + self._server.stop(None) do_not_leak_me = None - # Force garbage collection - gc.collect() self.assertIsNone(weak_ref()) def test_abort_with_status(self): From 510fba2deb23ec7f0455c463f46eab0dffe01cb6 Mon Sep 17 00:00:00 2001 From: Nicolas Noble Date: Tue, 5 Feb 2019 11:07:19 -0800 Subject: [PATCH 150/218] Removing BoringSSL-specific ubsan suppressions. Let's see if #17791 is really fixed. --- test/core/util/ubsan_suppressions.txt | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/test/core/util/ubsan_suppressions.txt b/test/core/util/ubsan_suppressions.txt index 8ed7d4d7fb6..951df98fbb0 100644 --- a/test/core/util/ubsan_suppressions.txt +++ b/test/core/util/ubsan_suppressions.txt @@ -1,11 +1,4 @@ -# boringssl stuff -nonnull-attribute:bn_wexpand -nonnull-attribute:CBB_add_bytes -nonnull-attribute:rsa_blinding_get -nonnull-attribute:ssl_copy_key_material -alignment:CRYPTO_cbc128_encrypt -alignment:CRYPTO_gcm128_encrypt -alignment:poly1305_block_copy +# Protobuf stuff nonnull-attribute:google::protobuf::* alignment:google::protobuf::* nonnull-attribute:_tr_stored_block @@ -16,11 +9,6 @@ enum:transport_security_test enum:algorithm_test alignment:transport_security_test # TODO(jtattermusch): address issues and remove the supressions -nonnull-attribute:gsec_aes_gcm_aead_crypter_decrypt_iovec -nonnull-attribute:gsec_test_random_encrypt_decrypt -nonnull-attribute:gsec_test_multiple_random_encrypt_decrypt -nonnull-attribute:gsec_test_copy -nonnull-attribute:gsec_test_encrypt_decrypt_test_vector alignment:absl::little_endian::Store64 alignment:absl::little_endian::Load64 float-divide-by-zero:grpc::testing::postprocess_scenario_result From 9abc673def87532617607bda44b2aae9398df3eb Mon Sep 17 00:00:00 2001 From: Nicolas Noble Date: Tue, 5 Feb 2019 13:00:33 -0800 Subject: [PATCH 151/218] Restore gsec* suppressions These aren't from BoringSSL --- test/core/util/ubsan_suppressions.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/core/util/ubsan_suppressions.txt b/test/core/util/ubsan_suppressions.txt index 951df98fbb0..8e17d37ec7e 100644 --- a/test/core/util/ubsan_suppressions.txt +++ b/test/core/util/ubsan_suppressions.txt @@ -9,6 +9,11 @@ enum:transport_security_test enum:algorithm_test alignment:transport_security_test # TODO(jtattermusch): address issues and remove the supressions +nonnull-attribute:gsec_aes_gcm_aead_crypter_decrypt_iovec +nonnull-attribute:gsec_test_random_encrypt_decrypt +nonnull-attribute:gsec_test_multiple_random_encrypt_decrypt +nonnull-attribute:gsec_test_copy +nonnull-attribute:gsec_test_encrypt_decrypt_test_vector alignment:absl::little_endian::Store64 alignment:absl::little_endian::Load64 float-divide-by-zero:grpc::testing::postprocess_scenario_result From bca92b2b7e2f2fcd2ede72e37d02e3787ed6bce3 Mon Sep 17 00:00:00 2001 From: Prashant Jaikumar Date: Thu, 24 Jan 2019 18:30:01 -0800 Subject: [PATCH 152/218] Added test for wall-clock time change on the client --- CMakeLists.txt | 45 ++ Makefile | 48 ++ build.yaml | 16 + src/core/lib/gpr/time.cc | 8 + src/core/lib/gpr/time_posix.cc | 10 +- test/cpp/end2end/BUILD | 24 +- test/cpp/end2end/time_change_test.cc | 422 ++++++++++++++++++ .../generated/sources_and_headers.json | 18 + tools/run_tests/generated/tests.json | 22 + 9 files changed, 610 insertions(+), 3 deletions(-) create mode 100644 test/cpp/end2end/time_change_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 9813eec7062..9ec075c63b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -699,6 +699,9 @@ endif() add_dependencies(buildtests_cxx stress_test) add_dependencies(buildtests_cxx thread_manager_test) add_dependencies(buildtests_cxx thread_stress_test) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) +add_dependencies(buildtests_cxx time_change_test) +endif() add_dependencies(buildtests_cxx transport_pid_controller_test) add_dependencies(buildtests_cxx transport_security_common_api_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -15973,6 +15976,48 @@ target_link_libraries(thread_stress_test ) +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + +add_executable(time_change_test + test/cpp/end2end/time_change_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(time_change_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} + 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(time_change_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc++_test_util + grpc_test_util + grpc++ + grpc + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + + +endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) diff --git a/Makefile b/Makefile index b9b7ab4c254..3a3eacb5764 100644 --- a/Makefile +++ b/Makefile @@ -1248,6 +1248,7 @@ streaming_throughput_test: $(BINDIR)/$(CONFIG)/streaming_throughput_test stress_test: $(BINDIR)/$(CONFIG)/stress_test thread_manager_test: $(BINDIR)/$(CONFIG)/thread_manager_test thread_stress_test: $(BINDIR)/$(CONFIG)/thread_stress_test +time_change_test: $(BINDIR)/$(CONFIG)/time_change_test transport_pid_controller_test: $(BINDIR)/$(CONFIG)/transport_pid_controller_test transport_security_common_api_test: $(BINDIR)/$(CONFIG)/transport_security_common_api_test writes_per_rpc_test: $(BINDIR)/$(CONFIG)/writes_per_rpc_test @@ -1756,6 +1757,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/stress_test \ $(BINDIR)/$(CONFIG)/thread_manager_test \ $(BINDIR)/$(CONFIG)/thread_stress_test \ + $(BINDIR)/$(CONFIG)/time_change_test \ $(BINDIR)/$(CONFIG)/transport_pid_controller_test \ $(BINDIR)/$(CONFIG)/transport_security_common_api_test \ $(BINDIR)/$(CONFIG)/writes_per_rpc_test \ @@ -1943,6 +1945,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/stress_test \ $(BINDIR)/$(CONFIG)/thread_manager_test \ $(BINDIR)/$(CONFIG)/thread_stress_test \ + $(BINDIR)/$(CONFIG)/time_change_test \ $(BINDIR)/$(CONFIG)/transport_pid_controller_test \ $(BINDIR)/$(CONFIG)/transport_security_common_api_test \ $(BINDIR)/$(CONFIG)/writes_per_rpc_test \ @@ -2458,6 +2461,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/thread_manager_test || ( echo test thread_manager_test failed ; exit 1 ) $(E) "[RUN] Testing thread_stress_test" $(Q) $(BINDIR)/$(CONFIG)/thread_stress_test || ( echo test thread_stress_test failed ; exit 1 ) + $(E) "[RUN] Testing time_change_test" + $(Q) $(BINDIR)/$(CONFIG)/time_change_test || ( echo test time_change_test failed ; exit 1 ) $(E) "[RUN] Testing transport_pid_controller_test" $(Q) $(BINDIR)/$(CONFIG)/transport_pid_controller_test || ( echo test transport_pid_controller_test failed ; exit 1 ) $(E) "[RUN] Testing transport_security_common_api_test" @@ -21025,6 +21030,49 @@ endif endif +TIME_CHANGE_TEST_SRC = \ + test/cpp/end2end/time_change_test.cc \ + +TIME_CHANGE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TIME_CHANGE_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/time_change_test: 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)/time_change_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/time_change_test: $(PROTOBUF_DEP) $(TIME_CHANGE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(TIME_CHANGE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/time_change_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/cpp/end2end/time_change_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_time_change_test: $(TIME_CHANGE_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(TIME_CHANGE_TEST_OBJS:.o=.dep) +endif +endif + + TRANSPORT_PID_CONTROLLER_TEST_SRC = \ test/core/transport/pid_controller_test.cc \ diff --git a/build.yaml b/build.yaml index 0946e853d1b..20089c1eba7 100644 --- a/build.yaml +++ b/build.yaml @@ -5558,6 +5558,22 @@ targets: - grpc++_unsecure - grpc_unsecure - gpr +- name: time_change_test + gtest: true + build: test + language: c++ + src: + - test/cpp/end2end/time_change_test.cc + deps: + - grpc++_test_util + - grpc_test_util + - grpc++ + - grpc + - gpr + platforms: + - mac + - linux + - posix - name: transport_pid_controller_test build: test language: c++ diff --git a/src/core/lib/gpr/time.cc b/src/core/lib/gpr/time.cc index 64c1c98f560..8927dab5a30 100644 --- a/src/core/lib/gpr/time.cc +++ b/src/core/lib/gpr/time.cc @@ -135,6 +135,10 @@ gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b) { gpr_timespec sum; int64_t inc = 0; GPR_ASSERT(b.clock_type == GPR_TIMESPAN); + // tv_nsec in a timespan is always +ve. -ve timespan is represented as (-ve + // tv_sec, +ve tv_nsec). For example, timespan = -2.5 seconds is represented + // as {-3, 5e8, GPR_TIMESPAN} + GPR_ASSERT(b.tv_nsec >= 0); sum.clock_type = a.clock_type; sum.tv_nsec = a.tv_nsec + b.tv_nsec; if (sum.tv_nsec >= GPR_NS_PER_SEC) { @@ -165,6 +169,10 @@ gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b) { int64_t dec = 0; if (b.clock_type == GPR_TIMESPAN) { diff.clock_type = a.clock_type; + // tv_nsec in a timespan is always +ve. -ve timespan is represented as (-ve + // tv_sec, +ve tv_nsec). For example, timespan = -2.5 seconds is represented + // as {-3, 5e8, GPR_TIMESPAN} + GPR_ASSERT(b.tv_nsec >= 0); } else { GPR_ASSERT(a.clock_type == b.clock_type); diff.clock_type = GPR_TIMESPAN; diff --git a/src/core/lib/gpr/time_posix.cc b/src/core/lib/gpr/time_posix.cc index 28836bfa54e..1b3e36486fc 100644 --- a/src/core/lib/gpr/time_posix.cc +++ b/src/core/lib/gpr/time_posix.cc @@ -133,12 +133,18 @@ gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type) = now_impl; #ifdef GPR_LOW_LEVEL_COUNTERS gpr_atm gpr_now_call_count; #endif - gpr_timespec gpr_now(gpr_clock_type clock_type) { #ifdef GPR_LOW_LEVEL_COUNTERS __atomic_fetch_add(&gpr_now_call_count, 1, __ATOMIC_RELAXED); #endif - return gpr_now_impl(clock_type); + // validate clock type + GPR_ASSERT(clock_type == GPR_CLOCK_MONOTONIC || + clock_type == GPR_CLOCK_REALTIME || + clock_type == GPR_CLOCK_PRECISE); + gpr_timespec ts = gpr_now_impl(clock_type); + // tv_nsecs must be in the range [0, 1e9). + GPR_ASSERT(ts.tv_nsec >= 0 && ts.tv_nsec < 1e9); + return ts; } void gpr_sleep_until(gpr_timespec until) { diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index 4c28eee4d15..cbf09354a03 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -80,6 +80,27 @@ grpc_cc_test( ], ) +grpc_cc_test( + name = "time_change_test", + srcs = ["time_change_test.cc"], + data = [ + ":client_crash_test_server", + ], + external_deps = [ + "gtest", + ], + deps = [ + ":test_service_impl", + "//:gpr", + "//:grpc", + "//:grpc++", + "//src/proto/grpc/testing:echo_messages_proto", + "//src/proto/grpc/testing:echo_proto", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], +) + grpc_cc_test( name = "client_crash_test", srcs = ["client_crash_test.cc"], @@ -110,6 +131,7 @@ grpc_cc_binary( "gtest", ], deps = [ + ":test_service_impl", "//:gpr", "//:grpc", "//:grpc++", @@ -219,10 +241,10 @@ grpc_cc_test( grpc_cc_test( name = "end2end_test", + size = "large", # with poll-cv this takes long, see #17493 deps = [ ":end2end_test_lib", ], - size = "large", # with poll-cv this takes long, see #17493 ) grpc_cc_test( diff --git a/test/cpp/end2end/time_change_test.cc b/test/cpp/end2end/time_change_test.cc new file mode 100644 index 00000000000..9fbd01299d0 --- /dev/null +++ b/test/cpp/end2end/time_change_test.cc @@ -0,0 +1,422 @@ +/* + * + * Copyright 2019 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 +#include + +#include "src/core/lib/iomgr/timer.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/subprocess.h" + +#include +#include +#include +#include + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; + +static std::string g_root; + +static gpr_mu g_mu; +extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type); +gpr_timespec (*gpr_now_impl_orig)(gpr_clock_type clock_type) = gpr_now_impl; +static int g_time_shift_sec = 0; +static int g_time_shift_nsec = 0; +static gpr_timespec now_impl(gpr_clock_type clock) { + auto ts = gpr_now_impl_orig(clock); + // We only manipulate the realtime clock to simulate changes in wall-clock + // time + if (clock != GPR_CLOCK_REALTIME) { + return ts; + } + GPR_ASSERT(ts.tv_nsec >= 0); + GPR_ASSERT(ts.tv_nsec < GPR_NS_PER_SEC); + gpr_mu_lock(&g_mu); + ts.tv_sec += g_time_shift_sec; + ts.tv_nsec += g_time_shift_nsec; + gpr_mu_unlock(&g_mu); + if (ts.tv_nsec >= GPR_NS_PER_SEC) { + ts.tv_nsec -= GPR_NS_PER_SEC; + ++ts.tv_sec; + } else if (ts.tv_nsec < 0) { + --ts.tv_sec; + ts.tv_nsec = GPR_NS_PER_SEC + ts.tv_nsec; + } + return ts; +} + +// offset the value returned by gpr_now(GPR_CLOCK_REALTIME) by msecs +// milliseconds +static void set_now_offset(int msecs) { + g_time_shift_sec = msecs / 1000; + g_time_shift_nsec = (msecs % 1000) * 1e6; +} + +// restore the original implementation of gpr_now() +static void reset_now_offset() { + g_time_shift_sec = 0; + g_time_shift_nsec = 0; +} + +namespace grpc { +namespace testing { + +namespace { + +// gpr_now() is called with invalid clock_type +TEST(TimespecTest, GprNowInvalidClockType) { + // initialize to some junk value + gpr_clock_type invalid_clock_type = (gpr_clock_type)32641; + EXPECT_DEATH(gpr_now(invalid_clock_type), ".*"); +} + +// Add timespan with negative nanoseconds +TEST(TimespecTest, GprTimeAddNegativeNs) { + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + gpr_timespec bad_ts = {1, -1000, GPR_TIMESPAN}; + EXPECT_DEATH(gpr_time_add(now, bad_ts), ".*"); +} + +// Subtract timespan with negative nanoseconds +TEST(TimespecTest, GprTimeSubNegativeNs) { + // Nanoseconds must always be positive. Negative timestamps are represented by + // (negative seconds, positive nanoseconds) + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + gpr_timespec bad_ts = {1, -1000, GPR_TIMESPAN}; + EXPECT_DEATH(gpr_time_sub(now, bad_ts), ".*"); +} + +// Add negative milliseconds to gpr_timespec +TEST(TimespecTest, GrpcNegativeMillisToTimespec) { + // -1500 milliseconds converts to timespec (-2 secs, 5 * 10^8 nsec) + gpr_timespec ts = grpc_millis_to_timespec(-1500, GPR_CLOCK_MONOTONIC); + GPR_ASSERT(ts.tv_sec = -2); + GPR_ASSERT(ts.tv_nsec = 5e8); + GPR_ASSERT(ts.clock_type == GPR_CLOCK_MONOTONIC); +} + +class TimeChangeTest : public ::testing::Test { + protected: + TimeChangeTest() {} + + void SetUp() { + auto port = grpc_pick_unused_port_or_die(); + std::ostringstream addr_stream; + addr_stream << "localhost:" << port; + auto addr = addr_stream.str(); + server_.reset(new SubProcess({ + g_root + "/client_crash_test_server", + "--address=" + addr, + })); + GPR_ASSERT(server_); + channel_ = CreateChannel(addr, InsecureChannelCredentials()); + GPR_ASSERT(channel_); + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + } + + void TearDown() { + server_.reset(); + reset_now_offset(); + } + + std::unique_ptr CreateStub() { + return grpc::testing::EchoTestService::NewStub(channel_); + } + + std::shared_ptr GetChannel() { return channel_; } + // time jump offsets in milliseconds + const int TIME_OFFSET1 = 20123; + const int TIME_OFFSET2 = 5678; + + private: + std::unique_ptr server_; + std::shared_ptr channel_; + std::unique_ptr stub_; +}; + +// Wall-clock time jumps forward on client before bidi stream is created +TEST_F(TimeChangeTest, TimeJumpForwardBeforeStreamCreated) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "1"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + + // time jumps forward by TIME_OFFSET1 milliseconds + set_now_offset(TIME_OFFSET1); + auto stream = stub->BidiStream(&context); + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps back on client before bidi stream is created +TEST_F(TimeChangeTest, TimeJumpBackBeforeStreamCreated) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "1"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + + // time jumps back by TIME_OFFSET1 milliseconds + set_now_offset(-TIME_OFFSET1); + auto stream = stub->BidiStream(&context); + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + EXPECT_EQ(request.message(), response.message()); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps forward on client while call is in progress +TEST_F(TimeChangeTest, TimeJumpForwardAfterStreamCreated) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "2"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + + // time jumps forward by TIME_OFFSET1 milliseconds. + set_now_offset(TIME_OFFSET1); + + request.set_message("World"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps back on client while call is in progress +TEST_F(TimeChangeTest, TimeJumpBackAfterStreamCreated) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "2"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + + // time jumps back TIME_OFFSET1 milliseconds. + set_now_offset(-TIME_OFFSET1); + + request.set_message("World"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps forward on client before connection to server is up +TEST_F(TimeChangeTest, TimeJumpForwardBeforeServerConnect) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "2"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + + // time jumps forward by TIME_OFFSET2 milliseconds + set_now_offset(TIME_OFFSET2); + + auto ret = + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000)); + // We use monotonic clock for pthread_cond_timedwait() deadline on linux, and + // realtime clock on other platforms - see gpr_cv_wait() in sync_posix.cc. + // So changes in system clock affect deadlines on non-linux platforms +#ifdef GPR_LINUX + EXPECT_TRUE(ret); + auto stub = CreateStub(); + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + request.set_message("World"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +#else + EXPECT_FALSE(ret); +#endif +} + +// Wall-clock time jumps back on client before connection to server is up +TEST_F(TimeChangeTest, TimeJumpBackBeforeServerConnect) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "2"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->Read(&response)); + request.set_message("World"); + EXPECT_TRUE(stream->Write(request)); + EXPECT_TRUE(stream->WritesDone()); + EXPECT_TRUE(stream->Read(&response)); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +// Wall-clock time jumps forward and backwards during call +TEST_F(TimeChangeTest, TimeJumpForwardAndBackDuringCall) { + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(5000)); + context.AddMetadata(kServerResponseStreamsToSend, "2"); + + auto channel = GetChannel(); + GPR_ASSERT(channel); + + EXPECT_TRUE( + channel->WaitForConnected(grpc_timeout_milliseconds_to_deadline(5000))); + auto stub = CreateStub(); + auto stream = stub->BidiStream(&context); + + request.set_message("Hello"); + EXPECT_TRUE(stream->Write(request)); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + EXPECT_TRUE(stream->Read(&response)); + request.set_message("World"); + + // time jumps forward by TIME_OFFSET milliseconds + set_now_offset(TIME_OFFSET1); + + EXPECT_TRUE(stream->Write(request)); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + EXPECT_TRUE(stream->WritesDone()); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + EXPECT_TRUE(stream->Read(&response)); + + // time jumps back by TIME_OFFSET2 milliseconds + set_now_offset(-TIME_OFFSET2); + + auto status = stream->Finish(); + EXPECT_TRUE(status.ok()); +} + +} // namespace + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + std::string me = argv[0]; + // get index of last slash in path to test binary + auto lslash = me.rfind('/'); + // set g_root = path to directory containing test binary + if (lslash != std::string::npos) { + g_root = me.substr(0, lslash); + } else { + g_root = "."; + } + + gpr_mu_init(&g_mu); + gpr_now_impl = now_impl; + + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + auto ret = RUN_ALL_TESTS(); + return ret; +} diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 9e07c548b69..558afccc28b 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -4894,6 +4894,24 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "grpc", + "grpc++", + "grpc++_test_util", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "time_change_test", + "src": [ + "test/cpp/end2end/time_change_test.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 b41fef6b795..fef3ec65ec4 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -5548,6 +5548,28 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "time_change_test", + "platforms": [ + "linux", + "mac", + "posix" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, From 45c684f89486643c7af8e76e161c5947e4dbf356 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Tue, 5 Feb 2019 14:05:28 -0800 Subject: [PATCH 153/218] Allow an alarm to be set again after firing --- include/grpcpp/alarm_impl.h | 5 ++--- src/cpp/common/alarm.cc | 14 ++++++------- test/cpp/common/alarm_test.cc | 38 +++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/include/grpcpp/alarm_impl.h b/include/grpcpp/alarm_impl.h index 7844e7c8866..543dcd82a4c 100644 --- a/include/grpcpp/alarm_impl.h +++ b/include/grpcpp/alarm_impl.h @@ -16,8 +16,8 @@ * */ -/// An Alarm posts the user provided tag to its associated completion queue upon -/// expiry or cancellation. +/// An Alarm posts the user-provided tag to its associated completion queue or +/// invokes the user-provided function on expiry or cancellation. #ifndef GRPCPP_ALARM_IMPL_H #define GRPCPP_ALARM_IMPL_H @@ -32,7 +32,6 @@ namespace grpc_impl { -/// A thin wrapper around \a grpc_alarm (see / \a / src/core/surface/alarm.h). class Alarm : private ::grpc::GrpcLibraryCodegen { public: /// Create an unset completion queue alarm diff --git a/src/cpp/common/alarm.cc b/src/cpp/common/alarm.cc index 6bfe26f04c4..dbec80cde4f 100644 --- a/src/cpp/common/alarm.cc +++ b/src/cpp/common/alarm.cc @@ -40,12 +40,7 @@ class AlarmImpl : public ::grpc::internal::CompletionQueueTag { gpr_ref_init(&refs_, 1); grpc_timer_init_unset(&timer_); } - ~AlarmImpl() { - grpc_core::ExecCtx exec_ctx; - if (cq_ != nullptr) { - GRPC_CQ_INTERNAL_UNREF(cq_, "alarm"); - } - } + ~AlarmImpl() {} bool FinalizeResult(void** tag, bool* status) override { *tag = tag_; Unref(); @@ -63,10 +58,15 @@ class AlarmImpl : public ::grpc::internal::CompletionQueueTag { // queue the op on the completion queue AlarmImpl* alarm = static_cast(arg); alarm->Ref(); + // Preserve the cq and reset the cq_ so that the alarm + // can be reset when the alarm tag is delivered. + grpc_completion_queue* cq = alarm->cq_; + alarm->cq_ = nullptr; grpc_cq_end_op( - alarm->cq_, alarm, error, + cq, alarm, error, [](void* arg, grpc_cq_completion* completion) {}, arg, &alarm->completion_); + GRPC_CQ_INTERNAL_UNREF(cq, "alarm"); }, this, grpc_schedule_on_exec_ctx); grpc_timer_init(&timer_, grpc_timespec_to_millis_round_up(deadline), diff --git a/test/cpp/common/alarm_test.cc b/test/cpp/common/alarm_test.cc index 802cdc209a0..4d410a5d460 100644 --- a/test/cpp/common/alarm_test.cc +++ b/test/cpp/common/alarm_test.cc @@ -47,6 +47,44 @@ TEST(AlarmTest, RegularExpiry) { EXPECT_EQ(junk, output_tag); } +TEST(AlarmTest, RegularExpiryMultiSet) { + CompletionQueue cq; + void* junk = reinterpret_cast(1618033); + Alarm alarm; + + for (int i = 0; i < 3; i++) { + alarm.Set(&cq, grpc_timeout_seconds_to_deadline(1), junk); + + void* output_tag; + bool ok; + const CompletionQueue::NextStatus status = + cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10)); + + EXPECT_EQ(status, CompletionQueue::GOT_EVENT); + EXPECT_TRUE(ok); + EXPECT_EQ(junk, output_tag); + } +} + +TEST(AlarmTest, RegularExpiryMultiSetMultiCQ) { + void* junk = reinterpret_cast(1618033); + Alarm alarm; + + for (int i = 0; i < 3; i++) { + CompletionQueue cq; + alarm.Set(&cq, grpc_timeout_seconds_to_deadline(1), junk); + + void* output_tag; + bool ok; + const CompletionQueue::NextStatus status = + cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10)); + + EXPECT_EQ(status, CompletionQueue::GOT_EVENT); + EXPECT_TRUE(ok); + EXPECT_EQ(junk, output_tag); + } +} + struct Completion { bool completed = false; std::mutex mu; From 84a537b1d12c8f75577992b5201c832455c46a3c Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Tue, 5 Feb 2019 14:22:47 -0800 Subject: [PATCH 154/218] Default compression level quick fix --- src/cpp/server/server_builder.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index 0dc03b68768..64210a2f8d1 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -139,6 +139,7 @@ ServerBuilder& ServerBuilder::SetCompressionAlgorithmSupportStatus( ServerBuilder& ServerBuilder::SetDefaultCompressionLevel( grpc_compression_level level) { + maybe_default_compression_level_.is_set = true; maybe_default_compression_level_.level = level; return *this; } From fdae4dc8331024fbc96f4c53f9e3be671b410152 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Tue, 5 Feb 2019 16:10:41 -0800 Subject: [PATCH 155/218] Second attemp to fix use-after-free in health check client --- src/core/ext/filters/client_channel/subchannel.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 4276df3067f..35225b0d5c3 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -407,7 +407,8 @@ class Subchannel::ConnectedSubchannelStateWatcher Subchannel* c = self->subchannel_; { MutexLock lock(&c->mu_); - if (self->health_state_ != GRPC_CHANNEL_SHUTDOWN) { + if (self->health_state_ != GRPC_CHANNEL_SHUTDOWN && + self->health_check_client_ != nullptr) { if (self->last_connectivity_state_ == GRPC_CHANNEL_READY) { grpc_connectivity_state_set(&c->state_and_health_tracker_, self->health_state_, From 474a931036d40d85eb8b91120f806c81ac1cb1ef Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 6 Feb 2019 10:28:40 +0100 Subject: [PATCH 156/218] Revert "added retry statements to jq installation commands" --- .../helper_scripts/prepare_build_linux_perf_rc | 8 +------- tools/internal_ci/linux/grpc_run_tests_matrix.sh | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc b/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc index b66ac38942f..ff5593e031a 100644 --- a/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc +++ b/tools/internal_ci/helper_scripts/prepare_build_linux_perf_rc @@ -21,13 +21,7 @@ ulimit -c unlimited # Performance PR testing needs GH API key and PR metadata to comment results if [ -n "$KOKORO_GITHUB_PULL_REQUEST_NUMBER" ]; then - retry=0 - until [ $retry -ge 3 ] - do - sudo apt-get install -y jq && break - retry=$[$retry+1] - sleep 5 - done + sudo apt-get install -y jq export ghprbTargetBranch=$(curl -s https://api.github.com/repos/grpc/grpc/pulls/$KOKORO_GITHUB_PULL_REQUEST_NUMBER | jq -r .base.ref) fi diff --git a/tools/internal_ci/linux/grpc_run_tests_matrix.sh b/tools/internal_ci/linux/grpc_run_tests_matrix.sh index f8fd963ccf3..f9acd814ae8 100755 --- a/tools/internal_ci/linux/grpc_run_tests_matrix.sh +++ b/tools/internal_ci/linux/grpc_run_tests_matrix.sh @@ -23,13 +23,7 @@ source tools/internal_ci/helper_scripts/prepare_build_linux_rc # If this is a PR using RUN_TESTS_FLAGS var, then add flags to filter tests if [ -n "$KOKORO_GITHUB_PULL_REQUEST_NUMBER" ] && [ -n "$RUN_TESTS_FLAGS" ]; then sudo apt-get update - retry=0 - until [ $retry -ge 3 ] - do - sudo apt-get install -y jq && break - retry=$[$retry+1] - sleep 5 - done + sudo apt-get install -y jq ghprbTargetBranch=$(curl -s https://api.github.com/repos/grpc/grpc/pulls/$KOKORO_GITHUB_PULL_REQUEST_NUMBER | jq -r .base.ref) export RUN_TESTS_FLAGS="$RUN_TESTS_FLAGS --filter_pr_tests --base_branch origin/$ghprbTargetBranch" fi From 440f734d59d8109fd20d4d95879fe22a74970908 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 6 Feb 2019 07:39:22 -0800 Subject: [PATCH 157/218] Remove owners for tools/run_tests/performance --- .github/CODEOWNERS | 1 - tools/run_tests/performance/OWNERS | 9 --------- 2 files changed, 10 deletions(-) delete mode 100644 tools/run_tests/performance/OWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0a7141c1be3..1fcdb6ba53c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -6,4 +6,3 @@ /cmake/** @jtattermusch @nicolasnoble @apolcyn /src/core/ext/filters/client_channel/** @markdroth @apolcyn @AspirinSJL /tools/dockerfile/** @jtattermusch @apolcyn @nicolasnoble -/tools/run_tests/performance/** @ncteisen @apolcyn @jtattermusch diff --git a/tools/run_tests/performance/OWNERS b/tools/run_tests/performance/OWNERS deleted file mode 100644 index 9cf8c131111..00000000000 --- a/tools/run_tests/performance/OWNERS +++ /dev/null @@ -1,9 +0,0 @@ -set noparent - -# These owners are in place to ensure that scenario_result_schema.json is not -# modified without also running tools/run_tests/performance/patch_scenario_results_schema.py -# to update the BigQuery schema - -@ncteisen -@apolcyn -@jtattermusch From 0da52ab133b7fd6e9ae2fbd7518af25ce4d8e004 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 6 Feb 2019 17:58:04 +0100 Subject: [PATCH 158/218] Fix typo in flow control trace --- src/core/ext/transport/chttp2/transport/flow_control.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ext/transport/chttp2/transport/flow_control.cc b/src/core/ext/transport/chttp2/transport/flow_control.cc index 53932bcb7f5..ee2bb930802 100644 --- a/src/core/ext/transport/chttp2/transport/flow_control.cc +++ b/src/core/ext/transport/chttp2/transport/flow_control.cc @@ -111,7 +111,7 @@ void FlowControlTrace::Finish() { saw_str = gpr_leftpad("", ' ', kTracePadding); } gpr_log(GPR_DEBUG, - "%p[%u][%s] | %s | trw:%s, ttw:%s, taw:%s, srw:%s, slw:%s, saw:%s", + "%p[%u][%s] | %s | trw:%s, tlw:%s, taw:%s, srw:%s, slw:%s, saw:%s", tfc_, sfc_ != nullptr ? sfc_->stream()->id : 0, tfc_->transport()->is_client ? "cli" : "svr", reason_, trw_str, tlw_str, taw_str, srw_str, slw_str, saw_str); From 94564d1c223e3ecdd2d734959f48d7bf53e3fdf0 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Tue, 5 Feb 2019 15:03:46 -0500 Subject: [PATCH 159/218] Update the channelz compaction test to use 300 entries. --- test/core/channel/channelz_registry_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core/channel/channelz_registry_test.cc b/test/core/channel/channelz_registry_test.cc index ed3d629dc99..31841f9f967 100644 --- a/test/core/channel/channelz_registry_test.cc +++ b/test/core/channel/channelz_registry_test.cc @@ -112,7 +112,7 @@ TEST_F(ChannelzRegistryTest, NullIfNotPresentTest) { } TEST_F(ChannelzRegistryTest, TestCompaction) { - const int kLoopIterations = 100; + const int kLoopIterations = 300; // These channels that will stay in the registry for the duration of the test. std::vector> even_channels; even_channels.reserve(kLoopIterations); From ade38d75c1041f7bf650ba10969967a864c72b1b Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 6 Feb 2019 10:47:40 -0800 Subject: [PATCH 160/218] Fix tsan --- src/core/lib/iomgr/error.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/core/lib/iomgr/error.cc b/src/core/lib/iomgr/error.cc index 59236b20c59..f4abad9b288 100644 --- a/src/core/lib/iomgr/error.cc +++ b/src/core/lib/iomgr/error.cc @@ -303,11 +303,15 @@ static void internal_add_error(grpc_error** err, grpc_error* new_err) { // It is very common to include and extra int and string in an error #define SURPLUS_CAPACITY (2 * SLOTS_PER_INT + SLOTS_PER_TIME) -static bool g_error_creation_allowed = true; +static gpr_atm g_error_creation_allowed = true; -void grpc_disable_error_creation() { g_error_creation_allowed = false; } +void grpc_disable_error_creation() { + gpr_atm_no_barrier_store(&g_error_creation_allowed, false); +} -void grpc_enable_error_creation() { g_error_creation_allowed = true; } +void grpc_enable_error_creation() { + gpr_atm_no_barrier_store(&g_error_creation_allowed, true); +} grpc_error* grpc_error_create(const char* file, int line, grpc_slice desc, grpc_error** referencing, @@ -323,7 +327,7 @@ grpc_error* grpc_error_create(const char* file, int line, grpc_slice desc, return GRPC_ERROR_OOM; } #ifndef NDEBUG - if (!g_error_creation_allowed) { + if (!gpr_atm_no_barrier_load(&g_error_creation_allowed)) { gpr_log(GPR_ERROR, "Error creation occurred when error creation was disabled [%s:%d]", file, line); From bc4c77bf95be0e0ad186d3e0b950a1ddb21507a4 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 6 Feb 2019 19:51:09 +0100 Subject: [PATCH 161/218] ignore reserved bit in WINDOW_UPDATE frame --- .../ext/transport/chttp2/transport/frame_window_update.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.cc b/src/core/ext/transport/chttp2/transport/frame_window_update.cc index 4b586dc3e7f..b8738ea7ea0 100644 --- a/src/core/ext/transport/chttp2/transport/frame_window_update.cc +++ b/src/core/ext/transport/chttp2/transport/frame_window_update.cc @@ -88,8 +88,9 @@ grpc_error* grpc_chttp2_window_update_parser_parse(void* parser, } if (p->byte == 4) { - uint32_t received_update = p->amount; - if (received_update == 0 || (received_update & 0x80000000u)) { + // top bit is reserved and must be ignored. + uint32_t received_update = p->amount & 0x7fffffffu; + if (received_update == 0) { char* msg; gpr_asprintf(&msg, "invalid window update bytes: %d", p->amount); grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); From 3fe3be39febd94198393b02b444ae6d0ec88f422 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 6 Feb 2019 11:04:54 -0800 Subject: [PATCH 162/218] Add empty binary metadata test --- test/cpp/end2end/end2end_test.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 05cd4330c61..4bddbb4bdf2 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -758,6 +758,18 @@ TEST_P(End2endTest, MultipleRpcs) { } } +TEST_P(End2endTest, EmptyBinaryMetadata) { + ResetStub(); + EchoRequest request; + EchoResponse response; + request.set_message("Hello hello hello hello"); + ClientContext context; + context.AddMetadata("custom-bin", ""); + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.ok()); +} + TEST_P(End2endTest, ReconnectChannel) { if (GetParam().inproc) { return; From 058ceccd71a61e6b1a717996df10147784b2d442 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 6 Feb 2019 13:31:10 -0800 Subject: [PATCH 163/218] Add test to check that reads reset the keepalive timer --- test/core/end2end/tests/keepalive_timeout.cc | 206 +++++++++++++++++++ 1 file changed, 206 insertions(+) diff --git a/test/core/end2end/tests/keepalive_timeout.cc b/test/core/end2end/tests/keepalive_timeout.cc index 5f6a36dac44..d4e1fe34af3 100644 --- a/test/core/end2end/tests/keepalive_timeout.cc +++ b/test/core/end2end/tests/keepalive_timeout.cc @@ -220,8 +220,214 @@ static void test_keepalive_timeout(grpc_end2end_test_config config) { config.tear_down_data(&f); } +/* Verify that reads reset the keepalive ping timer. The client sends 10 pings + * with a sleep of 5ms in between. It has a configured keepalive timer of 10ms. + * In the success case, each ping ack should reset the keepalive timer so that + * the keepalive ping is never sent. */ +static void test_read_delays_keepalive(grpc_end2end_test_config config) { + const int kPingIntervalMS = 5; + grpc_arg keepalive_arg_elems[3]; + keepalive_arg_elems[0].type = GRPC_ARG_INTEGER; + keepalive_arg_elems[0].key = const_cast(GRPC_ARG_KEEPALIVE_TIME_MS); + keepalive_arg_elems[0].value.integer = kPingIntervalMS * 2; + keepalive_arg_elems[1].type = GRPC_ARG_INTEGER; + keepalive_arg_elems[1].key = const_cast(GRPC_ARG_KEEPALIVE_TIMEOUT_MS); + keepalive_arg_elems[1].value.integer = 0; + keepalive_arg_elems[2].type = GRPC_ARG_INTEGER; + keepalive_arg_elems[2].key = const_cast(GRPC_ARG_HTTP2_BDP_PROBE); + keepalive_arg_elems[2].value.integer = 0; + grpc_channel_args keepalive_args = {GPR_ARRAY_SIZE(keepalive_arg_elems), + keepalive_arg_elems}; + grpc_end2end_test_fixture f = begin_test(config, "test_read_delays_keepalive", + &keepalive_args, nullptr); + /* Disable ping ack to trigger the keepalive timeout */ + grpc_set_disable_ping_ack(true); + grpc_call* c; + grpc_call* s; + 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_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + grpc_byte_buffer* request_payload; + grpc_byte_buffer* request_payload_recv; + grpc_byte_buffer* response_payload; + grpc_byte_buffer* response_payload_recv; + int i; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string("hello you"); + + 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_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); + + error = + grpc_server_request_call(f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(100)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(100), 1); + cq_verify(cqv); + + 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_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(s, ops, static_cast(op - ops), tag(101), + nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + for (i = 0; i < 10; i++) { + request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); + response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); + + memset(ops, 0, sizeof(ops)); + op = ops; + 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_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(c, ops, static_cast(op - ops), tag(2), + nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + 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); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + 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(2), 1); + cq_verify(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + /* Sleep for a short interval to check if the client sends any pings */ + gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(kPingIntervalMS)); + } + + grpc_slice_unref(request_payload_slice); + grpc_slice_unref(response_payload_slice); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(c, ops, static_cast(op - ops), tag(3), + nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + 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_UNIMPLEMENTED; + 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(104), + nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + CQ_EXPECT_COMPLETION(cqv, tag(3), 1); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + CQ_EXPECT_COMPLETION(cqv, tag(104), 1); + cq_verify(cqv); + + grpc_call_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + 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_slice_unref(details); + + end_test(&f); + config.tear_down_data(&f); +} + void keepalive_timeout(grpc_end2end_test_config config) { test_keepalive_timeout(config); + test_read_delays_keepalive(config); } void keepalive_timeout_pre_init(void) {} From 8a5c52e53fdf9b9f855bfb0eba893b06ae0b6b00 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 6 Feb 2019 23:07:00 +0100 Subject: [PATCH 164/218] move Logging types back to Grpc.Core --- src/csharp/Grpc.Core/ForwardedTypes.cs | 2 -- src/csharp/{Grpc.Core.Api => Grpc.Core}/Logging/ILogger.cs | 0 src/csharp/{Grpc.Core.Api => Grpc.Core}/Logging/LogLevel.cs | 0 3 files changed, 2 deletions(-) rename src/csharp/{Grpc.Core.Api => Grpc.Core}/Logging/ILogger.cs (100%) rename src/csharp/{Grpc.Core.Api => Grpc.Core}/Logging/LogLevel.cs (100%) diff --git a/src/csharp/Grpc.Core/ForwardedTypes.cs b/src/csharp/Grpc.Core/ForwardedTypes.cs index e17696a626f..dd7f292a248 100644 --- a/src/csharp/Grpc.Core/ForwardedTypes.cs +++ b/src/csharp/Grpc.Core/ForwardedTypes.cs @@ -26,8 +26,6 @@ using Grpc.Core.Utils; // TODO(jtattermusch): move types needed for implementing a client -[assembly:TypeForwardedToAttribute(typeof(ILogger))] -[assembly:TypeForwardedToAttribute(typeof(LogLevel))] [assembly:TypeForwardedToAttribute(typeof(GrpcPreconditions))] [assembly:TypeForwardedToAttribute(typeof(AuthContext))] [assembly:TypeForwardedToAttribute(typeof(ContextPropagationOptions))] diff --git a/src/csharp/Grpc.Core.Api/Logging/ILogger.cs b/src/csharp/Grpc.Core/Logging/ILogger.cs similarity index 100% rename from src/csharp/Grpc.Core.Api/Logging/ILogger.cs rename to src/csharp/Grpc.Core/Logging/ILogger.cs diff --git a/src/csharp/Grpc.Core.Api/Logging/LogLevel.cs b/src/csharp/Grpc.Core/Logging/LogLevel.cs similarity index 100% rename from src/csharp/Grpc.Core.Api/Logging/LogLevel.cs rename to src/csharp/Grpc.Core/Logging/LogLevel.cs From d77bf34c1c2b8423f7cd0ee8b4e7e3f1b7a3d8a0 Mon Sep 17 00:00:00 2001 From: Prashant Jaikumar Date: Wed, 6 Feb 2019 14:14:31 -0800 Subject: [PATCH 165/218] Fixed typo in templates documentation --- templates/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/README.md b/templates/README.md index a7aeec26c7c..a8104b1ace6 100644 --- a/templates/README.md +++ b/templates/README.md @@ -41,7 +41,7 @@ filegroups: # groups of files that are automatically expanded ... libs: # list of libraries to build ... -target: # list of targets to build +targets: # list of targets to build ... ``` From 6b74b1350b259d5b75b3871f94ff3f56ce281fc1 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 6 Feb 2019 15:59:40 -0800 Subject: [PATCH 166/218] Experiment with timing values to make sure that tests pass --- test/core/end2end/tests/keepalive_timeout.cc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/test/core/end2end/tests/keepalive_timeout.cc b/test/core/end2end/tests/keepalive_timeout.cc index d4e1fe34af3..38ff37fca6a 100644 --- a/test/core/end2end/tests/keepalive_timeout.cc +++ b/test/core/end2end/tests/keepalive_timeout.cc @@ -91,6 +91,7 @@ static void end_test(grpc_end2end_test_fixture* f) { /* Client sends a request, server replies with a payload, then waits for the keepalive watchdog timeouts before returning status. */ +#if 0 static void test_keepalive_timeout(grpc_end2end_test_config config) { grpc_call* c; grpc_call* s; @@ -219,17 +220,19 @@ static void test_keepalive_timeout(grpc_end2end_test_config config) { end_test(&f); config.tear_down_data(&f); } +#endif -/* Verify that reads reset the keepalive ping timer. The client sends 10 pings - * with a sleep of 5ms in between. It has a configured keepalive timer of 10ms. - * In the success case, each ping ack should reset the keepalive timer so that - * the keepalive ping is never sent. */ +/* Verify that reads reset the keepalive ping timer. The client sends 30 pings + * with a sleep of 10ms in between. It has a configured keepalive timer of + * 200ms. In the success case, each ping ack should reset the keepalive timer so + * that the keepalive ping is never sent. */ static void test_read_delays_keepalive(grpc_end2end_test_config config) { + gpr_log(GPR_ERROR, "ura"); const int kPingIntervalMS = 5; grpc_arg keepalive_arg_elems[3]; keepalive_arg_elems[0].type = GRPC_ARG_INTEGER; keepalive_arg_elems[0].key = const_cast(GRPC_ARG_KEEPALIVE_TIME_MS); - keepalive_arg_elems[0].value.integer = kPingIntervalMS * 2; + keepalive_arg_elems[0].value.integer = 20 * kPingIntervalMS; keepalive_arg_elems[1].type = GRPC_ARG_INTEGER; keepalive_arg_elems[1].key = const_cast(GRPC_ARG_KEEPALIVE_TIMEOUT_MS); keepalive_arg_elems[1].value.integer = 0; @@ -322,7 +325,7 @@ static void test_read_delays_keepalive(grpc_end2end_test_config config) { nullptr); GPR_ASSERT(GRPC_CALL_OK == error); - for (i = 0; i < 10; i++) { + for (i = 0; i < 30; i++) { request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); @@ -374,7 +377,9 @@ static void test_read_delays_keepalive(grpc_end2end_test_config config) { grpc_byte_buffer_destroy(request_payload_recv); grpc_byte_buffer_destroy(response_payload_recv); /* Sleep for a short interval to check if the client sends any pings */ + gpr_log(GPR_ERROR, "before sleep"); gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(kPingIntervalMS)); + gpr_log(GPR_ERROR, "after sleep"); } grpc_slice_unref(request_payload_slice); @@ -426,7 +431,7 @@ static void test_read_delays_keepalive(grpc_end2end_test_config config) { } void keepalive_timeout(grpc_end2end_test_config config) { - test_keepalive_timeout(config); + // test_keepalive_timeout(config); test_read_delays_keepalive(config); } From 26605fa3095e9e8676433e05fba7368a6e12a6f1 Mon Sep 17 00:00:00 2001 From: Nicolas Noble Date: Wed, 6 Feb 2019 17:02:57 -0800 Subject: [PATCH 167/218] Revert "Track the pollsets of an FD in PO_MULTI mode for pollex." --- src/core/lib/iomgr/ev_epollex_linux.cc | 300 +++++++++++++------------ 1 file changed, 162 insertions(+), 138 deletions(-) diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index d6947d00e84..0a0891013af 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -45,7 +45,6 @@ #include "src/core/lib/gpr/spinlock.h" #include "src/core/lib/gpr/tls.h" #include "src/core/lib/gpr/useful.h" -#include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/iomgr/block_annotate.h" @@ -79,6 +78,18 @@ typedef enum { PO_MULTI, PO_FD, PO_EMPTY } pollable_type; typedef struct pollable pollable; +typedef struct cached_fd { + // Set to the grpc_fd's salt value. See 'salt' variable' in grpc_fd for more + // details + intptr_t salt; + + // The underlying fd + int fd; + + // A recency time counter that helps to determine the LRU fd in the cache + uint64_t last_used; +} cached_fd; + /// A pollable is something that can be polled: it has an epoll set to poll on, /// and a wakeup fd for kicks /// There are three broad types: @@ -109,6 +120,33 @@ struct pollable { int event_cursor; int event_count; struct epoll_event events[MAX_EPOLL_EVENTS]; + + // We may be calling pollable_add_fd() on the same (pollable, fd) multiple + // times. To prevent pollable_add_fd() from making multiple sys calls to + // epoll_ctl() to add the fd, we maintain a cache of what fds are already + // present in the underlying epoll-set. + // + // Since this is not a correctness issue, we do not need to maintain all the + // fds in the cache. Hence we just use an LRU cache of size 'MAX_FDS_IN_CACHE' + // + // NOTE: An ideal implementation of this should do the following: + // 1) Add fds to the cache in pollable_add_fd() function (i.e whenever the fd + // is added to the pollable's epoll set) + // 2) Remove the fd from the cache whenever the fd is removed from the + // underlying epoll set (i.e whenever fd_orphan() is called). + // + // Implementing (2) above (i.e removing fds from cache on fd_orphan) adds a + // lot of complexity since an fd can be present in multiple pollables. So our + // implementation ONLY DOES (1) and NOT (2). + // + // The cache_fd.salt variable helps here to maintain correctness (it serves as + // an epoch that differentiates one grpc_fd from the other even though both of + // them may have the same fd number) + // + // The following implements LRU-eviction cache of fds in this pollable + cached_fd fd_cache[MAX_FDS_IN_CACHE]; + int fd_cache_size; + uint64_t fd_cache_counter; // Recency timer tick counter }; static const char* pollable_type_string(pollable_type t) { @@ -151,86 +189,37 @@ static void pollable_unref(pollable* p, int line, const char* reason); * Fd Declarations */ -struct grpc_fd { - grpc_fd(int fd, const char* name, bool track_err) - : fd(fd), track_err(track_err) { - gpr_mu_init(&orphan_mu); - gpr_mu_init(&pollable_mu); - read_closure.InitEvent(); - write_closure.InitEvent(); - error_closure.InitEvent(); - - char* fd_name; - gpr_asprintf(&fd_name, "%s fd=%d", name, fd); - grpc_iomgr_register_object(&iomgr_object, fd_name); -#ifndef NDEBUG - if (grpc_trace_fd_refcount.enabled()) { - gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, this, fd_name); - } -#endif - gpr_free(fd_name); - } - - // This is really the dtor, but the poller threads waking up from - // epoll_wait() may access the (read|write|error)_closure after destruction. - // Since the object will be added to the free pool, this behavior is - // not going to cause issues, except spurious events if the FD is reused - // while the race happens. - void destroy() { - grpc_iomgr_unregister_object(&iomgr_object); - - POLLABLE_UNREF(pollable_obj, "fd_pollable"); - pollsets.clear(); - gpr_mu_destroy(&pollable_mu); - gpr_mu_destroy(&orphan_mu); - - read_closure.DestroyEvent(); - write_closure.DestroyEvent(); - error_closure.DestroyEvent(); - - invalidate(); - } - -#ifndef NDEBUG - /* Since an fd is never really destroyed (i.e gpr_free() is not called), it is - * hard-to-debug cases where fd fields are accessed even after calling - * fd_destroy(). The following invalidates fd fields to make catching such - * errors easier */ - void invalidate() { - fd = -1; - gpr_atm_no_barrier_store(&refst, -1); - memset(&orphan_mu, -1, sizeof(orphan_mu)); - memset(&pollable_mu, -1, sizeof(pollable_mu)); - pollable_obj = nullptr; - on_done_closure = nullptr; - memset(&iomgr_object, -1, sizeof(iomgr_object)); - track_err = false; - } -#else - void invalidate() {} -#endif +// Monotonically increasing Epoch counter that is assinged to each grpc_fd. See +// the description of 'salt' variable in 'grpc_fd' for more details +// TODO: (sreek/kpayson) gpr_atm is intptr_t which may not be wide-enough on +// 32-bit systems. Change this to int_64 - atleast on 32-bit systems +static gpr_atm g_fd_salt; +struct grpc_fd { int fd; + // Since fd numbers can be reused (after old fds are closed), this serves as + // an epoch that uniquely identifies this fd (i.e the pair (salt, fd) is + // unique (until the salt counter (i.e g_fd_salt) overflows) + intptr_t salt; + // refst format: // bit 0 : 1=Active / 0=Orphaned // bits 1-n : refcount // Ref/Unref by two to avoid altering the orphaned bit - gpr_atm refst = 1; + gpr_atm refst; gpr_mu orphan_mu; - // Protects pollable_obj and pollsets. gpr_mu pollable_mu; - grpc_core::InlinedVector pollsets; // Used in PO_MULTI. - pollable* pollable_obj = nullptr; // Used in PO_FD. + pollable* pollable_obj; - grpc_core::LockfreeEvent read_closure; - grpc_core::LockfreeEvent write_closure; - grpc_core::LockfreeEvent error_closure; + grpc_core::ManualConstructor read_closure; + grpc_core::ManualConstructor write_closure; + grpc_core::ManualConstructor error_closure; - struct grpc_fd* freelist_next = nullptr; - grpc_closure* on_done_closure = nullptr; + struct grpc_fd* freelist_next; + grpc_closure* on_done_closure; grpc_iomgr_object iomgr_object; @@ -269,7 +258,6 @@ struct grpc_pollset_worker { struct grpc_pollset { gpr_mu mu; gpr_atm worker_count; - gpr_atm active_pollable_type; pollable* active_pollable; bool kicked_without_poller; grpc_closure* shutdown_closure; @@ -349,10 +337,39 @@ static void ref_by(grpc_fd* fd, int n) { GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); } +#ifndef NDEBUG +#define INVALIDATE_FD(fd) invalidate_fd(fd) +/* Since an fd is never really destroyed (i.e gpr_free() is not called), it is + * hard to cases where fd fields are accessed even after calling fd_destroy(). + * The following invalidates fd fields to make catching such errors easier */ +static void invalidate_fd(grpc_fd* fd) { + fd->fd = -1; + fd->salt = -1; + gpr_atm_no_barrier_store(&fd->refst, -1); + memset(&fd->orphan_mu, -1, sizeof(fd->orphan_mu)); + memset(&fd->pollable_mu, -1, sizeof(fd->pollable_mu)); + fd->pollable_obj = nullptr; + fd->on_done_closure = nullptr; + memset(&fd->iomgr_object, -1, sizeof(fd->iomgr_object)); + fd->track_err = false; +} +#else +#define INVALIDATE_FD(fd) +#endif + /* Uninitialize and add to the freelist */ static void fd_destroy(void* arg, grpc_error* error) { grpc_fd* fd = static_cast(arg); - fd->destroy(); + grpc_iomgr_unregister_object(&fd->iomgr_object); + POLLABLE_UNREF(fd->pollable_obj, "fd_pollable"); + gpr_mu_destroy(&fd->pollable_mu); + gpr_mu_destroy(&fd->orphan_mu); + + fd->read_closure->DestroyEvent(); + fd->write_closure->DestroyEvent(); + fd->error_closure->DestroyEvent(); + + INVALIDATE_FD(fd); /* Add the fd to the freelist */ gpr_mu_lock(&fd_freelist_mu); @@ -412,9 +429,35 @@ static grpc_fd* fd_create(int fd, const char* name, bool track_err) { if (new_fd == nullptr) { new_fd = static_cast(gpr_malloc(sizeof(grpc_fd))); + new_fd->read_closure.Init(); + new_fd->write_closure.Init(); + new_fd->error_closure.Init(); + } + + new_fd->fd = fd; + new_fd->salt = gpr_atm_no_barrier_fetch_add(&g_fd_salt, 1); + gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); + gpr_mu_init(&new_fd->orphan_mu); + gpr_mu_init(&new_fd->pollable_mu); + new_fd->pollable_obj = nullptr; + new_fd->read_closure->InitEvent(); + new_fd->write_closure->InitEvent(); + new_fd->error_closure->InitEvent(); + new_fd->freelist_next = nullptr; + new_fd->on_done_closure = nullptr; + + char* fd_name; + gpr_asprintf(&fd_name, "%s fd=%d", name, fd); + grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); +#ifndef NDEBUG + if (grpc_trace_fd_refcount.enabled()) { + gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, new_fd, fd_name); } +#endif + gpr_free(fd_name); - return new (new_fd) grpc_fd(fd, name, track_err); + new_fd->track_err = track_err; + return new_fd; } static int fd_wrapped_fd(grpc_fd* fd) { @@ -422,7 +465,6 @@ static int fd_wrapped_fd(grpc_fd* fd) { return (gpr_atm_acq_load(&fd->refst) & 1) ? ret_fd : -1; } -static int pollset_epoll_fd_locked(grpc_pollset* pollset); static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, const char* reason) { bool is_fd_closed = false; @@ -433,6 +475,7 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, // true so that the pollable will no longer access its owner_fd field. gpr_mu_lock(&fd->pollable_mu); pollable* pollable_obj = fd->pollable_obj; + gpr_mu_unlock(&fd->pollable_mu); if (pollable_obj) { gpr_mu_lock(&pollable_obj->owner_orphan_mu); @@ -444,20 +487,6 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, /* If release_fd is not NULL, we should be relinquishing control of the file descriptor fd->fd (but we still own the grpc_fd structure). */ if (release_fd != nullptr) { - // Remove the FD from all epolls sets, before releasing it. - // Otherwise, we will receive epoll events after we release the FD. - epoll_event ev_fd; - memset(&ev_fd, 0, sizeof(ev_fd)); - if (release_fd != nullptr) { - if (pollable_obj != nullptr) { // For PO_FD. - epoll_ctl(pollable_obj->epfd, EPOLL_CTL_DEL, fd->fd, &ev_fd); - } - for (size_t i = 0; i < fd->pollsets.size(); ++i) { // For PO_MULTI. - grpc_pollset* pollset = fd->pollsets[i]; - const int epfd = pollset_epoll_fd_locked(pollset); - epoll_ctl(epfd, EPOLL_CTL_DEL, fd->fd, &ev_fd); - } - } *release_fd = fd->fd; } else { close(fd->fd); @@ -479,56 +508,40 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, gpr_mu_unlock(&pollable_obj->owner_orphan_mu); } - gpr_mu_unlock(&fd->pollable_mu); gpr_mu_unlock(&fd->orphan_mu); UNREF_BY(fd, 2, reason); /* Drop the reference */ } static bool fd_is_shutdown(grpc_fd* fd) { - return fd->read_closure.IsShutdown(); + return fd->read_closure->IsShutdown(); } /* Might be called multiple times */ static void fd_shutdown(grpc_fd* fd, grpc_error* why) { - if (fd->read_closure.SetShutdown(GRPC_ERROR_REF(why))) { + if (fd->read_closure->SetShutdown(GRPC_ERROR_REF(why))) { if (shutdown(fd->fd, SHUT_RDWR)) { if (errno != ENOTCONN) { gpr_log(GPR_ERROR, "Error shutting down fd %d. errno: %d", grpc_fd_wrapped_fd(fd), errno); } } - fd->write_closure.SetShutdown(GRPC_ERROR_REF(why)); - fd->error_closure.SetShutdown(GRPC_ERROR_REF(why)); + fd->write_closure->SetShutdown(GRPC_ERROR_REF(why)); + fd->error_closure->SetShutdown(GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } static void fd_notify_on_read(grpc_fd* fd, grpc_closure* closure) { - fd->read_closure.NotifyOn(closure); + fd->read_closure->NotifyOn(closure); } static void fd_notify_on_write(grpc_fd* fd, grpc_closure* closure) { - fd->write_closure.NotifyOn(closure); + fd->write_closure->NotifyOn(closure); } static void fd_notify_on_error(grpc_fd* fd, grpc_closure* closure) { - fd->error_closure.NotifyOn(closure); -} - -static bool fd_has_pollset(grpc_fd* fd, grpc_pollset* pollset) { - grpc_core::MutexLock lock(&fd->pollable_mu); - for (size_t i = 0; i < fd->pollsets.size(); ++i) { - if (fd->pollsets[i] == pollset) { - return true; - } - } - return false; -} - -static void fd_add_pollset(grpc_fd* fd, grpc_pollset* pollset) { - grpc_core::MutexLock lock(&fd->pollable_mu); - fd->pollsets.push_back(pollset); + fd->error_closure->NotifyOn(closure); } /******************************************************************************* @@ -581,6 +594,8 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) { (*p)->root_worker = nullptr; (*p)->event_cursor = 0; (*p)->event_count = 0; + (*p)->fd_cache_size = 0; + (*p)->fd_cache_counter = 0; return GRPC_ERROR_NONE; } @@ -622,6 +637,39 @@ static grpc_error* pollable_add_fd(pollable* p, grpc_fd* fd) { grpc_error* error = GRPC_ERROR_NONE; static const char* err_desc = "pollable_add_fd"; const int epfd = p->epfd; + gpr_mu_lock(&p->mu); + p->fd_cache_counter++; + + // Handle the case of overflow for our cache counter by + // reseting the recency-counter on all cache objects + if (p->fd_cache_counter == 0) { + for (int i = 0; i < p->fd_cache_size; i++) { + p->fd_cache[i].last_used = 0; + } + } + + int lru_idx = 0; + for (int i = 0; i < p->fd_cache_size; i++) { + if (p->fd_cache[i].fd == fd->fd && p->fd_cache[i].salt == fd->salt) { + GRPC_STATS_INC_POLLSET_FD_CACHE_HITS(); + p->fd_cache[i].last_used = p->fd_cache_counter; + gpr_mu_unlock(&p->mu); + return GRPC_ERROR_NONE; + } else if (p->fd_cache[i].last_used < p->fd_cache[lru_idx].last_used) { + lru_idx = i; + } + } + + // Add to cache + if (p->fd_cache_size < MAX_FDS_IN_CACHE) { + lru_idx = p->fd_cache_size; + p->fd_cache_size++; + } + p->fd_cache[lru_idx].fd = fd->fd; + p->fd_cache[lru_idx].salt = fd->salt; + p->fd_cache[lru_idx].last_used = p->fd_cache_counter; + gpr_mu_unlock(&p->mu); + if (grpc_polling_trace.enabled()) { gpr_log(GPR_INFO, "add fd %p (%d) to pollable %p", fd, fd->fd, p); } @@ -801,7 +849,6 @@ static grpc_error* pollset_kick_all(grpc_pollset* pollset) { static void pollset_init(grpc_pollset* pollset, gpr_mu** mu) { gpr_mu_init(&pollset->mu); gpr_atm_no_barrier_store(&pollset->worker_count, 0); - gpr_atm_no_barrier_store(&pollset->active_pollable_type, PO_EMPTY); pollset->active_pollable = POLLABLE_REF(g_empty_pollable, "pollset"); pollset->kicked_without_poller = false; pollset->shutdown_closure = nullptr; @@ -822,11 +869,11 @@ static int poll_deadline_to_millis_timeout(grpc_millis millis) { return static_cast(delta); } -static void fd_become_readable(grpc_fd* fd) { fd->read_closure.SetReady(); } +static void fd_become_readable(grpc_fd* fd) { fd->read_closure->SetReady(); } -static void fd_become_writable(grpc_fd* fd) { fd->write_closure.SetReady(); } +static void fd_become_writable(grpc_fd* fd) { fd->write_closure->SetReady(); } -static void fd_has_errors(grpc_fd* fd) { fd->error_closure.SetReady(); } +static void fd_has_errors(grpc_fd* fd) { fd->error_closure->SetReady(); } /* Get the pollable_obj attached to this fd. If none is attached, create a new * pollable object (of type PO_FD), attach it to the fd and return it @@ -1236,8 +1283,6 @@ static grpc_error* pollset_add_fd_locked(grpc_pollset* pollset, grpc_fd* fd) { POLLABLE_UNREF(pollset->active_pollable, "pollset"); pollset->active_pollable = po_at_start; } else { - gpr_atm_rel_store(&pollset->active_pollable_type, - pollset->active_pollable->type); POLLABLE_UNREF(po_at_start, "pollset_add_fd"); } return error; @@ -1284,38 +1329,17 @@ static grpc_error* pollset_as_multipollable_locked(grpc_pollset* pollset, pollset->active_pollable = po_at_start; *pollable_obj = nullptr; } else { - gpr_atm_rel_store(&pollset->active_pollable_type, - pollset->active_pollable->type); *pollable_obj = POLLABLE_REF(pollset->active_pollable, "pollset_set"); POLLABLE_UNREF(po_at_start, "pollset_as_multipollable"); } return error; } -// Caller must hold the lock for `pollset->mu`. -static int pollset_epoll_fd_locked(grpc_pollset* pollset) { - return pollset->active_pollable->epfd; -} - static void pollset_add_fd(grpc_pollset* pollset, grpc_fd* fd) { GPR_TIMER_SCOPE("pollset_add_fd", 0); - - // We never transition from PO_MULTI to other modes (i.e., PO_FD or PO_EMOPTY) - // and, thus, it is safe to simply store and check whether the FD has already - // been added to the active pollable previously. - if (gpr_atm_acq_load(&pollset->active_pollable_type) == PO_MULTI && - fd_has_pollset(fd, pollset)) { - return; - } - - grpc_core::MutexLock lock(&pollset->mu); + gpr_mu_lock(&pollset->mu); grpc_error* error = pollset_add_fd_locked(pollset, fd); - - // If we are in PO_MULTI mode, we should update the pollsets of the FD. - if (gpr_atm_no_barrier_load(&pollset->active_pollable_type) == PO_MULTI) { - fd_add_pollset(fd, pollset); - } - + gpr_mu_unlock(&pollset->mu); GRPC_LOG_IF_ERROR("pollset_add_fd", error); } From bfd89bcec589298780af86336b39ead756775a95 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 6 Feb 2019 17:56:03 -0800 Subject: [PATCH 168/218] Don't run for poll and poll-cv --- test/core/end2end/tests/keepalive_timeout.cc | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/test/core/end2end/tests/keepalive_timeout.cc b/test/core/end2end/tests/keepalive_timeout.cc index 38ff37fca6a..f39a33cff9b 100644 --- a/test/core/end2end/tests/keepalive_timeout.cc +++ b/test/core/end2end/tests/keepalive_timeout.cc @@ -91,7 +91,6 @@ static void end_test(grpc_end2end_test_fixture* f) { /* Client sends a request, server replies with a payload, then waits for the keepalive watchdog timeouts before returning status. */ -#if 0 static void test_keepalive_timeout(grpc_end2end_test_config config) { grpc_call* c; grpc_call* s; @@ -220,15 +219,20 @@ static void test_keepalive_timeout(grpc_end2end_test_config config) { end_test(&f); config.tear_down_data(&f); } -#endif /* Verify that reads reset the keepalive ping timer. The client sends 30 pings * with a sleep of 10ms in between. It has a configured keepalive timer of * 200ms. In the success case, each ping ack should reset the keepalive timer so * that the keepalive ping is never sent. */ static void test_read_delays_keepalive(grpc_end2end_test_config config) { - gpr_log(GPR_ERROR, "ura"); - const int kPingIntervalMS = 5; + char* poller = gpr_getenv("GRPC_POLL_STRATEGY"); + /* It is hard to get the timing right for the polling engines poll and poll-cv */ + if(poller != nullptr && (0 == strcmp(poller, "poll-cv") || 0 == strcmp(poller, "poll"))) { + gpr_free(poller); + return; + } + gpr_free(poller); + const int kPingIntervalMS = 100; grpc_arg keepalive_arg_elems[3]; keepalive_arg_elems[0].type = GRPC_ARG_INTEGER; keepalive_arg_elems[0].key = const_cast(GRPC_ARG_KEEPALIVE_TIME_MS); @@ -377,9 +381,7 @@ static void test_read_delays_keepalive(grpc_end2end_test_config config) { grpc_byte_buffer_destroy(request_payload_recv); grpc_byte_buffer_destroy(response_payload_recv); /* Sleep for a short interval to check if the client sends any pings */ - gpr_log(GPR_ERROR, "before sleep"); gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(kPingIntervalMS)); - gpr_log(GPR_ERROR, "after sleep"); } grpc_slice_unref(request_payload_slice); @@ -431,7 +433,7 @@ static void test_read_delays_keepalive(grpc_end2end_test_config config) { } void keepalive_timeout(grpc_end2end_test_config config) { - // test_keepalive_timeout(config); + test_keepalive_timeout(config); test_read_delays_keepalive(config); } From 5a9eb31a3e6ca2aa80bd41e7018ccabd71a4e9c1 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 6 Feb 2019 18:15:28 -0800 Subject: [PATCH 169/218] Clang format --- test/core/end2end/tests/keepalive_timeout.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/core/end2end/tests/keepalive_timeout.cc b/test/core/end2end/tests/keepalive_timeout.cc index f39a33cff9b..c4025e93b82 100644 --- a/test/core/end2end/tests/keepalive_timeout.cc +++ b/test/core/end2end/tests/keepalive_timeout.cc @@ -226,8 +226,10 @@ static void test_keepalive_timeout(grpc_end2end_test_config config) { * that the keepalive ping is never sent. */ static void test_read_delays_keepalive(grpc_end2end_test_config config) { char* poller = gpr_getenv("GRPC_POLL_STRATEGY"); - /* It is hard to get the timing right for the polling engines poll and poll-cv */ - if(poller != nullptr && (0 == strcmp(poller, "poll-cv") || 0 == strcmp(poller, "poll"))) { + /* It is hard to get the timing right for the polling engines poll and poll-cv + */ + if (poller != nullptr && + (0 == strcmp(poller, "poll-cv") || 0 == strcmp(poller, "poll"))) { gpr_free(poller); return; } From 25797cf8062288a24fe300307f356dc9665776e8 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 6 Feb 2019 18:45:06 -0800 Subject: [PATCH 170/218] Add logging around GOAWAYs and keepalives --- .../chttp2/transport/chttp2_transport.cc | 16 +++++++++++++--- 1 file changed, 13 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 c2b57ed2905..34477c93230 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -1119,9 +1119,6 @@ static void queue_setting_update(grpc_chttp2_transport* t, void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t, uint32_t goaway_error, grpc_slice goaway_text) { - // GRPC_CHTTP2_IF_TRACING( - // gpr_log(GPR_INFO, "got goaway [%d]: %s", goaway_error, msg)); - // Discard the error from a previous goaway frame (if any) if (t->goaway_error != GRPC_ERROR_NONE) { GRPC_ERROR_UNREF(t->goaway_error); @@ -1132,6 +1129,9 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t, GRPC_ERROR_INT_HTTP2_ERROR, static_cast(goaway_error)), GRPC_ERROR_STR_RAW_BYTES, goaway_text); + gpr_log(GPR_ERROR, "%s: Got goaway [%d] err=%s", t->peer_string, goaway_error, + grpc_error_string(t->goaway_error)); + /* When a client receives a GOAWAY with error code ENHANCE_YOUR_CALM and debug * data equal to "too_many_pings", it should log the occurrence at a log level * that is enabled by default and double the configured KEEPALIVE_TIME used @@ -1774,6 +1774,8 @@ void grpc_chttp2_ack_ping(grpc_chttp2_transport* t, uint64_t id) { } static void send_goaway(grpc_chttp2_transport* t, grpc_error* error) { + gpr_log(GPR_ERROR, "%s: Sending goaway err=%s", t->peer_string, + grpc_error_string(error)); t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED; grpc_http2_error_code http_error; grpc_slice slice; @@ -2723,6 +2725,9 @@ static void start_keepalive_ping_locked(void* arg, grpc_error* error) { if (t->channelz_socket != nullptr) { t->channelz_socket->RecordKeepaliveSent(); } + if (grpc_http_trace.enabled()) { + gpr_log(GPR_INFO, "%s: Start keepalive ping", t->peer_string); + } GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog"); grpc_timer_init(&t->keepalive_watchdog_timer, grpc_core::ExecCtx::Get()->Now() + t->keepalive_timeout, @@ -2733,6 +2738,9 @@ static void finish_keepalive_ping_locked(void* arg, grpc_error* error) { grpc_chttp2_transport* t = static_cast(arg); if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { if (error == GRPC_ERROR_NONE) { + if (grpc_http_trace.enabled()) { + gpr_log(GPR_INFO, "%s: Finish keepalive ping", t->peer_string); + } t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING; grpc_timer_cancel(&t->keepalive_watchdog_timer); GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping"); @@ -2748,6 +2756,8 @@ static void keepalive_watchdog_fired_locked(void* arg, grpc_error* error) { grpc_chttp2_transport* t = static_cast(arg); if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { if (error == GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "%s: Keepalive watchdog fired. Closing transport.", + t->peer_string); t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING; close_transport_locked( t, grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( From 3af64e8495c8cb62966273db5c48c95f5e4ab905 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Wed, 6 Feb 2019 19:22:15 -0800 Subject: [PATCH 171/218] Reduce logging level to info from error for goaway --- src/core/ext/transport/chttp2/transport/chttp2_transport.cc | 6 ++++-- 1 file changed, 4 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 34477c93230..8e8c9b88493 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -1129,7 +1129,8 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t, GRPC_ERROR_INT_HTTP2_ERROR, static_cast(goaway_error)), GRPC_ERROR_STR_RAW_BYTES, goaway_text); - gpr_log(GPR_ERROR, "%s: Got goaway [%d] err=%s", t->peer_string, goaway_error, + /* We want to log this irrespective of whether http tracing is enabled */ + gpr_log(GPR_INFO, "%s: Got goaway [%d] err=%s", t->peer_string, goaway_error, grpc_error_string(t->goaway_error)); /* When a client receives a GOAWAY with error code ENHANCE_YOUR_CALM and debug @@ -1774,7 +1775,8 @@ void grpc_chttp2_ack_ping(grpc_chttp2_transport* t, uint64_t id) { } static void send_goaway(grpc_chttp2_transport* t, grpc_error* error) { - gpr_log(GPR_ERROR, "%s: Sending goaway err=%s", t->peer_string, + /* We want to log this irrespective of whether http tracing is enabled */ + gpr_log(GPR_INFO, "%s: Sending goaway err=%s", t->peer_string, grpc_error_string(error)); t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED; grpc_http2_error_code http_error; From 486b1fe3206d922d80b201861b8816b30639a0c9 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 7 Feb 2019 10:21:09 +0100 Subject: [PATCH 172/218] Fix bad_client_simple_request test. The data of 0xffffffff is actually not illegal, the top bit should be ingored according to the spec. --- test/core/bad_client/tests/simple_request.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/core/bad_client/tests/simple_request.cc b/test/core/bad_client/tests/simple_request.cc index 34049aaaffc..614f5869976 100644 --- a/test/core/bad_client/tests/simple_request.cc +++ b/test/core/bad_client/tests/simple_request.cc @@ -147,11 +147,12 @@ int main(int argc, char** argv) { /* push a window update with bad flags */ GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr, PFX_STR "\x00\x00\x00\x08\x10\x00\x00\x00\x01", 0); - /* push a window update with bad data */ + /* push a window update with bad data (0 is not legal window size increment) + */ GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr, PFX_STR "\x00\x00\x04\x08\x00\x00\x00\x00\x01" - "\xff\xff\xff\xff", + "\x00\x00\x00\x00", 0); /* push a short goaway */ GRPC_RUN_BAD_CLIENT_TEST(failure_verifier, nullptr, From 75dec4d0f22eb0dbd51bb584ca624f861744d218 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Thu, 7 Feb 2019 11:15:07 -0500 Subject: [PATCH 173/218] Track the pollsets of an FD in PO_MULTI mode for pollex. Each pollset in pollex has a lock, grabbed upon adding an FD to the pollset. Since this is called on a per-call basis, there is a flat array caching the FDs of the pollset, to avoid unnecessarily calling epoll_ctl multiple times for the same FD. This has two problems: 1) When multiple threads add FDs to the same pollset, we will have contention on the pollset lock. 2) When we have many FDs we simply run out of cache storage, and call epoll_ctl(). This commit changes the caching strategy by simply storing the epfd of pollsets of an FD inside that FD, when we are in PO_MULTI mode. This results in address in both (1) and (2). Moreover, this commit fixes another performance bug. When we have a release FD callback, we do not call close(). That FD will remain in our epollset, until the new owner of the FD actually call close(). This results in a lot of spurious wake ups when we simply hand off gRPC FDs to other FDs. Note that this is a revision on the reverted commit e83e463b5a14cf0de5d8c9e1197d06f925160111 (PR #17823). The main change is to track the epfd of the pollset instead of the pollset pointer, so that if the pollset is deleted we can still access the FD. It also halves the size of the cache vector for 64-bit machines. --- src/core/lib/iomgr/ev_epollex_linux.cc | 295 +++++++++++-------------- 1 file changed, 133 insertions(+), 162 deletions(-) diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index 0a0891013af..b6d13b44d12 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -45,6 +45,7 @@ #include "src/core/lib/gpr/spinlock.h" #include "src/core/lib/gpr/tls.h" #include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/iomgr/block_annotate.h" @@ -78,18 +79,6 @@ typedef enum { PO_MULTI, PO_FD, PO_EMPTY } pollable_type; typedef struct pollable pollable; -typedef struct cached_fd { - // Set to the grpc_fd's salt value. See 'salt' variable' in grpc_fd for more - // details - intptr_t salt; - - // The underlying fd - int fd; - - // A recency time counter that helps to determine the LRU fd in the cache - uint64_t last_used; -} cached_fd; - /// A pollable is something that can be polled: it has an epoll set to poll on, /// and a wakeup fd for kicks /// There are three broad types: @@ -120,33 +109,6 @@ struct pollable { int event_cursor; int event_count; struct epoll_event events[MAX_EPOLL_EVENTS]; - - // We may be calling pollable_add_fd() on the same (pollable, fd) multiple - // times. To prevent pollable_add_fd() from making multiple sys calls to - // epoll_ctl() to add the fd, we maintain a cache of what fds are already - // present in the underlying epoll-set. - // - // Since this is not a correctness issue, we do not need to maintain all the - // fds in the cache. Hence we just use an LRU cache of size 'MAX_FDS_IN_CACHE' - // - // NOTE: An ideal implementation of this should do the following: - // 1) Add fds to the cache in pollable_add_fd() function (i.e whenever the fd - // is added to the pollable's epoll set) - // 2) Remove the fd from the cache whenever the fd is removed from the - // underlying epoll set (i.e whenever fd_orphan() is called). - // - // Implementing (2) above (i.e removing fds from cache on fd_orphan) adds a - // lot of complexity since an fd can be present in multiple pollables. So our - // implementation ONLY DOES (1) and NOT (2). - // - // The cache_fd.salt variable helps here to maintain correctness (it serves as - // an epoch that differentiates one grpc_fd from the other even though both of - // them may have the same fd number) - // - // The following implements LRU-eviction cache of fds in this pollable - cached_fd fd_cache[MAX_FDS_IN_CACHE]; - int fd_cache_size; - uint64_t fd_cache_counter; // Recency timer tick counter }; static const char* pollable_type_string(pollable_type t) { @@ -189,37 +151,86 @@ static void pollable_unref(pollable* p, int line, const char* reason); * Fd Declarations */ -// Monotonically increasing Epoch counter that is assinged to each grpc_fd. See -// the description of 'salt' variable in 'grpc_fd' for more details -// TODO: (sreek/kpayson) gpr_atm is intptr_t which may not be wide-enough on -// 32-bit systems. Change this to int_64 - atleast on 32-bit systems -static gpr_atm g_fd_salt; - struct grpc_fd { - int fd; + grpc_fd(int fd, const char* name, bool track_err) + : fd(fd), track_err(track_err) { + gpr_mu_init(&orphan_mu); + gpr_mu_init(&pollable_mu); + read_closure.InitEvent(); + write_closure.InitEvent(); + error_closure.InitEvent(); + + char* fd_name; + gpr_asprintf(&fd_name, "%s fd=%d", name, fd); + grpc_iomgr_register_object(&iomgr_object, fd_name); +#ifndef NDEBUG + if (grpc_trace_fd_refcount.enabled()) { + gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, this, fd_name); + } +#endif + gpr_free(fd_name); + } + + // This is really the dtor, but the poller threads waking up from + // epoll_wait() may access the (read|write|error)_closure after destruction. + // Since the object will be added to the free pool, this behavior is + // not going to cause issues, except spurious events if the FD is reused + // while the race happens. + void destroy() { + grpc_iomgr_unregister_object(&iomgr_object); - // Since fd numbers can be reused (after old fds are closed), this serves as - // an epoch that uniquely identifies this fd (i.e the pair (salt, fd) is - // unique (until the salt counter (i.e g_fd_salt) overflows) - intptr_t salt; + POLLABLE_UNREF(pollable_obj, "fd_pollable"); + pollset_fds.clear(); + gpr_mu_destroy(&pollable_mu); + gpr_mu_destroy(&orphan_mu); + + read_closure.DestroyEvent(); + write_closure.DestroyEvent(); + error_closure.DestroyEvent(); + + invalidate(); + } + +#ifndef NDEBUG + /* Since an fd is never really destroyed (i.e gpr_free() is not called), it is + * hard-to-debug cases where fd fields are accessed even after calling + * fd_destroy(). The following invalidates fd fields to make catching such + * errors easier */ + void invalidate() { + fd = -1; + gpr_atm_no_barrier_store(&refst, -1); + memset(&orphan_mu, -1, sizeof(orphan_mu)); + memset(&pollable_mu, -1, sizeof(pollable_mu)); + pollable_obj = nullptr; + on_done_closure = nullptr; + memset(&iomgr_object, -1, sizeof(iomgr_object)); + track_err = false; + } +#else + void invalidate() {} +#endif + + int fd; // refst format: // bit 0 : 1=Active / 0=Orphaned // bits 1-n : refcount // Ref/Unref by two to avoid altering the orphaned bit - gpr_atm refst; + gpr_atm refst = 1; gpr_mu orphan_mu; + // Protects pollable_obj and pollset_fds. gpr_mu pollable_mu; - pollable* pollable_obj; + grpc_core::InlinedVector pollset_fds; // Used in PO_MULTI. + pollable* pollable_obj = nullptr; // Used in PO_FD. - grpc_core::ManualConstructor read_closure; - grpc_core::ManualConstructor write_closure; - grpc_core::ManualConstructor error_closure; + grpc_core::LockfreeEvent read_closure; + grpc_core::LockfreeEvent write_closure; + grpc_core::LockfreeEvent error_closure; - struct grpc_fd* freelist_next; - grpc_closure* on_done_closure; + struct grpc_fd* freelist_next = nullptr; + grpc_closure* on_done_closure = nullptr; grpc_iomgr_object iomgr_object; @@ -258,6 +269,7 @@ struct grpc_pollset_worker { struct grpc_pollset { gpr_mu mu; gpr_atm worker_count; + gpr_atm active_pollable_type; pollable* active_pollable; bool kicked_without_poller; grpc_closure* shutdown_closure; @@ -337,39 +349,10 @@ static void ref_by(grpc_fd* fd, int n) { GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); } -#ifndef NDEBUG -#define INVALIDATE_FD(fd) invalidate_fd(fd) -/* Since an fd is never really destroyed (i.e gpr_free() is not called), it is - * hard to cases where fd fields are accessed even after calling fd_destroy(). - * The following invalidates fd fields to make catching such errors easier */ -static void invalidate_fd(grpc_fd* fd) { - fd->fd = -1; - fd->salt = -1; - gpr_atm_no_barrier_store(&fd->refst, -1); - memset(&fd->orphan_mu, -1, sizeof(fd->orphan_mu)); - memset(&fd->pollable_mu, -1, sizeof(fd->pollable_mu)); - fd->pollable_obj = nullptr; - fd->on_done_closure = nullptr; - memset(&fd->iomgr_object, -1, sizeof(fd->iomgr_object)); - fd->track_err = false; -} -#else -#define INVALIDATE_FD(fd) -#endif - /* Uninitialize and add to the freelist */ static void fd_destroy(void* arg, grpc_error* error) { grpc_fd* fd = static_cast(arg); - grpc_iomgr_unregister_object(&fd->iomgr_object); - POLLABLE_UNREF(fd->pollable_obj, "fd_pollable"); - gpr_mu_destroy(&fd->pollable_mu); - gpr_mu_destroy(&fd->orphan_mu); - - fd->read_closure->DestroyEvent(); - fd->write_closure->DestroyEvent(); - fd->error_closure->DestroyEvent(); - - INVALIDATE_FD(fd); + fd->destroy(); /* Add the fd to the freelist */ gpr_mu_lock(&fd_freelist_mu); @@ -429,35 +412,9 @@ static grpc_fd* fd_create(int fd, const char* name, bool track_err) { if (new_fd == nullptr) { new_fd = static_cast(gpr_malloc(sizeof(grpc_fd))); - new_fd->read_closure.Init(); - new_fd->write_closure.Init(); - new_fd->error_closure.Init(); - } - - new_fd->fd = fd; - new_fd->salt = gpr_atm_no_barrier_fetch_add(&g_fd_salt, 1); - gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); - gpr_mu_init(&new_fd->orphan_mu); - gpr_mu_init(&new_fd->pollable_mu); - new_fd->pollable_obj = nullptr; - new_fd->read_closure->InitEvent(); - new_fd->write_closure->InitEvent(); - new_fd->error_closure->InitEvent(); - new_fd->freelist_next = nullptr; - new_fd->on_done_closure = nullptr; - - char* fd_name; - gpr_asprintf(&fd_name, "%s fd=%d", name, fd); - grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); -#ifndef NDEBUG - if (grpc_trace_fd_refcount.enabled()) { - gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, new_fd, fd_name); } -#endif - gpr_free(fd_name); - new_fd->track_err = track_err; - return new_fd; + return new (new_fd) grpc_fd(fd, name, track_err); } static int fd_wrapped_fd(grpc_fd* fd) { @@ -475,7 +432,6 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, // true so that the pollable will no longer access its owner_fd field. gpr_mu_lock(&fd->pollable_mu); pollable* pollable_obj = fd->pollable_obj; - gpr_mu_unlock(&fd->pollable_mu); if (pollable_obj) { gpr_mu_lock(&pollable_obj->owner_orphan_mu); @@ -487,6 +443,19 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, /* If release_fd is not NULL, we should be relinquishing control of the file descriptor fd->fd (but we still own the grpc_fd structure). */ if (release_fd != nullptr) { + // Remove the FD from all epolls sets, before releasing it. + // Otherwise, we will receive epoll events after we release the FD. + epoll_event ev_fd; + memset(&ev_fd, 0, sizeof(ev_fd)); + if (release_fd != nullptr) { + if (pollable_obj != nullptr) { // For PO_FD. + epoll_ctl(pollable_obj->epfd, EPOLL_CTL_DEL, fd->fd, &ev_fd); + } + for (size_t i = 0; i < fd->pollset_fds.size(); ++i) { // For PO_MULTI. + const int epfd = fd->pollset_fds[i]; + epoll_ctl(epfd, EPOLL_CTL_DEL, fd->fd, &ev_fd); + } + } *release_fd = fd->fd; } else { close(fd->fd); @@ -508,40 +477,58 @@ static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, gpr_mu_unlock(&pollable_obj->owner_orphan_mu); } + gpr_mu_unlock(&fd->pollable_mu); gpr_mu_unlock(&fd->orphan_mu); UNREF_BY(fd, 2, reason); /* Drop the reference */ } static bool fd_is_shutdown(grpc_fd* fd) { - return fd->read_closure->IsShutdown(); + return fd->read_closure.IsShutdown(); } /* Might be called multiple times */ static void fd_shutdown(grpc_fd* fd, grpc_error* why) { - if (fd->read_closure->SetShutdown(GRPC_ERROR_REF(why))) { + if (fd->read_closure.SetShutdown(GRPC_ERROR_REF(why))) { if (shutdown(fd->fd, SHUT_RDWR)) { if (errno != ENOTCONN) { gpr_log(GPR_ERROR, "Error shutting down fd %d. errno: %d", grpc_fd_wrapped_fd(fd), errno); } } - fd->write_closure->SetShutdown(GRPC_ERROR_REF(why)); - fd->error_closure->SetShutdown(GRPC_ERROR_REF(why)); + fd->write_closure.SetShutdown(GRPC_ERROR_REF(why)); + fd->error_closure.SetShutdown(GRPC_ERROR_REF(why)); } GRPC_ERROR_UNREF(why); } static void fd_notify_on_read(grpc_fd* fd, grpc_closure* closure) { - fd->read_closure->NotifyOn(closure); + fd->read_closure.NotifyOn(closure); } static void fd_notify_on_write(grpc_fd* fd, grpc_closure* closure) { - fd->write_closure->NotifyOn(closure); + fd->write_closure.NotifyOn(closure); } static void fd_notify_on_error(grpc_fd* fd, grpc_closure* closure) { - fd->error_closure->NotifyOn(closure); + fd->error_closure.NotifyOn(closure); +} + +static bool fd_has_pollset(grpc_fd* fd, grpc_pollset* pollset) { + const int epfd = pollset->active_pollable->epfd; + grpc_core::MutexLock lock(&fd->pollable_mu); + for (size_t i = 0; i < fd->pollset_fds.size(); ++i) { + if (fd->pollset_fds[i] == epfd) { + return true; + } + } + return false; +} + +static void fd_add_pollset(grpc_fd* fd, grpc_pollset* pollset) { + const int epfd = pollset->active_pollable->epfd; + grpc_core::MutexLock lock(&fd->pollable_mu); + fd->pollset_fds.push_back(epfd); } /******************************************************************************* @@ -594,8 +581,6 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) { (*p)->root_worker = nullptr; (*p)->event_cursor = 0; (*p)->event_count = 0; - (*p)->fd_cache_size = 0; - (*p)->fd_cache_counter = 0; return GRPC_ERROR_NONE; } @@ -637,39 +622,6 @@ static grpc_error* pollable_add_fd(pollable* p, grpc_fd* fd) { grpc_error* error = GRPC_ERROR_NONE; static const char* err_desc = "pollable_add_fd"; const int epfd = p->epfd; - gpr_mu_lock(&p->mu); - p->fd_cache_counter++; - - // Handle the case of overflow for our cache counter by - // reseting the recency-counter on all cache objects - if (p->fd_cache_counter == 0) { - for (int i = 0; i < p->fd_cache_size; i++) { - p->fd_cache[i].last_used = 0; - } - } - - int lru_idx = 0; - for (int i = 0; i < p->fd_cache_size; i++) { - if (p->fd_cache[i].fd == fd->fd && p->fd_cache[i].salt == fd->salt) { - GRPC_STATS_INC_POLLSET_FD_CACHE_HITS(); - p->fd_cache[i].last_used = p->fd_cache_counter; - gpr_mu_unlock(&p->mu); - return GRPC_ERROR_NONE; - } else if (p->fd_cache[i].last_used < p->fd_cache[lru_idx].last_used) { - lru_idx = i; - } - } - - // Add to cache - if (p->fd_cache_size < MAX_FDS_IN_CACHE) { - lru_idx = p->fd_cache_size; - p->fd_cache_size++; - } - p->fd_cache[lru_idx].fd = fd->fd; - p->fd_cache[lru_idx].salt = fd->salt; - p->fd_cache[lru_idx].last_used = p->fd_cache_counter; - gpr_mu_unlock(&p->mu); - if (grpc_polling_trace.enabled()) { gpr_log(GPR_INFO, "add fd %p (%d) to pollable %p", fd, fd->fd, p); } @@ -849,6 +801,7 @@ static grpc_error* pollset_kick_all(grpc_pollset* pollset) { static void pollset_init(grpc_pollset* pollset, gpr_mu** mu) { gpr_mu_init(&pollset->mu); gpr_atm_no_barrier_store(&pollset->worker_count, 0); + gpr_atm_no_barrier_store(&pollset->active_pollable_type, PO_EMPTY); pollset->active_pollable = POLLABLE_REF(g_empty_pollable, "pollset"); pollset->kicked_without_poller = false; pollset->shutdown_closure = nullptr; @@ -869,11 +822,11 @@ static int poll_deadline_to_millis_timeout(grpc_millis millis) { return static_cast(delta); } -static void fd_become_readable(grpc_fd* fd) { fd->read_closure->SetReady(); } +static void fd_become_readable(grpc_fd* fd) { fd->read_closure.SetReady(); } -static void fd_become_writable(grpc_fd* fd) { fd->write_closure->SetReady(); } +static void fd_become_writable(grpc_fd* fd) { fd->write_closure.SetReady(); } -static void fd_has_errors(grpc_fd* fd) { fd->error_closure->SetReady(); } +static void fd_has_errors(grpc_fd* fd) { fd->error_closure.SetReady(); } /* Get the pollable_obj attached to this fd. If none is attached, create a new * pollable object (of type PO_FD), attach it to the fd and return it @@ -1283,6 +1236,8 @@ static grpc_error* pollset_add_fd_locked(grpc_pollset* pollset, grpc_fd* fd) { POLLABLE_UNREF(pollset->active_pollable, "pollset"); pollset->active_pollable = po_at_start; } else { + gpr_atm_rel_store(&pollset->active_pollable_type, + pollset->active_pollable->type); POLLABLE_UNREF(po_at_start, "pollset_add_fd"); } return error; @@ -1329,6 +1284,8 @@ static grpc_error* pollset_as_multipollable_locked(grpc_pollset* pollset, pollset->active_pollable = po_at_start; *pollable_obj = nullptr; } else { + gpr_atm_rel_store(&pollset->active_pollable_type, + pollset->active_pollable->type); *pollable_obj = POLLABLE_REF(pollset->active_pollable, "pollset_set"); POLLABLE_UNREF(po_at_start, "pollset_as_multipollable"); } @@ -1337,9 +1294,23 @@ static grpc_error* pollset_as_multipollable_locked(grpc_pollset* pollset, static void pollset_add_fd(grpc_pollset* pollset, grpc_fd* fd) { GPR_TIMER_SCOPE("pollset_add_fd", 0); - gpr_mu_lock(&pollset->mu); + + // We never transition from PO_MULTI to other modes (i.e., PO_FD or PO_EMOPTY) + // and, thus, it is safe to simply store and check whether the FD has already + // been added to the active pollable previously. + if (gpr_atm_acq_load(&pollset->active_pollable_type) == PO_MULTI && + fd_has_pollset(fd, pollset)) { + return; + } + + grpc_core::MutexLock lock(&pollset->mu); grpc_error* error = pollset_add_fd_locked(pollset, fd); - gpr_mu_unlock(&pollset->mu); + + // If we are in PO_MULTI mode, we should update the pollsets of the FD. + if (gpr_atm_no_barrier_load(&pollset->active_pollable_type) == PO_MULTI) { + fd_add_pollset(fd, pollset); + } + GRPC_LOG_IF_ERROR("pollset_add_fd", error); } From f919ace038044b4ee88fa0fb77c87ac8a19d1f06 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Thu, 7 Feb 2019 08:34:54 -0800 Subject: [PATCH 174/218] Add a microbenchmark for immediately-firing alarms --- CMakeLists.txt | 48 ++++++++++++++ Makefile | 49 ++++++++++++++ build.yaml | 20 ++++++ test/cpp/microbenchmarks/BUILD | 7 ++ test/cpp/microbenchmarks/bm_alarm.cc | 64 +++++++++++++++++++ .../generated/sources_and_headers.json | 21 ++++++ tools/run_tests/generated/tests.json | 22 +++++++ 7 files changed, 231 insertions(+) create mode 100644 test/cpp/microbenchmarks/bm_alarm.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 7425e62f8f0..6f1a0f6af9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -538,6 +538,9 @@ add_dependencies(buildtests_cxx auth_property_iterator_test) add_dependencies(buildtests_cxx backoff_test) add_dependencies(buildtests_cxx bdp_estimator_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) +add_dependencies(buildtests_cxx bm_alarm) +endif() +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bm_arena) endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -11177,6 +11180,51 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) +add_executable(bm_alarm + test/cpp/microbenchmarks/bm_alarm.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(bm_alarm + 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_alarm + ${_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) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) + add_executable(bm_arena test/cpp/microbenchmarks/bm_arena.cc third_party/googletest/googletest/src/gtest-all.cc diff --git a/Makefile b/Makefile index 7caf155058a..e41c0584c7d 100644 --- a/Makefile +++ b/Makefile @@ -1137,6 +1137,7 @@ async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test backoff_test: $(BINDIR)/$(CONFIG)/backoff_test bdp_estimator_test: $(BINDIR)/$(CONFIG)/bdp_estimator_test +bm_alarm: $(BINDIR)/$(CONFIG)/bm_alarm bm_arena: $(BINDIR)/$(CONFIG)/bm_arena bm_byte_buffer: $(BINDIR)/$(CONFIG)/bm_byte_buffer bm_call_create: $(BINDIR)/$(CONFIG)/bm_call_create @@ -1654,6 +1655,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \ $(BINDIR)/$(CONFIG)/backoff_test \ $(BINDIR)/$(CONFIG)/bdp_estimator_test \ + $(BINDIR)/$(CONFIG)/bm_alarm \ $(BINDIR)/$(CONFIG)/bm_arena \ $(BINDIR)/$(CONFIG)/bm_byte_buffer \ $(BINDIR)/$(CONFIG)/bm_call_create \ @@ -1842,6 +1844,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \ $(BINDIR)/$(CONFIG)/backoff_test \ $(BINDIR)/$(CONFIG)/bdp_estimator_test \ + $(BINDIR)/$(CONFIG)/bm_alarm \ $(BINDIR)/$(CONFIG)/bm_arena \ $(BINDIR)/$(CONFIG)/bm_byte_buffer \ $(BINDIR)/$(CONFIG)/bm_call_create \ @@ -2285,6 +2288,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/backoff_test || ( echo test backoff_test failed ; exit 1 ) $(E) "[RUN] Testing bdp_estimator_test" $(Q) $(BINDIR)/$(CONFIG)/bdp_estimator_test || ( echo test bdp_estimator_test failed ; exit 1 ) + $(E) "[RUN] Testing bm_alarm" + $(Q) $(BINDIR)/$(CONFIG)/bm_alarm || ( echo test bm_alarm failed ; exit 1 ) $(E) "[RUN] Testing bm_arena" $(Q) $(BINDIR)/$(CONFIG)/bm_arena || ( echo test bm_arena failed ; exit 1 ) $(E) "[RUN] Testing bm_byte_buffer" @@ -16186,6 +16191,50 @@ endif endif +BM_ALARM_SRC = \ + test/cpp/microbenchmarks/bm_alarm.cc \ + +BM_ALARM_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_ALARM_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/bm_alarm: 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_alarm: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/bm_alarm: $(PROTOBUF_DEP) $(BM_ALARM_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_ALARM_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_alarm + +endif + +endif + +$(BM_ALARM_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX +$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_alarm.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_alarm: $(BM_ALARM_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(BM_ALARM_OBJS:.o=.dep) +endif +endif + + BM_ARENA_SRC = \ test/cpp/microbenchmarks/bm_arena.cc \ diff --git a/build.yaml b/build.yaml index bcd98aaac00..ec00450f28a 100644 --- a/build.yaml +++ b/build.yaml @@ -3936,6 +3936,26 @@ targets: - grpc - gpr uses_polling: false +- name: bm_alarm + build: test + language: c++ + src: + - test/cpp/microbenchmarks/bm_alarm.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 - name: bm_arena build: test language: c++ diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD index a29462f78fc..70b4000780c 100644 --- a/test/cpp/microbenchmarks/BUILD +++ b/test/cpp/microbenchmarks/BUILD @@ -54,6 +54,13 @@ grpc_cc_binary( deps = [":helpers"], ) +grpc_cc_binary( + name = "bm_alarm", + testonly = 1, + srcs = ["bm_alarm.cc"], + deps = [":helpers"], +) + grpc_cc_binary( name = "bm_arena", testonly = 1, diff --git a/test/cpp/microbenchmarks/bm_alarm.cc b/test/cpp/microbenchmarks/bm_alarm.cc new file mode 100644 index 00000000000..64aad6476de --- /dev/null +++ b/test/cpp/microbenchmarks/bm_alarm.cc @@ -0,0 +1,64 @@ +/* + * + * 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. + * + */ + +/* This benchmark exists to ensure that immediately-firing alarms are fast */ + +#include +#include +#include +#include +#include +#include "test/core/util/test_config.h" +#include "test/cpp/microbenchmarks/helpers.h" +#include "test/cpp/util/test_config.h" + +namespace grpc { +namespace testing { + +auto& force_library_initialization = Library::get(); + +static void BM_Alarm_Tag_Immediate(benchmark::State& state) { + TrackCounters track_counters; + CompletionQueue cq; + Alarm alarm; + void* output_tag; + bool ok; + auto deadline = grpc_timeout_seconds_to_deadline(0); + while (state.KeepRunning()) { + alarm.Set(&cq, deadline, nullptr); + cq.Next(&output_tag, &ok); + } + track_counters.Finish(state); +} +BENCHMARK(BM_Alarm_Tag_Immediate); + +} // 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 6693fcec58e..ab01b8fca6a 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -2708,6 +2708,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_alarm", + "src": [ + "test/cpp/microbenchmarks/bm_alarm.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "benchmark", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index f35be0c1f43..9a202ecf167 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -3415,6 +3415,28 @@ ], "uses_polling": false }, + { + "args": [], + "benchmark": true, + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": false, + "language": "c++", + "name": "bm_alarm", + "platforms": [ + "linux", + "mac", + "posix" + ], + "uses_polling": true + }, { "args": [], "benchmark": true, From 7e210fac5bb160c086ac3b0c2299190ae8a1e7df Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 6 Feb 2019 10:30:25 -0800 Subject: [PATCH 175/218] Pre-fetch Cocoapods master repo --- tools/internal_ci/helper_scripts/prepare_build_macos_rc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/internal_ci/helper_scripts/prepare_build_macos_rc b/tools/internal_ci/helper_scripts/prepare_build_macos_rc index 23619ecbb8b..2ecd39465d4 100644 --- a/tools/internal_ci/helper_scripts/prepare_build_macos_rc +++ b/tools/internal_ci/helper_scripts/prepare_build_macos_rc @@ -48,6 +48,10 @@ set -ex # cocoapods export LANG=en_US.UTF-8 +# pre-fetch cocoapods master repo with HEAD only +mkdir -p ~/.cocoapods/repos +git clone --depth 1 https://github.com/CocoaPods/Specs.git ~/.cocoapods/repos/master + time pod repo update # needed by python # python From 817c28f22fb39bc4c278cae65588a4009b6c4261 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 7 Feb 2019 18:33:02 +0100 Subject: [PATCH 176/218] scaffolding for flaky network test --- .../internal_ci/linux/grpc_flaky_network.cfg | 23 ++++++++++++++ .../linux/grpc_flaky_network_in_docker.sh | 31 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 tools/internal_ci/linux/grpc_flaky_network.cfg create mode 100755 tools/internal_ci/linux/grpc_flaky_network_in_docker.sh diff --git a/tools/internal_ci/linux/grpc_flaky_network.cfg b/tools/internal_ci/linux/grpc_flaky_network.cfg new file mode 100644 index 00000000000..de7a3b9cd8f --- /dev/null +++ b/tools/internal_ci/linux/grpc_flaky_network.cfg @@ -0,0 +1,23 @@ +# Copyright 2019 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. + +# Config file for the internal CI (in protobuf text format) + +# Location of the continuous shell script in repository. +build_file: "grpc/tools/internal_ci/linux/grpc_bazel.sh" +timeout_mins: 240 +env_vars { + key: "BAZEL_SCRIPT" + value: "tools/internal_ci/linux/grpc_flaky_network_in_docker.sh" +} diff --git a/tools/internal_ci/linux/grpc_flaky_network_in_docker.sh b/tools/internal_ci/linux/grpc_flaky_network_in_docker.sh new file mode 100755 index 00000000000..42b6d44c1cb --- /dev/null +++ b/tools/internal_ci/linux/grpc_flaky_network_in_docker.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# Copyright 2019 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. +# +# Run the flaky network test +# +# NOTE: No empty lines should appear in this file before igncr is set! +set -ex -o igncr || set -ex + +mkdir -p /var/local/git +git clone /var/local/jenkins/grpc /var/local/git/grpc +(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \ +&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \ +${name}') +cd /var/local/git/grpc + +# TODO(jtattermusch): install prerequsites if needed + +# TODO(jtattermusch): run the flaky network test instead +bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... examples/... From 1fab48edfc539c5ac1bb2870d3158dd907c64936 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Wed, 6 Feb 2019 13:53:51 -0800 Subject: [PATCH 177/218] Add null input handling in grpc_json_destroy() --- src/core/lib/json/json.cc | 5 +---- .../credentials/google_default/google_default_credentials.cc | 2 +- src/core/lib/security/credentials/jwt/json_token.cc | 2 +- src/core/lib/security/credentials/jwt/jwt_verifier.cc | 4 ++-- .../lib/security/credentials/oauth2/oauth2_credentials.cc | 4 ++-- 5 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/core/lib/json/json.cc b/src/core/lib/json/json.cc index e78b73cefd3..2ed45fe55fe 100644 --- a/src/core/lib/json/json.cc +++ b/src/core/lib/json/json.cc @@ -35,24 +35,21 @@ grpc_json* grpc_json_create(grpc_json_type type) { } void grpc_json_destroy(grpc_json* json) { + if (json == nullptr) return; while (json->child) { grpc_json_destroy(json->child); } - if (json->next) { json->next->prev = json->prev; } - if (json->prev) { json->prev->next = json->next; } else if (json->parent) { json->parent->child = json->next; } - if (json->owns_value) { gpr_free((void*)json->value); } - gpr_free(json); } diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/src/core/lib/security/credentials/google_default/google_default_credentials.cc index aa57fa2c5ec..b6a79c1030e 100644 --- a/src/core/lib/security/credentials/google_default/google_default_credentials.cc +++ b/src/core/lib/security/credentials/google_default/google_default_credentials.cc @@ -272,7 +272,7 @@ end: GPR_ASSERT((result == nullptr) + (error == GRPC_ERROR_NONE) == 1); if (creds_path != nullptr) gpr_free(creds_path); grpc_slice_unref_internal(creds_data); - if (json != nullptr) grpc_json_destroy(json); + grpc_json_destroy(json); *creds = result; return error; } diff --git a/src/core/lib/security/credentials/jwt/json_token.cc b/src/core/lib/security/credentials/jwt/json_token.cc index 1c4827df0fc..113e2b83754 100644 --- a/src/core/lib/security/credentials/jwt/json_token.cc +++ b/src/core/lib/security/credentials/jwt/json_token.cc @@ -121,7 +121,7 @@ grpc_auth_json_key grpc_auth_json_key_create_from_string( char* scratchpad = gpr_strdup(json_string); grpc_json* json = grpc_json_parse_string(scratchpad); grpc_auth_json_key result = grpc_auth_json_key_create_from_json(json); - if (json != nullptr) grpc_json_destroy(json); + grpc_json_destroy(json); gpr_free(scratchpad); return result; } diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.cc b/src/core/lib/security/credentials/jwt/jwt_verifier.cc index cdef0f322a9..87fe3cc8e08 100644 --- a/src/core/lib/security/credentials/jwt/jwt_verifier.cc +++ b/src/core/lib/security/credentials/jwt/jwt_verifier.cc @@ -666,7 +666,7 @@ static void on_keys_retrieved(void* user_data, grpc_error* error) { } end: - if (json != nullptr) grpc_json_destroy(json); + grpc_json_destroy(json); EVP_PKEY_free(verification_key); ctx->user_cb(ctx->user_data, status, claims); verifier_cb_ctx_destroy(ctx); @@ -719,7 +719,7 @@ static void on_openid_config_retrieved(void* user_data, grpc_error* error) { return; error: - if (json != nullptr) grpc_json_destroy(json); + grpc_json_destroy(json); ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, nullptr); verifier_cb_ctx_destroy(ctx); } diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc b/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc index ad63b01e754..b9af757d05e 100644 --- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc @@ -80,7 +80,7 @@ grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( grpc_json* json = grpc_json_parse_string(scratchpad); grpc_auth_refresh_token result = grpc_auth_refresh_token_create_from_json(json); - if (json != nullptr) grpc_json_destroy(json); + grpc_json_destroy(json); gpr_free(scratchpad); return result; } @@ -199,7 +199,7 @@ end: } if (null_terminated_body != nullptr) gpr_free(null_terminated_body); if (new_access_token != nullptr) gpr_free(new_access_token); - if (json != nullptr) grpc_json_destroy(json); + grpc_json_destroy(json); return status; } From 236d657afc54180e3ae1f56ca1dcc5756fd4c1b4 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 7 Feb 2019 16:06:11 +0100 Subject: [PATCH 178/218] change Grpc.nuspec metapackage into csproj --- src/csharp/Grpc.nuspec | 22 ---------------------- src/csharp/Grpc/.gitignore | 2 ++ src/csharp/Grpc/Grpc.csproj | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 22 deletions(-) delete mode 100644 src/csharp/Grpc.nuspec create mode 100644 src/csharp/Grpc/.gitignore create mode 100644 src/csharp/Grpc/Grpc.csproj diff --git a/src/csharp/Grpc.nuspec b/src/csharp/Grpc.nuspec deleted file mode 100644 index 7fbd8619230..00000000000 --- a/src/csharp/Grpc.nuspec +++ /dev/null @@ -1,22 +0,0 @@ - - - - Grpc - gRPC C# - C# implementation of gRPC - an RPC library and framework - C# implementation of gRPC - an RPC library and framework. See project site for more info. - $version$ - Google Inc. - grpc-packages - https://github.com/grpc/grpc/blob/master/LICENSE - https://github.com/grpc/grpc - false - Release $version$ of gRPC C# - Copyright 2015, Google Inc. - gRPC RPC Protocol HTTP/2 - - - - - - diff --git a/src/csharp/Grpc/.gitignore b/src/csharp/Grpc/.gitignore new file mode 100644 index 00000000000..1746e3269ed --- /dev/null +++ b/src/csharp/Grpc/.gitignore @@ -0,0 +1,2 @@ +bin +obj diff --git a/src/csharp/Grpc/Grpc.csproj b/src/csharp/Grpc/Grpc.csproj new file mode 100644 index 00000000000..9f17e319714 --- /dev/null +++ b/src/csharp/Grpc/Grpc.csproj @@ -0,0 +1,25 @@ + + + + + + + Copyright 2015, Google Inc. + gRPC C# + C# implementation of gRPC - an RPC library and framework. + $(GrpcCsharpVersion) + Google Inc. + net45;netstandard1.5 + Grpc + gRPC RPC Protocol HTTP/2 + https://github.com/grpc/grpc + https://github.com/grpc/grpc/blob/master/LICENSE + + false + true + + + + + + From aaaa32ef7d482f9cf2fc29f32169f510551ac008 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 7 Feb 2019 16:36:18 +0100 Subject: [PATCH 179/218] change Grpc.Core.NativeDebug metapackage into csproj --- src/csharp/Grpc.Core.NativeDebug.nuspec | 25 ------------ src/csharp/Grpc.Core.NativeDebug/.gitignore | 2 + .../Grpc.Core.NativeDebug.csproj | 40 +++++++++++++++++++ 3 files changed, 42 insertions(+), 25 deletions(-) delete mode 100644 src/csharp/Grpc.Core.NativeDebug.nuspec create mode 100644 src/csharp/Grpc.Core.NativeDebug/.gitignore create mode 100644 src/csharp/Grpc.Core.NativeDebug/Grpc.Core.NativeDebug.csproj diff --git a/src/csharp/Grpc.Core.NativeDebug.nuspec b/src/csharp/Grpc.Core.NativeDebug.nuspec deleted file mode 100644 index d4bb8ad2237..00000000000 --- a/src/csharp/Grpc.Core.NativeDebug.nuspec +++ /dev/null @@ -1,25 +0,0 @@ - - - - Grpc.Core.NativeDebug - Grpc.Core: Native Debug Symbols - Debug symbols for the native library contained in Grpc.Core - Currently contains grpc_csharp_ext.pdb - $version$ - Google Inc. - grpc-packages - https://github.com/grpc/grpc/blob/master/LICENSE - https://github.com/grpc/grpc - false - Release $version$ - Copyright 2015, Google Inc. - gRPC RPC Protocol HTTP/2 - - - - - - - - - diff --git a/src/csharp/Grpc.Core.NativeDebug/.gitignore b/src/csharp/Grpc.Core.NativeDebug/.gitignore new file mode 100644 index 00000000000..1746e3269ed --- /dev/null +++ b/src/csharp/Grpc.Core.NativeDebug/.gitignore @@ -0,0 +1,2 @@ +bin +obj diff --git a/src/csharp/Grpc.Core.NativeDebug/Grpc.Core.NativeDebug.csproj b/src/csharp/Grpc.Core.NativeDebug/Grpc.Core.NativeDebug.csproj new file mode 100644 index 00000000000..5f1cac05425 --- /dev/null +++ b/src/csharp/Grpc.Core.NativeDebug/Grpc.Core.NativeDebug.csproj @@ -0,0 +1,40 @@ + + + + + + + Copyright 2015, Google Inc. + Grpc.Core: Native Debug Symbols + Debug symbols for the native library contained in Grpc.Core + $(GrpcCsharpVersion) + Google Inc. + net45;netstandard1.5 + Grpc.Core.NativeDebug + gRPC RPC Protocol HTTP/2 + https://github.com/grpc/grpc + https://github.com/grpc/grpc/blob/master/LICENSE + + false + true + + + + + runtimes/win/native/grpc_csharp_ext.x86.dll + true + + + runtimes/win/native/grpc_csharp_ext.x86.pdb + true + + + runtimes/win/native/grpc_csharp_ext.x64.dll + true + + + runtimes/win/native/grpc_csharp_ext.x64.pdb + true + + + From 9197a6ea25ef2db778c6b72f33ae6ca5133ea142 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 7 Feb 2019 16:42:13 +0100 Subject: [PATCH 180/218] simplify c# build_packages scripts, get rid of a template --- src/csharp/build_packages_dotnetcli.bat | 11 +--- .../build_packages_dotnetcli.bat.template | 61 ------------------- 2 files changed, 3 insertions(+), 69 deletions(-) delete mode 100755 templates/src/csharp/build_packages_dotnetcli.bat.template diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index 9fdfbcbd315..a482d3a5305 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -12,11 +12,6 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. -@rem Current package versions -set VERSION=1.19.0-dev - -@rem Adjust the location of nuget.exe -set NUGET=C:\nuget\nuget.exe set DOTNET=dotnet mkdir ..\..\artifacts @@ -41,9 +36,9 @@ xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\bu %DOTNET% pack --configuration Release Grpc.HealthCheck --output ..\..\..\artifacts || goto :error %DOTNET% pack --configuration Release Grpc.Reflection --output ..\..\..\artifacts || goto :error %DOTNET% pack --configuration Release Grpc.Tools --output ..\..\..\artifacts || goto :error - -%NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error -%NUGET% pack Grpc.Core.NativeDebug.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts +@rem build auxiliary packages +%DOTNET% pack --configuration Release Grpc --output ..\..\..\artifacts || goto :error +%DOTNET% pack --configuration Release Grpc.Core.NativeDebug --output ..\..\..\artifacts || goto :error @rem copy resulting nuget packages to artifacts directory xcopy /Y /I *.nupkg ..\..\artifacts\ || goto :error diff --git a/templates/src/csharp/build_packages_dotnetcli.bat.template b/templates/src/csharp/build_packages_dotnetcli.bat.template deleted file mode 100755 index aa35ae1e6fc..00000000000 --- a/templates/src/csharp/build_packages_dotnetcli.bat.template +++ /dev/null @@ -1,61 +0,0 @@ -%YAML 1.2 ---- | - @rem Copyright 2016 gRPC authors. - @rem - @rem Licensed under the Apache License, Version 2.0 (the "License"); - @rem you may not use this file except in compliance with the License. - @rem You may obtain a copy of the License at - @rem - @rem http://www.apache.org/licenses/LICENSE-2.0 - @rem - @rem Unless required by applicable law or agreed to in writing, software - @rem distributed under the License is distributed on an "AS IS" BASIS, - @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - @rem See the License for the specific language governing permissions and - @rem limitations under the License. - - @rem Current package versions - set VERSION=${settings.csharp_version} - - @rem Adjust the location of nuget.exe - set NUGET=C:\nuget\nuget.exe - set DOTNET=dotnet - - mkdir ..\..\artifacts - - @rem Collect the artifacts built by the previous build step - mkdir nativelibs - powershell -Command "cp -r ..\..\input_artifacts\csharp_ext_* nativelibs" - - @rem Collect protoc artifacts built by the previous build step - mkdir protoc_plugins - powershell -Command "cp -r ..\..\input_artifacts\protoc_* protoc_plugins" - - %%DOTNET% restore Grpc.sln || goto :error - - @rem To be able to build, we also need to put grpc_csharp_ext to its normal location - xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release${"\\"} - - %%DOTNET% pack --configuration Release Grpc.Core.Api --output ..\..\..\artifacts || goto :error - %%DOTNET% pack --configuration Release Grpc.Core --output ..\..\..\artifacts || goto :error - %%DOTNET% pack --configuration Release Grpc.Core.Testing --output ..\..\..\artifacts || goto :error - %%DOTNET% pack --configuration Release Grpc.Auth --output ..\..\..\artifacts || goto :error - %%DOTNET% pack --configuration Release Grpc.HealthCheck --output ..\..\..\artifacts || goto :error - %%DOTNET% pack --configuration Release Grpc.Reflection --output ..\..\..\artifacts || goto :error - %%DOTNET% pack --configuration Release Grpc.Tools --output ..\..\..\artifacts || goto :error - - %%NUGET% pack Grpc.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts || goto :error - %%NUGET% pack Grpc.Core.NativeDebug.nuspec -Version %VERSION% -OutputDirectory ..\..\artifacts - - @rem copy resulting nuget packages to artifacts directory - xcopy /Y /I *.nupkg ..\..\artifacts\ || goto :error - - @rem create a zipfile with the artifacts as well - powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('..\..\artifacts', 'csharp_nugets_windows_dotnetcli.zip');" - xcopy /Y /I csharp_nugets_windows_dotnetcli.zip ..\..\artifacts\ || goto :error - - goto :EOF - - :error - echo Failed! - exit /b %errorlevel% From 70a05a7c531b239040c0fddee54f295eb443b266 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 7 Feb 2019 16:45:07 +0100 Subject: [PATCH 181/218] unify usage of Version vs VersionPrefix --- src/csharp/Grpc.Tools/Grpc.Tools.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/csharp/Grpc.Tools/Grpc.Tools.csproj b/src/csharp/Grpc.Tools/Grpc.Tools.csproj index 61fa75a4ec2..aa39dd0fe9b 100644 --- a/src/csharp/Grpc.Tools/Grpc.Tools.csproj +++ b/src/csharp/Grpc.Tools/Grpc.Tools.csproj @@ -4,7 +4,7 @@ Protobuf.MSBuild - $(GrpcCsharpVersion) + $(GrpcCsharpVersion) net45;netstandard1.3 From 8a9e0742373ce5cc5815a3b04662dd13f84f7e65 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 7 Feb 2019 21:43:15 +0100 Subject: [PATCH 182/218] build -dev nugets with timestamp suffix --- src/csharp/build_packages_dotnetcli.bat | 3 +++ src/csharp/expand_dev_version.sh | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/csharp/expand_dev_version.sh diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat index a482d3a5305..f500310865b 100755 --- a/src/csharp/build_packages_dotnetcli.bat +++ b/src/csharp/build_packages_dotnetcli.bat @@ -24,6 +24,9 @@ powershell -Command "cp -r ..\..\input_artifacts\csharp_ext_* nativelibs" mkdir protoc_plugins powershell -Command "cp -r ..\..\input_artifacts\protoc_* protoc_plugins" +@rem Add current timestamp to dev nugets +expand_dev_version.sh + %DOTNET% restore Grpc.sln || goto :error @rem To be able to build, we also need to put grpc_csharp_ext to its normal location diff --git a/src/csharp/expand_dev_version.sh b/src/csharp/expand_dev_version.sh new file mode 100644 index 00000000000..555f22a619c --- /dev/null +++ b/src/csharp/expand_dev_version.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Copyright 2019 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. + +# Updates the GrpcSharpVersion property so that we can build +# dev nuget packages differentiated by timestamp. + +set -e + +cd "$(dirname "$0")" + +DEV_DATETIME_SUFFIX=$(date -u "+%Y%m%d%H%M") +# expand the -dev suffix to contain current timestamp +sed -ibak "s/-dev<\/GrpcCsharpVersion>/-dev${DEV_DATETIME_SUFFIX}<\/GrpcCsharpVersion>/" Grpc.Core/Version.csproj.include From a61785f18492b4780d69322490ec710c4e3af008 Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Thu, 7 Feb 2019 12:52:04 -0800 Subject: [PATCH 183/218] Don't count internal ApplicationCallbackExcCtx against ExcCtx count This was originally done for ExcCtx in https://github.com/grpc/grpc/pull/15825. This avoids a hang in our pre-fork handler, where grpc_core::Executor::RunClosures attempts to increment the thread count from an invocation of grpc_prefork(): --- src/core/lib/iomgr/exec_ctx.h | 33 ++++++++++++++++++++++------- src/core/lib/iomgr/executor.cc | 3 ++- src/core/lib/iomgr/timer_manager.cc | 3 ++- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index 16ac14ba6c5..ef11f99dae0 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -49,6 +49,10 @@ typedef struct grpc_combiner grpc_combiner; be counted by fork handlers */ #define GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD 4 +/* This application callback exec ctx was initialized by an internal thread, and + should not be counted by fork handlers */ +#define GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD 1 + extern grpc_closure_scheduler* grpc_schedule_on_exec_ctx; gpr_timespec grpc_millis_to_timespec(grpc_millis millis, gpr_clock_type clock); @@ -229,13 +233,12 @@ class ExecCtx { class ApplicationCallbackExecCtx { public: - ApplicationCallbackExecCtx() { - if (reinterpret_cast( - gpr_tls_get(&callback_exec_ctx_)) == nullptr) { - grpc_core::Fork::IncExecCtxCount(); - gpr_tls_set(&callback_exec_ctx_, reinterpret_cast(this)); - } - } + /** Default Constructor */ + ApplicationCallbackExecCtx() { Set(this, flags_); } + + /** Parameterised Constructor */ + ApplicationCallbackExecCtx(uintptr_t fl) : flags_(fl) { Set(this, flags_); } + ~ApplicationCallbackExecCtx() { if (reinterpret_cast( gpr_tls_get(&callback_exec_ctx_)) == this) { @@ -248,12 +251,25 @@ class ApplicationCallbackExecCtx { (*f->functor_run)(f, f->internal_success); } gpr_tls_set(&callback_exec_ctx_, reinterpret_cast(nullptr)); - grpc_core::Fork::DecExecCtxCount(); + if (!(GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags_)) { + grpc_core::Fork::DecExecCtxCount(); + } } else { GPR_DEBUG_ASSERT(head_ == nullptr); GPR_DEBUG_ASSERT(tail_ == nullptr); } } + + static void Set(ApplicationCallbackExecCtx* exec_ctx, uintptr_t flags) { + if (reinterpret_cast( + gpr_tls_get(&callback_exec_ctx_)) == nullptr) { + if (!(GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD & flags)) { + grpc_core::Fork::IncExecCtxCount(); + } + gpr_tls_set(&callback_exec_ctx_, reinterpret_cast(exec_ctx)); + } + } + static void Enqueue(grpc_experimental_completion_queue_functor* functor, int is_success) { functor->internal_success = is_success; @@ -278,6 +294,7 @@ class ApplicationCallbackExecCtx { static void GlobalShutdown(void) { gpr_tls_destroy(&callback_exec_ctx_); } private: + uintptr_t flags_; grpc_experimental_completion_queue_functor* head_{nullptr}; grpc_experimental_completion_queue_functor* tail_{nullptr}; GPR_TLS_CLASS_DECL(callback_exec_ctx_); diff --git a/src/core/lib/iomgr/executor.cc b/src/core/lib/iomgr/executor.cc index 1e7c6a907a2..2ad8972fc79 100644 --- a/src/core/lib/iomgr/executor.cc +++ b/src/core/lib/iomgr/executor.cc @@ -116,7 +116,8 @@ size_t Executor::RunClosures(const char* executor_name, // application-level callbacks. No need to create a new ExecCtx, though, // since there already is one and it is flushed (but not destructed) in this // function itself. - grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx( + GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD); grpc_closure* c = list.head; while (c != nullptr) { diff --git a/src/core/lib/iomgr/timer_manager.cc b/src/core/lib/iomgr/timer_manager.cc index 1da242938a2..4469db70dd0 100644 --- a/src/core/lib/iomgr/timer_manager.cc +++ b/src/core/lib/iomgr/timer_manager.cc @@ -110,7 +110,8 @@ static void run_some_timers() { // could start seeing application-level callbacks. No need to // create a new ExecCtx, though, since there already is one and it is // flushed (but not destructed) in this function itself - grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx( + GRPC_APP_CALLBACK_EXEC_CTX_FLAG_IS_INTERNAL_THREAD); // if there's something to execute... gpr_mu_lock(&g_mu); From db1c09ad49840ae9e030c84e0fabd2e5c4ebddd8 Mon Sep 17 00:00:00 2001 From: Juanli Shen Date: Thu, 7 Feb 2019 12:51:25 -0800 Subject: [PATCH 184/218] Fix subchannel call destruction --- .../ext/filters/client_channel/subchannel.cc | 36 ++++++++++--------- .../ext/filters/client_channel/subchannel.h | 6 ++-- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 35225b0d5c3..1a07edad09c 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -116,21 +116,6 @@ void ConnectedSubchannel::Ping(grpc_closure* on_initiate, elem->filter->start_transport_op(elem, op); } -namespace { - -void SubchannelCallDestroy(void* arg, grpc_error* error) { - GPR_TIMER_SCOPE("subchannel_call_destroy", 0); - SubchannelCall* call = static_cast(arg); - grpc_closure* after_call_stack_destroy = call->after_call_stack_destroy(); - call->~SubchannelCall(); - // This should be the last step to destroy the subchannel call, because - // call->after_call_stack_destroy(), if not null, will free the call arena. - grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(call), nullptr, - after_call_stack_destroy); -} - -} // namespace - RefCountedPtr ConnectedSubchannel::CreateCall( const CallArgs& args, grpc_error** error) { const size_t allocation_size = @@ -149,7 +134,7 @@ RefCountedPtr ConnectedSubchannel::CreateCall( args.arena, /* arena */ args.call_combiner /* call_combiner */ }; - *error = grpc_call_stack_init(channel_stack_, 1, SubchannelCallDestroy, + *error = grpc_call_stack_init(channel_stack_, 1, SubchannelCall::Destroy, call.get(), &call_args); if (GPR_UNLIKELY(*error != GRPC_ERROR_NONE)) { const char* error_string = grpc_error_string(*error); @@ -226,6 +211,25 @@ void SubchannelCall::Unref(const DebugLocation& location, const char* reason) { GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason); } +void SubchannelCall::Destroy(void* arg, grpc_error* error) { + GPR_TIMER_SCOPE("subchannel_call_destroy", 0); + SubchannelCall* self = static_cast(arg); + // Keep some members before destroying the subchannel call. + grpc_closure* after_call_stack_destroy = self->after_call_stack_destroy_; + RefCountedPtr connected_subchannel = + std::move(self->connected_subchannel_); + // Destroy the subchannel call. + self->~SubchannelCall(); + // Destroy the call stack. This should be after destroying the subchannel + // call, because call->after_call_stack_destroy(), if not null, will free the + // call arena. + grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(self), nullptr, + after_call_stack_destroy); + // Automatically reset connected_subchannel. This should be after destroying + // the call stack, because destroying call stack needs access to the channel + // stack. +} + void SubchannelCall::MaybeInterceptRecvTrailingMetadata( grpc_transport_stream_op_batch* batch) { // only intercept payloads with recv trailing. diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 47c21ff8680..bb8e45bf965 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -131,10 +131,6 @@ class SubchannelCall { // Returns the call stack of the subchannel call. grpc_call_stack* GetCallStack(); - grpc_closure* after_call_stack_destroy() const { - return after_call_stack_destroy_; - } - // Sets the 'then_schedule_closure' argument for call stack destruction. // Must be called once per call. void SetAfterCallStackDestroy(grpc_closure* closure); @@ -148,6 +144,8 @@ class SubchannelCall { void Unref(); void Unref(const DebugLocation& location, const char* reason); + static void Destroy(void* arg, grpc_error* error); + private: // Allow RefCountedPtr<> to access IncrementRefCount(). template From 56a93d4c18eb63128cba815e11976cd59f7fa452 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 7 Feb 2019 14:41:20 -0800 Subject: [PATCH 185/218] Add no enum sanitizer annotations around functions that need to fill/load in grpc_status_code --- src/core/lib/surface/call.cc | 6 +++--- src/core/lib/transport/error_utils.cc | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index d53eb704420..3efe81f51eb 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -1494,9 +1494,9 @@ static void free_no_op_completion(void* p, grpc_cq_completion* completion) { gpr_free(completion); } -static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, - size_t nops, void* notify_tag, - int is_notify_tag_closure) { +__attribute__((no_sanitize("enum"))) static grpc_call_error call_start_batch( + grpc_call* call, const grpc_op* ops, size_t nops, void* notify_tag, + int is_notify_tag_closure) { GPR_TIMER_SCOPE("call_start_batch", 0); size_t i; diff --git a/src/core/lib/transport/error_utils.cc b/src/core/lib/transport/error_utils.cc index 558f1d494cd..3294b2accdd 100644 --- a/src/core/lib/transport/error_utils.cc +++ b/src/core/lib/transport/error_utils.cc @@ -44,10 +44,10 @@ static grpc_error* recursively_find_error_with_field(grpc_error* error, return nullptr; } -void grpc_error_get_status(grpc_error* error, grpc_millis deadline, - grpc_status_code* code, grpc_slice* slice, - grpc_http2_error_code* http_error, - const char** error_string) { +__attribute__((no_sanitize("enum"))) void grpc_error_get_status( + grpc_error* error, grpc_millis deadline, grpc_status_code* code, + grpc_slice* slice, grpc_http2_error_code* http_error, + const char** error_string) { // Start with the parent error and recurse through the tree of children // until we find the first one that has a status code. grpc_error* found_error = From ff72f3eeff2839b5727f562e6ad273a27a3a22d4 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 7 Feb 2019 14:57:58 -0800 Subject: [PATCH 186/218] Skip the test instead --- src/core/lib/surface/call.cc | 6 +++--- src/core/lib/transport/error_utils.cc | 8 ++++---- test/core/util/ubsan_suppressions.txt | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index 3efe81f51eb..d53eb704420 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -1494,9 +1494,9 @@ static void free_no_op_completion(void* p, grpc_cq_completion* completion) { gpr_free(completion); } -__attribute__((no_sanitize("enum"))) static grpc_call_error call_start_batch( - grpc_call* call, const grpc_op* ops, size_t nops, void* notify_tag, - int is_notify_tag_closure) { +static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, + size_t nops, void* notify_tag, + int is_notify_tag_closure) { GPR_TIMER_SCOPE("call_start_batch", 0); size_t i; diff --git a/src/core/lib/transport/error_utils.cc b/src/core/lib/transport/error_utils.cc index 3294b2accdd..558f1d494cd 100644 --- a/src/core/lib/transport/error_utils.cc +++ b/src/core/lib/transport/error_utils.cc @@ -44,10 +44,10 @@ static grpc_error* recursively_find_error_with_field(grpc_error* error, return nullptr; } -__attribute__((no_sanitize("enum"))) void grpc_error_get_status( - grpc_error* error, grpc_millis deadline, grpc_status_code* code, - grpc_slice* slice, grpc_http2_error_code* http_error, - const char** error_string) { +void grpc_error_get_status(grpc_error* error, grpc_millis deadline, + grpc_status_code* code, grpc_slice* slice, + grpc_http2_error_code* http_error, + const char** error_string) { // Start with the parent error and recurse through the tree of children // until we find the first one that has a status code. grpc_error* found_error = diff --git a/test/core/util/ubsan_suppressions.txt b/test/core/util/ubsan_suppressions.txt index 8e17d37ec7e..06533d9eb62 100644 --- a/test/core/util/ubsan_suppressions.txt +++ b/test/core/util/ubsan_suppressions.txt @@ -21,3 +21,4 @@ enum:grpc_op_string signed-integer-overflow:chrono enum:grpc_http2_error_to_grpc_status enum:grpc_chttp2_cancel_stream +enum:api_fuzzer From 89ee1a8b102f7058b35afbabf6d8ffe9bac4a25c Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 7 Feb 2019 19:13:45 -0800 Subject: [PATCH 187/218] Improved interception docs --- include/grpcpp/impl/codegen/interceptor.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/grpcpp/impl/codegen/interceptor.h b/include/grpcpp/impl/codegen/interceptor.h index 03520867f9c..3af783a61b6 100644 --- a/include/grpcpp/impl/codegen/interceptor.h +++ b/include/grpcpp/impl/codegen/interceptor.h @@ -45,6 +45,10 @@ namespace experimental { /// PRE_RECV means an interception between the time that a certain /// 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. +/// A batch of interception points will only contain either PRE or POST hooks +/// but not both types. For example, a batch with PRE_SEND hook points will not +/// contain POST_RECV or POST_SEND ops. Likewise, a batch with POST_* ops can +/// not contain PRE_* ops. enum class InterceptionHookPoints { /// The first three in this list are for clients and servers PRE_SEND_INITIAL_METADATA, @@ -52,8 +56,8 @@ enum class InterceptionHookPoints { POST_SEND_MESSAGE, PRE_SEND_STATUS, // server only PRE_SEND_CLOSE, // client only: WritesDone for stream; after write in unary - /// The following three are for hijacked clients only and can only be - /// registered by the global interceptor + /// The following three are for hijacked clients only. A batch with PRE_RECV_* + /// hook points will never contain hook points of other types. PRE_RECV_INITIAL_METADATA, PRE_RECV_MESSAGE, PRE_RECV_STATUS, From f815656256139f8772cc0223da5029be3868d8c0 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Fri, 8 Feb 2019 00:12:29 -0800 Subject: [PATCH 188/218] Instantiate an application callback exec ctx in security filter --- src/core/lib/security/transport/server_auth_filter.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/lib/security/transport/server_auth_filter.cc b/src/core/lib/security/transport/server_auth_filter.cc index f93eb4275e3..81b9c2ce074 100644 --- a/src/core/lib/security/transport/server_auth_filter.cc +++ b/src/core/lib/security/transport/server_auth_filter.cc @@ -169,6 +169,7 @@ static void on_md_processing_done( grpc_status_code status, const char* error_details) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; // If the call was not cancelled while we were in flight, process the result. if (gpr_atm_full_cas(&calld->state, static_cast(STATE_INIT), From cd22177e04424ee36d5c22dc8e55cd3480dfcb64 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 8 Feb 2019 10:05:19 -0800 Subject: [PATCH 189/218] Add manual test suite --- src/objective-c/manual_tests/AppDelegate.h | 25 ++ src/objective-c/manual_tests/AppDelegate.m | 23 ++ .../GrpcIosTest.xcodeproj/project.pbxproj | 380 ++++++++++++++++++ src/objective-c/manual_tests/Info.plist | 43 ++ src/objective-c/manual_tests/Main.storyboard | 61 +++ src/objective-c/manual_tests/Podfile | 100 +++++ src/objective-c/manual_tests/ViewController.m | 117 ++++++ src/objective-c/manual_tests/main.m | 26 ++ 8 files changed, 775 insertions(+) create mode 100644 src/objective-c/manual_tests/AppDelegate.h create mode 100644 src/objective-c/manual_tests/AppDelegate.m create mode 100644 src/objective-c/manual_tests/GrpcIosTest.xcodeproj/project.pbxproj create mode 100644 src/objective-c/manual_tests/Info.plist create mode 100644 src/objective-c/manual_tests/Main.storyboard create mode 100644 src/objective-c/manual_tests/Podfile create mode 100644 src/objective-c/manual_tests/ViewController.m create mode 100644 src/objective-c/manual_tests/main.m diff --git a/src/objective-c/manual_tests/AppDelegate.h b/src/objective-c/manual_tests/AppDelegate.h new file mode 100644 index 00000000000..b4b675059a4 --- /dev/null +++ b/src/objective-c/manual_tests/AppDelegate.h @@ -0,0 +1,25 @@ +/* + * + * Copyright 2019 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 AppDelegate : UIResponder + +@property(strong, nonatomic) UIWindow *window; + +@end diff --git a/src/objective-c/manual_tests/AppDelegate.m b/src/objective-c/manual_tests/AppDelegate.m new file mode 100644 index 00000000000..659f7528d22 --- /dev/null +++ b/src/objective-c/manual_tests/AppDelegate.m @@ -0,0 +1,23 @@ +/* + * + * Copyright 2019 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 "AppDelegate.h" + +@implementation AppDelegate + +@end diff --git a/src/objective-c/manual_tests/GrpcIosTest.xcodeproj/project.pbxproj b/src/objective-c/manual_tests/GrpcIosTest.xcodeproj/project.pbxproj new file mode 100644 index 00000000000..00004e06cad --- /dev/null +++ b/src/objective-c/manual_tests/GrpcIosTest.xcodeproj/project.pbxproj @@ -0,0 +1,380 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 4E1314BB1DA3DC6ECCEB96AB /* libPods-GrpcIosTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D22EC48A487B02F76135EA3 /* libPods-GrpcIosTest.a */; }; + 5EDA909B220DF1B00046D27A /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EDA9094220DF1B00046D27A /* ViewController.m */; }; + 5EDA909C220DF1B00046D27A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EDA9096220DF1B00046D27A /* main.m */; }; + 5EDA909E220DF1B00046D27A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5EDA9098220DF1B00046D27A /* Main.storyboard */; }; + 5EDA909F220DF1B00046D27A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EDA9099220DF1B00046D27A /* AppDelegate.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1D22EC48A487B02F76135EA3 /* libPods-GrpcIosTest.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-GrpcIosTest.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 5EDA907B220DF0BC0046D27A /* GrpcIosTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GrpcIosTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 5EDA9094220DF1B00046D27A /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = SOURCE_ROOT; }; + 5EDA9095220DF1B00046D27A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = SOURCE_ROOT; }; + 5EDA9096220DF1B00046D27A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = SOURCE_ROOT; }; + 5EDA9098220DF1B00046D27A /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = SOURCE_ROOT; }; + 5EDA9099220DF1B00046D27A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = SOURCE_ROOT; }; + 7C9FAFB11727DCA50888C1B8 /* Pods-GrpcIosTest.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GrpcIosTest.debug.xcconfig"; path = "Pods/Target Support Files/Pods-GrpcIosTest/Pods-GrpcIosTest.debug.xcconfig"; sourceTree = ""; }; + A4E7CA72304A7B43FE8A5BC7 /* Pods-GrpcIosTest.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GrpcIosTest.release.xcconfig"; path = "Pods/Target Support Files/Pods-GrpcIosTest/Pods-GrpcIosTest.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5EDA9078220DF0BC0046D27A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4E1314BB1DA3DC6ECCEB96AB /* libPods-GrpcIosTest.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2B8131AC634883AFEC02557C /* Pods */ = { + isa = PBXGroup; + children = ( + 7C9FAFB11727DCA50888C1B8 /* Pods-GrpcIosTest.debug.xcconfig */, + A4E7CA72304A7B43FE8A5BC7 /* Pods-GrpcIosTest.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 5EDA9072220DF0BC0046D27A = { + isa = PBXGroup; + children = ( + 5EDA9095220DF1B00046D27A /* AppDelegate.h */, + 5EDA9099220DF1B00046D27A /* AppDelegate.m */, + 5EDA9096220DF1B00046D27A /* main.m */, + 5EDA9098220DF1B00046D27A /* Main.storyboard */, + 5EDA9094220DF1B00046D27A /* ViewController.m */, + 5EDA907C220DF0BC0046D27A /* Products */, + 2B8131AC634883AFEC02557C /* Pods */, + E73D92116C1C328622A8C77F /* Frameworks */, + ); + sourceTree = ""; + }; + 5EDA907C220DF0BC0046D27A /* Products */ = { + isa = PBXGroup; + children = ( + 5EDA907B220DF0BC0046D27A /* GrpcIosTest.app */, + ); + name = Products; + sourceTree = ""; + }; + E73D92116C1C328622A8C77F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1D22EC48A487B02F76135EA3 /* libPods-GrpcIosTest.a */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 5EDA907A220DF0BC0046D27A /* GrpcIosTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5EDA9091220DF0BD0046D27A /* Build configuration list for PBXNativeTarget "GrpcIosTest" */; + buildPhases = ( + 33B0CC39F9DDEC2CEFB413C5 /* [CP] Check Pods Manifest.lock */, + 5EDA9077220DF0BC0046D27A /* Sources */, + 5EDA9078220DF0BC0046D27A /* Frameworks */, + 5EDA9079220DF0BC0046D27A /* Resources */, + 3EA5D3D73BDF48C306548037 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = GrpcIosTest; + productName = GrpcIosTest; + productReference = 5EDA907B220DF0BC0046D27A /* GrpcIosTest.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 5EDA9073220DF0BC0046D27A /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1000; + ORGANIZATIONNAME = gRPC; + TargetAttributes = { + 5EDA907A220DF0BC0046D27A = { + CreatedOnToolsVersion = 10.0; + }; + }; + }; + buildConfigurationList = 5EDA9076220DF0BC0046D27A /* Build configuration list for PBXProject "GrpcIosTest" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 5EDA9072220DF0BC0046D27A; + productRefGroup = 5EDA907C220DF0BC0046D27A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 5EDA907A220DF0BC0046D27A /* GrpcIosTest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 5EDA9079220DF0BC0046D27A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5EDA909E220DF1B00046D27A /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 33B0CC39F9DDEC2CEFB413C5 /* [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-GrpcIosTest-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; + }; + 3EA5D3D73BDF48C306548037 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-GrpcIosTest/Pods-GrpcIosTest-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-GrpcIosTest/Pods-GrpcIosTest-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5EDA9077220DF0BC0046D27A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5EDA909C220DF1B00046D27A /* main.m in Sources */, + 5EDA909B220DF1B00046D27A /* ViewController.m in Sources */, + 5EDA909F220DF1B00046D27A /* AppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 5EDA908F220DF0BD0046D27A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 5EDA9090220DF0BD0046D27A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5EDA9092220DF0BD0046D27A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7C9FAFB11727DCA50888C1B8 /* Pods-GrpcIosTest.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.GrpcIosTest; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 5EDA9093220DF0BD0046D27A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A4E7CA72304A7B43FE8A5BC7 /* Pods-GrpcIosTest.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.GrpcIosTest; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 5EDA9076220DF0BC0046D27A /* Build configuration list for PBXProject "GrpcIosTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5EDA908F220DF0BD0046D27A /* Debug */, + 5EDA9090220DF0BD0046D27A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5EDA9091220DF0BD0046D27A /* Build configuration list for PBXNativeTarget "GrpcIosTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5EDA9092220DF0BD0046D27A /* Debug */, + 5EDA9093220DF0BD0046D27A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 5EDA9073220DF0BC0046D27A /* Project object */; +} diff --git a/src/objective-c/manual_tests/Info.plist b/src/objective-c/manual_tests/Info.plist new file mode 100644 index 00000000000..8824c40c504 --- /dev/null +++ b/src/objective-c/manual_tests/Info.plist @@ -0,0 +1,43 @@ + + + + + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/src/objective-c/manual_tests/Main.storyboard b/src/objective-c/manual_tests/Main.storyboard new file mode 100644 index 00000000000..e88f30e324b --- /dev/null +++ b/src/objective-c/manual_tests/Main.storyboard @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/objective-c/manual_tests/Podfile b/src/objective-c/manual_tests/Podfile new file mode 100644 index 00000000000..7cb650a3412 --- /dev/null +++ b/src/objective-c/manual_tests/Podfile @@ -0,0 +1,100 @@ +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '8.0' + +install! 'cocoapods', :deterministic_uuids => false + +# Location of gRPC's repo root relative to this file. +GRPC_LOCAL_SRC = '../../..' + +# Install the dependencies in the main target plus all test targets. +%w( +GrpcIosTest +).each do |target_name| + target target_name do + pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true + + pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" + pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" + + pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true + + pod 'gRPC', :path => GRPC_LOCAL_SRC + pod 'gRPC-Core', :path => GRPC_LOCAL_SRC + pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC + pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC, :inhibit_warnings => true + pod 'RemoteTest', :path => "../tests/RemoteTestClient", :inhibit_warnings => true + end +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. +# +# This podspec searches for the gRPC core library headers under "$(PODS_ROOT)/gRPC-Core", where +# Cocoapods normally places the downloaded sources. When doing local development of the libraries, +# though, Cocoapods just takes the sources from whatever directory was specified using `:path`, and +# doesn't copy them under $(PODS_ROOT). When using static libraries, one can sometimes rely on the +# symbolic links to the pods headers that Cocoapods creates under "$(PODS_ROOT)/Headers". But those +# aren't created when using dynamic frameworks. So our solution is to modify the podspec on the fly +# to point at the local directory where the sources are. +# +# TODO(jcanizales): Send a PR to Cocoapods to get rid of this need. +pre_install do |installer| + # This is the gRPC-Core podspec object, as initialized by its podspec file. + grpc_core_spec = installer.pod_targets.find{|t| t.name.start_with?('gRPC-Core')}.root_spec + + # Copied from gRPC-Core.podspec, except for the adjusted src_root: + src_root = "$(PODS_ROOT)/../#{GRPC_LOCAL_SRC}" + grpc_core_spec.pod_target_xcconfig = { + 'GRPC_SRC_ROOT' => src_root, + 'HEADER_SEARCH_PATHS' => '"$(inherited)" "$(GRPC_SRC_ROOT)/include"', + 'USER_HEADER_SEARCH_PATHS' => '"$(GRPC_SRC_ROOT)"', + # If we don't set these two settings, `include/grpc/support/time.h` and + # `src/core/lib/gpr/string.h` shadow the system `` and ``, breaking the + # build. + 'USE_HEADERMAP' => 'NO', + 'ALWAYS_SEARCH_USER_PATHS' => 'NO', + } +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'YES' + end + + # CocoaPods creates duplicated library targets of gRPC-Core when the test targets include + # non-default subspecs of gRPC-Core. All of these library targets start with prefix 'gRPC-Core' + # and require the same error suppresion. + if target.name.start_with?('gRPC-Core') + target.build_configurations.each do |config| + # TODO(zyc): Remove this setting after the issue is resolved + # GPR_UNREACHABLE_CODE causes "Control may reach end of non-void + # function" warning + config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO' + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CRONET_WITH_PACKET_COALESCING=1' + end + end + + # Activate Cronet for the dedicated build configuration 'Cronet', which will be used solely by + # the test target 'InteropTestsRemoteWithCronet' + # Activate GRPCCall+InternalTests functions for the dedicated build configuration 'Test', which will + # be used by all test targets using it. + if target.name == 'gRPC' || target.name.start_with?('gRPC.') + target.build_configurations.each do |config| + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_TEST_OBJC=1' + end + end + + # Enable NSAssert on gRPC + 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' + end + end + end + end +end diff --git a/src/objective-c/manual_tests/ViewController.m b/src/objective-c/manual_tests/ViewController.m new file mode 100644 index 00000000000..c87e50285cf --- /dev/null +++ b/src/objective-c/manual_tests/ViewController.m @@ -0,0 +1,117 @@ +/* + * + * Copyright 2019 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 + +NSString *const kRemoteHost = @"grpc-test.sandbox.googleapis.com"; +const int32_t kMessageSize = 100; + +@interface ViewController : UIViewController + +@end + +@implementation ViewController { + RMTTestService *_service; + dispatch_queue_t _dispatchQueue; + GRPCStreamingProtoCall *_call; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); +} + +- (IBAction)tapUnaryCall:(id)sender { + if (_service == nil) { + _service = [RMTTestService serviceWithHost:kRemoteHost]; + } + + // Set up request proto message + RMTSimpleRequest *request = [RMTSimpleRequest message]; + request.responseType = RMTPayloadType_Compressable; + request.responseSize = kMessageSize; + request.payload.body = [NSMutableData dataWithLength:kMessageSize]; + + GRPCUnaryProtoCall *call = [_service unaryCallWithMessage:request + responseHandler:self + callOptions:nil]; + [call start]; +} + +- (IBAction)tapStreamingCallStart:(id)sender { + if (_service == nil) { + _service = [RMTTestService serviceWithHost:kRemoteHost]; + } + + // Set up request proto message + RMTStreamingOutputCallRequest *request = RMTStreamingOutputCallRequest.message; + RMTResponseParameters *parameters = [RMTResponseParameters message]; + parameters.size = kMessageSize; + [request.responseParametersArray addObject:parameters]; + request.payload.body = [NSMutableData dataWithLength:kMessageSize]; + + GRPCStreamingProtoCall *call = [_service fullDuplexCallWithResponseHandler:self callOptions:nil]; + [call start]; + _call = call; + // display something to confirm the tester the call is started + NSLog(@"Started streaming call"); +} + +- (IBAction)tapStreamingCallSend:(id)sender { + if (_call == nil) return; + + RMTStreamingOutputCallRequest *request = RMTStreamingOutputCallRequest.message; + RMTResponseParameters *parameters = [RMTResponseParameters message]; + parameters.size = kMessageSize; + [request.responseParametersArray addObject:parameters]; + request.payload.body = [NSMutableData dataWithLength:kMessageSize]; + + [_call writeMessage:request]; +} + +- (IBAction)tapStreamingCallStop:(id)sender { + if (_call == nil) return; + + [_call finish]; + + _call = nil; +} + +- (void)didReceiveInitialMetadata:(NSDictionary *)initialMetadata { + NSLog(@"Recv initial metadata: %@", initialMetadata); +} + +- (void)didReceiveProtoMessage:(GPBMessage *)message { + NSLog(@"Recv message: %@", message); +} + +- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata + error:(nullable NSError *)error { + NSLog(@"Recv trailing metadata: %@, error: %@", trailingMetadata, error); +} + +- (dispatch_queue_t)dispatchQueue { + return _dispatchQueue; +} + +@end diff --git a/src/objective-c/manual_tests/main.m b/src/objective-c/manual_tests/main.m new file mode 100644 index 00000000000..2797c6f17f2 --- /dev/null +++ b/src/objective-c/manual_tests/main.m @@ -0,0 +1,26 @@ +/* + * + * Copyright 2019 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 "AppDelegate.h" + +int main(int argc, char* argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} From ae88ee803ddf2bba46c6b32c70c80279550b38cf Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 8 Feb 2019 10:45:07 -0800 Subject: [PATCH 190/218] clang-format --- src/objective-c/manual_tests/AppDelegate.h | 4 ++-- src/objective-c/manual_tests/ViewController.m | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/objective-c/manual_tests/AppDelegate.h b/src/objective-c/manual_tests/AppDelegate.h index b4b675059a4..183abcf4ec8 100644 --- a/src/objective-c/manual_tests/AppDelegate.h +++ b/src/objective-c/manual_tests/AppDelegate.h @@ -18,8 +18,8 @@ #import -@interface AppDelegate : UIResponder +@interface AppDelegate : UIResponder -@property(strong, nonatomic) UIWindow *window; +@property(strong, nonatomic) UIWindow* window; @end diff --git a/src/objective-c/manual_tests/ViewController.m b/src/objective-c/manual_tests/ViewController.m index c87e50285cf..00bb516bdfc 100644 --- a/src/objective-c/manual_tests/ViewController.m +++ b/src/objective-c/manual_tests/ViewController.m @@ -18,15 +18,15 @@ #import -#import -#import #import #import +#import +#import NSString *const kRemoteHost = @"grpc-test.sandbox.googleapis.com"; const int32_t kMessageSize = 100; -@interface ViewController : UIViewController +@interface ViewController : UIViewController @end @@ -52,9 +52,8 @@ const int32_t kMessageSize = 100; request.responseSize = kMessageSize; request.payload.body = [NSMutableData dataWithLength:kMessageSize]; - GRPCUnaryProtoCall *call = [_service unaryCallWithMessage:request - responseHandler:self - callOptions:nil]; + GRPCUnaryProtoCall *call = + [_service unaryCallWithMessage:request responseHandler:self callOptions:nil]; [call start]; } From 07945070430dc817602b08f8aa00a0fd6597dd8f Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 8 Feb 2019 13:07:27 -0800 Subject: [PATCH 191/218] Don't pass service config from parent channel to grpclb balancer channel. --- .../client_channel/lb_policy/grpclb/grpclb.cc | 5 +- test/cpp/end2end/grpclb_end2end_test.cc | 52 +++++++++++++++---- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index 750b312fae9..63e381d64c7 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -917,6 +917,9 @@ grpc_channel_args* BuildBalancerChannelArgs( // LB policy name, since we want to use the default (pick_first) in // the LB channel. GRPC_ARG_LB_POLICY_NAME, + // Strip out the service config, since we don't want the LB policy + // config specified for the parent channel to affect the LB channel. + GRPC_ARG_SERVICE_CONFIG, // The channel arg for the server URI, since that will be different for // the LB channel than for the parent channel. The client channel // factory will re-add this arg with the right value. @@ -928,7 +931,7 @@ grpc_channel_args* BuildBalancerChannelArgs( // resolver will have is_balancer=false, whereas our own addresses have // is_balancer=true. We need the LB channel to return addresses with // is_balancer=false so that it does not wind up recursively using the - // grpclb LB policy, as per the special case logic in client_channel.c. + // grpclb LB policy. GRPC_ARG_SERVER_ADDRESS_LIST, // The fake resolver response generator, because we are replacing it // with the one from the grpclb policy, used to propagate updates to diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc index b589cd4044a..b56e65e50af 100644 --- a/test/cpp/end2end/grpclb_end2end_test.cc +++ b/test/cpp/end2end/grpclb_end2end_test.cc @@ -404,14 +404,6 @@ class GrpclbEnd2endTest : public ::testing::Test { } } - void SetNextResolutionAllBalancers() { - std::vector addresses; - for (size_t i = 0; i < balancer_servers_.size(); ++i) { - addresses.emplace_back(AddressData{balancer_servers_[i].port_, true, ""}); - } - SetNextResolution(addresses); - } - void ResetStub(int fallback_timeout = 0, const grpc::string& expected_targets = "") { ChannelArguments args; @@ -533,12 +525,29 @@ class GrpclbEnd2endTest : public ::testing::Test { return addresses; } - void SetNextResolution(const std::vector& address_data) { + void SetNextResolutionAllBalancers( + const char* service_config_json = nullptr) { + std::vector addresses; + for (size_t i = 0; i < balancer_servers_.size(); ++i) { + addresses.emplace_back(AddressData{balancer_servers_[i].port_, true, ""}); + } + SetNextResolution(addresses, service_config_json); + } + + void SetNextResolution(const std::vector& address_data, + const char* service_config_json = nullptr) { grpc_core::ExecCtx exec_ctx; grpc_core::ServerAddressList addresses = CreateLbAddressesFromAddressDataList(address_data); - grpc_arg fake_addresses = CreateServerAddressListChannelArg(&addresses); - grpc_channel_args fake_result = {1, &fake_addresses}; + std::vector args = { + CreateServerAddressListChannelArg(&addresses), + }; + if (service_config_json != nullptr) { + args.push_back(grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast(service_config_json))); + } + grpc_channel_args fake_result = {args.size(), args.data()}; response_generator_->SetResponse(&fake_result); } @@ -693,6 +702,27 @@ TEST_F(SingleBalancerTest, Vanilla) { EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); } +TEST_F(SingleBalancerTest, SelectGrpclbWithMigrationServiceConfig) { + SetNextResolutionAllBalancers( + "{\n" + " \"loadBalancingConfig\":[\n" + " { \"does_not_exist\":{} },\n" + " { \"grpclb\":{} }\n" + " ]\n" + "}"); + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), + 0); + CheckRpcSendOk(1, 1000 /* timeout_ms */, true /* wait_for_ready */); + balancers_[0]->NotifyDoneWithServerlists(); + // The balancer got a single request. + EXPECT_EQ(1U, balancer_servers_[0].service_->request_count()); + // and sent a single response. + EXPECT_EQ(1U, balancer_servers_[0].service_->response_count()); + // Check LB policy name for the channel. + EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); +} + TEST_F(SingleBalancerTest, SameBackendListedMultipleTimes) { SetNextResolutionAllBalancers(); // Same backend listed twice. From 67c010b44fdf91e81ef529bd68c3b0cd242a5c5d Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Fri, 8 Feb 2019 14:21:34 -0800 Subject: [PATCH 192/218] Add default initialization value --- src/core/lib/iomgr/exec_ctx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index ef11f99dae0..246c6f659b3 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -294,7 +294,7 @@ class ApplicationCallbackExecCtx { static void GlobalShutdown(void) { gpr_tls_destroy(&callback_exec_ctx_); } private: - uintptr_t flags_; + uintptr_t flags_{0u}; grpc_experimental_completion_queue_functor* head_{nullptr}; grpc_experimental_completion_queue_functor* tail_{nullptr}; GPR_TLS_CLASS_DECL(callback_exec_ctx_); From 85d76b2888ddd19a743191d6676d4be17df6a584 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Fri, 8 Feb 2019 16:56:42 -0800 Subject: [PATCH 193/218] Add ApplicationCallbackExecCtx in other spots that may trigger application work --- .../ext/filters/client_channel/channel_connectivity.cc | 2 ++ .../ext/transport/cronet/transport/cronet_transport.cc | 8 ++++++++ src/core/lib/iomgr/cfstream_handle.cc | 2 ++ src/core/lib/security/credentials/jwt/jwt_credentials.cc | 1 + src/core/lib/security/credentials/jwt/jwt_verifier.cc | 1 + .../lib/security/credentials/plugin/plugin_credentials.cc | 1 + 6 files changed, 15 insertions(+) diff --git a/src/core/ext/filters/client_channel/channel_connectivity.cc b/src/core/ext/filters/client_channel/channel_connectivity.cc index c71d10274a8..9f970f6affa 100644 --- a/src/core/ext/filters/client_channel/channel_connectivity.cc +++ b/src/core/ext/filters/client_channel/channel_connectivity.cc @@ -35,6 +35,7 @@ grpc_connectivity_state grpc_channel_check_connectivity_state( /* forward through to the underlying client channel */ grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; grpc_connectivity_state state; GRPC_API_TRACE( @@ -202,6 +203,7 @@ void grpc_channel_watch_connectivity_state( gpr_timespec deadline, grpc_completion_queue* cq, void* tag) { grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; state_watcher* w = static_cast(gpr_malloc(sizeof(*w))); diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc index ade88da4cb9..9551b4ba496 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.cc +++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc @@ -441,6 +441,7 @@ static void convert_cronet_array_to_metadata( */ static void on_failed(bidirectional_stream* stream, int net_error) { gpr_log(GPR_ERROR, "on_failed(%p, %d)", stream, net_error); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; stream_obj* s = static_cast(stream->annotation); @@ -467,6 +468,7 @@ static void on_failed(bidirectional_stream* stream, int net_error) { */ static void on_canceled(bidirectional_stream* stream) { CRONET_LOG(GPR_DEBUG, "on_canceled(%p)", stream); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; stream_obj* s = static_cast(stream->annotation); @@ -493,6 +495,7 @@ static void on_canceled(bidirectional_stream* stream) { */ static void on_succeeded(bidirectional_stream* stream) { CRONET_LOG(GPR_DEBUG, "on_succeeded(%p)", stream); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; stream_obj* s = static_cast(stream->annotation); @@ -511,6 +514,7 @@ static void on_succeeded(bidirectional_stream* stream) { */ static void on_stream_ready(bidirectional_stream* stream) { CRONET_LOG(GPR_DEBUG, "W: on_stream_ready(%p)", stream); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; stream_obj* s = static_cast(stream->annotation); grpc_cronet_transport* t = s->curr_ct; @@ -541,6 +545,7 @@ static void on_response_headers_received( bidirectional_stream* stream, const bidirectional_stream_header_array* headers, const char* negotiated_protocol) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; CRONET_LOG(GPR_DEBUG, "R: on_response_headers_received(%p, %p, %s)", stream, headers, negotiated_protocol); @@ -580,6 +585,7 @@ static void on_response_headers_received( Cronet callback */ static void on_write_completed(bidirectional_stream* stream, const char* data) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; stream_obj* s = static_cast(stream->annotation); CRONET_LOG(GPR_DEBUG, "W: on_write_completed(%p, %s)", stream, data); @@ -598,6 +604,7 @@ static void on_write_completed(bidirectional_stream* stream, const char* data) { */ static void on_read_completed(bidirectional_stream* stream, char* data, int count) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; stream_obj* s = static_cast(stream->annotation); CRONET_LOG(GPR_DEBUG, "R: on_read_completed(%p, %p, %d)", stream, data, @@ -640,6 +647,7 @@ static void on_read_completed(bidirectional_stream* stream, char* data, static void on_response_trailers_received( bidirectional_stream* stream, const bidirectional_stream_header_array* trailers) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; CRONET_LOG(GPR_DEBUG, "R: on_response_trailers_received(%p,%p)", stream, trailers); diff --git a/src/core/lib/iomgr/cfstream_handle.cc b/src/core/lib/iomgr/cfstream_handle.cc index 6cb9ca1a0d4..87b7b9fb334 100644 --- a/src/core/lib/iomgr/cfstream_handle.cc +++ b/src/core/lib/iomgr/cfstream_handle.cc @@ -52,6 +52,7 @@ CFStreamHandle* CFStreamHandle::CreateStreamHandle( void CFStreamHandle::ReadCallback(CFReadStreamRef stream, CFStreamEventType type, void* client_callback_info) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; CFStreamHandle* handle = static_cast(client_callback_info); if (grpc_tcp_trace.enabled()) { @@ -77,6 +78,7 @@ void CFStreamHandle::ReadCallback(CFReadStreamRef stream, void CFStreamHandle::WriteCallback(CFWriteStreamRef stream, CFStreamEventType type, void* clientCallBackInfo) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; CFStreamHandle* handle = static_cast(clientCallBackInfo); if (grpc_tcp_trace.enabled()) { diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.cc b/src/core/lib/security/credentials/jwt/jwt_credentials.cc index f2591a1ea5e..70fe45e56dc 100644 --- a/src/core/lib/security/credentials/jwt/jwt_credentials.cc +++ b/src/core/lib/security/credentials/jwt/jwt_credentials.cc @@ -174,6 +174,7 @@ grpc_call_credentials* grpc_service_account_jwt_access_credentials_create( gpr_free(clean_json); } GPR_ASSERT(reserved == nullptr); + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; return grpc_service_account_jwt_access_credentials_create_from_auth_json_key( grpc_auth_json_key_create_from_string(json_key), token_lifetime) diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.cc b/src/core/lib/security/credentials/jwt/jwt_verifier.cc index cdef0f322a9..d887c354b41 100644 --- a/src/core/lib/security/credentials/jwt/jwt_verifier.cc +++ b/src/core/lib/security/credentials/jwt/jwt_verifier.cc @@ -353,6 +353,7 @@ static verifier_cb_ctx* verifier_cb_ctx_create( grpc_jwt_claims* claims, const char* audience, grpc_slice signature, const char* signed_jwt, size_t signed_jwt_len, void* user_data, grpc_jwt_verification_done_cb cb) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; verifier_cb_ctx* ctx = static_cast(gpr_zalloc(sizeof(verifier_cb_ctx))); diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.cc b/src/core/lib/security/credentials/plugin/plugin_credentials.cc index 52982fdb8f1..59fecbca992 100644 --- a/src/core/lib/security/credentials/plugin/plugin_credentials.cc +++ b/src/core/lib/security/credentials/plugin/plugin_credentials.cc @@ -114,6 +114,7 @@ static void plugin_md_request_metadata_ready(void* request, grpc_status_code status, const char* error_details) { /* called from application code */ + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx(GRPC_EXEC_CTX_FLAG_IS_FINISHED | GRPC_EXEC_CTX_FLAG_THREAD_RESOURCE_LOOP); grpc_plugin_credentials::pending_request* r = From 30d8f7a6268b30f7b3b4d5657ce936d2f903f968 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Fri, 8 Feb 2019 17:14:45 -0800 Subject: [PATCH 194/218] Memset before setting length --- src/core/lib/iomgr/buffer_list.cc | 2 +- test/core/iomgr/buffer_list_test.cc | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/lib/iomgr/buffer_list.cc b/src/core/lib/iomgr/buffer_list.cc index 321de539934..73915933eee 100644 --- a/src/core/lib/iomgr/buffer_list.cc +++ b/src/core/lib/iomgr/buffer_list.cc @@ -188,8 +188,8 @@ void extract_opt_stats_from_cmsg(ConnectionMetrics* metrics, } static int get_socket_tcp_info(grpc_core::tcp_info* info, int fd) { - info->length = sizeof(*info) - sizeof(socklen_t); memset(info, 0, sizeof(*info)); + info->length = sizeof(*info) - sizeof(socklen_t); return getsockopt(fd, IPPROTO_TCP, TCP_INFO, info, &(info->length)); } } /* namespace */ diff --git a/test/core/iomgr/buffer_list_test.cc b/test/core/iomgr/buffer_list_test.cc index 61a81e31c2b..70e36940425 100644 --- a/test/core/iomgr/buffer_list_test.cc +++ b/test/core/iomgr/buffer_list_test.cc @@ -66,6 +66,7 @@ static void TestVerifierCalledOnAckVerifier(void* arg, GPR_ASSERT(ts->acked_time.time.clock_type == GPR_CLOCK_REALTIME); GPR_ASSERT(ts->acked_time.time.tv_sec == 123); GPR_ASSERT(ts->acked_time.time.tv_nsec == 456); + GPR_ASSERT(ts->info.length > 0); gpr_atm* done = reinterpret_cast(arg); gpr_atm_rel_store(done, static_cast(1)); } From d8947ae0731b4d474a8155c739181cf5cc460a91 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 8 Feb 2019 17:17:00 -0800 Subject: [PATCH 195/218] Fix internal build error --- test/cpp/end2end/channelz_service_test.cc | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/cpp/end2end/channelz_service_test.cc b/test/cpp/end2end/channelz_service_test.cc index e7719b5c14e..fe52a64db48 100644 --- a/test/cpp/end2end/channelz_service_test.cc +++ b/test/cpp/end2end/channelz_service_test.cc @@ -35,8 +35,6 @@ #include "test/core/util/test_config.h" #include "test/cpp/end2end/test_service_impl.h" -#include - #include using grpc::channelz::v1::GetChannelRequest; @@ -54,14 +52,6 @@ using grpc::channelz::v1::GetSubchannelResponse; using grpc::channelz::v1::GetTopChannelsRequest; using grpc::channelz::v1::GetTopChannelsResponse; -// This code snippet can be used to print out any responses for -// visual debugging. -// -// -// string out_str; -// google::protobuf::TextFormat::PrintToString(resp, &out_str); -// std::cout << "resp: " << out_str << "\n"; - namespace grpc { namespace testing { namespace { From 40544bb112a87ed9738d92b4f2a4b3c39551a031 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 8 Feb 2019 17:33:47 -0800 Subject: [PATCH 196/218] Min deployment target change --- .../manual_tests/GrpcIosTest.xcodeproj/project.pbxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/objective-c/manual_tests/GrpcIosTest.xcodeproj/project.pbxproj b/src/objective-c/manual_tests/GrpcIosTest.xcodeproj/project.pbxproj index 00004e06cad..9063719aa2e 100644 --- a/src/objective-c/manual_tests/GrpcIosTest.xcodeproj/project.pbxproj +++ b/src/objective-c/manual_tests/GrpcIosTest.xcodeproj/project.pbxproj @@ -323,6 +323,7 @@ CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -342,6 +343,7 @@ CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", From 34965961cf15dfdb8cc2a6c290849704771b763e Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Sat, 9 Feb 2019 12:56:02 -0800 Subject: [PATCH 197/218] check grpc is init before creating execctx --- src/core/lib/iomgr/fork_posix.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/lib/iomgr/fork_posix.cc b/src/core/lib/iomgr/fork_posix.cc index 2eebe3f26f6..0918e7ae1ba 100644 --- a/src/core/lib/iomgr/fork_posix.cc +++ b/src/core/lib/iomgr/fork_posix.cc @@ -47,11 +47,11 @@ bool registered_handlers = false; } // namespace void grpc_prefork() { - grpc_core::ExecCtx exec_ctx; skipped_handler = true; if (!grpc_is_initialized()) { return; } + grpc_core::ExecCtx exec_ctx; if (!grpc_core::Fork::Enabled()) { gpr_log(GPR_ERROR, "Fork support not enabled; try running with the " From dc8bac54ad4a0b4aa8c3e14862ffee5b547dff9e Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sat, 9 Feb 2019 22:16:29 -0800 Subject: [PATCH 198/218] patch --- tools/internal_ci/helper_scripts/prepare_build_macos_rc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/internal_ci/helper_scripts/prepare_build_macos_rc b/tools/internal_ci/helper_scripts/prepare_build_macos_rc index 2ecd39465d4..e9ec07cd0f9 100644 --- a/tools/internal_ci/helper_scripts/prepare_build_macos_rc +++ b/tools/internal_ci/helper_scripts/prepare_build_macos_rc @@ -48,11 +48,9 @@ set -ex # cocoapods export LANG=en_US.UTF-8 -# pre-fetch cocoapods master repo with HEAD only +# pre-fetch cocoapods master repo's most recent commit only mkdir -p ~/.cocoapods/repos -git clone --depth 1 https://github.com/CocoaPods/Specs.git ~/.cocoapods/repos/master - -time pod repo update # needed by python +time git clone --depth 1 https://github.com/CocoaPods/Specs.git ~/.cocoapods/repos/master # python time pip install virtualenv --user python From 1124c4edd98ee2c051ebf99f36c55a3ea41df616 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sun, 10 Feb 2019 11:22:30 -0800 Subject: [PATCH 199/218] increase timeout of cfstream-tests --- tools/run_tests/run_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 2556e777730..986e7cd58c2 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -1126,7 +1126,7 @@ class ObjCLanguage(object): }), self.config.job_spec( ['test/core/iomgr/ios/CFStreamTests/run_tests.sh'], - timeout_seconds=10 * 60, + timeout_seconds=20 * 60, shortname='cfstream-tests', cpu_cost=1e6, environ=_FORCE_ENVIRON_FOR_WRAPPERS), From 5c85f5a1a001eab3f671d674a915d720347c8f3a Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Sat, 9 Feb 2019 01:09:13 -0800 Subject: [PATCH 200/218] Ruby: refactor init/shutdown logic to avoid using atexit; fix windows --- src/ruby/ext/grpc/rb_call_credentials.c | 13 ++++--- src/ruby/ext/grpc/rb_channel.c | 16 +++++--- src/ruby/ext/grpc/rb_channel_credentials.c | 12 ++++-- src/ruby/ext/grpc/rb_compression_options.c | 16 ++++---- src/ruby/ext/grpc/rb_event_thread.c | 2 + src/ruby/ext/grpc/rb_grpc.c | 45 +++++++++++----------- src/ruby/ext/grpc/rb_grpc.h | 6 ++- src/ruby/ext/grpc/rb_server.c | 12 ++++-- 8 files changed, 71 insertions(+), 51 deletions(-) diff --git a/src/ruby/ext/grpc/rb_call_credentials.c b/src/ruby/ext/grpc/rb_call_credentials.c index be325975920..cea9620081f 100644 --- a/src/ruby/ext/grpc/rb_call_credentials.c +++ b/src/ruby/ext/grpc/rb_call_credentials.c @@ -134,8 +134,7 @@ static void grpc_rb_call_credentials_plugin_destroy(void* state) { // Not sure what needs to be done here } -/* Destroys the credentials instances. */ -static void grpc_rb_call_credentials_free(void* p) { +static void grpc_rb_call_credentials_free_internal(void* p) { grpc_rb_call_credentials* wrapper; if (p == NULL) { return; @@ -143,10 +142,15 @@ static void grpc_rb_call_credentials_free(void* p) { wrapper = (grpc_rb_call_credentials*)p; grpc_call_credentials_release(wrapper->wrapped); wrapper->wrapped = NULL; - xfree(p); } +/* Destroys the credentials instances. */ +static void grpc_rb_call_credentials_free(void* p) { + grpc_rb_call_credentials_free_internal(p); + grpc_ruby_shutdown(); +} + /* Protects the mark object from GC */ static void grpc_rb_call_credentials_mark(void* p) { grpc_rb_call_credentials* wrapper = NULL; @@ -175,6 +179,7 @@ static rb_data_type_t grpc_rb_call_credentials_data_type = { /* Allocates CallCredentials instances. Provides safe initial defaults for the instance fields. */ static VALUE grpc_rb_call_credentials_alloc(VALUE cls) { + grpc_ruby_init(); grpc_rb_call_credentials* wrapper = ALLOC(grpc_rb_call_credentials); wrapper->wrapped = NULL; wrapper->mark = Qnil; @@ -212,8 +217,6 @@ static VALUE grpc_rb_call_credentials_init(VALUE self, VALUE proc) { grpc_call_credentials* creds = NULL; grpc_metadata_credentials_plugin plugin; - grpc_ruby_once_init(); - TypedData_Get_Struct(self, grpc_rb_call_credentials, &grpc_rb_call_credentials_data_type, wrapper); diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 5bde962f788..d789e5a4362 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -143,14 +143,12 @@ static void* channel_safe_destroy_without_gil(void* arg) { return NULL; } -/* Destroys Channel instances. */ -static void grpc_rb_channel_free(void* p) { +static void grpc_rb_channel_free_internal(void* p) { grpc_rb_channel* ch = NULL; if (p == NULL) { return; }; ch = (grpc_rb_channel*)p; - if (ch->bg_wrapped != NULL) { /* assumption made here: it's ok to directly gpr_mu_lock the global * connection polling mutex because we're in a finalizer, @@ -159,10 +157,15 @@ static void grpc_rb_channel_free(void* p) { grpc_rb_channel_safe_destroy(ch->bg_wrapped); ch->bg_wrapped = NULL; } - xfree(p); } +/* Destroys Channel instances. */ +static void grpc_rb_channel_free(void* p) { + grpc_rb_channel_free_internal(p); + grpc_ruby_shutdown(); +} + /* Protects the mark object from GC */ static void grpc_rb_channel_mark(void* p) { grpc_rb_channel* channel = NULL; @@ -189,6 +192,7 @@ static rb_data_type_t grpc_channel_data_type = {"grpc_channel", /* Allocates grpc_rb_channel instances. */ static VALUE grpc_rb_channel_alloc(VALUE cls) { + grpc_ruby_init(); grpc_rb_channel* wrapper = ALLOC(grpc_rb_channel); wrapper->bg_wrapped = NULL; wrapper->credentials = Qnil; @@ -216,7 +220,6 @@ static VALUE grpc_rb_channel_init(int argc, VALUE* argv, VALUE self) { int stop_waiting_for_thread_start = 0; MEMZERO(&args, grpc_channel_args, 1); - grpc_ruby_once_init(); grpc_ruby_fork_guard(); rb_thread_call_without_gvl( wait_until_channel_polling_thread_started_no_gil, @@ -682,9 +685,10 @@ static VALUE run_poll_channels_loop(VALUE arg) { gpr_log( GPR_DEBUG, "GRPC_RUBY: run_poll_channels_loop - create connection polling thread"); + grpc_ruby_init(); rb_thread_call_without_gvl(run_poll_channels_loop_no_gil, NULL, run_poll_channels_loop_unblocking_func, NULL); - + grpc_ruby_shutdown(); return Qnil; } diff --git a/src/ruby/ext/grpc/rb_channel_credentials.c b/src/ruby/ext/grpc/rb_channel_credentials.c index 178224c6e00..970bc4eeb11 100644 --- a/src/ruby/ext/grpc/rb_channel_credentials.c +++ b/src/ruby/ext/grpc/rb_channel_credentials.c @@ -48,8 +48,7 @@ typedef struct grpc_rb_channel_credentials { grpc_channel_credentials* wrapped; } grpc_rb_channel_credentials; -/* Destroys the credentials instances. */ -static void grpc_rb_channel_credentials_free(void* p) { +static void grpc_rb_channel_credentials_free_internal(void* p) { grpc_rb_channel_credentials* wrapper = NULL; if (p == NULL) { return; @@ -61,6 +60,12 @@ static void grpc_rb_channel_credentials_free(void* p) { xfree(p); } +/* Destroys the credentials instances. */ +static void grpc_rb_channel_credentials_free(void* p) { + grpc_rb_channel_credentials_free_internal(p); + grpc_ruby_shutdown(); +} + /* Protects the mark object from GC */ static void grpc_rb_channel_credentials_mark(void* p) { grpc_rb_channel_credentials* wrapper = NULL; @@ -90,6 +95,7 @@ static rb_data_type_t grpc_rb_channel_credentials_data_type = { /* Allocates ChannelCredential instances. Provides safe initial defaults for the instance fields. */ static VALUE grpc_rb_channel_credentials_alloc(VALUE cls) { + grpc_ruby_init(); grpc_rb_channel_credentials* wrapper = ALLOC(grpc_rb_channel_credentials); wrapper->wrapped = NULL; wrapper->mark = Qnil; @@ -147,8 +153,6 @@ static VALUE grpc_rb_channel_credentials_init(int argc, VALUE* argv, const char* pem_root_certs_cstr = NULL; MEMZERO(&key_cert_pair, grpc_ssl_pem_key_cert_pair, 1); - grpc_ruby_once_init(); - /* "03" == no mandatory arg, 3 optional */ rb_scan_args(argc, argv, "03", &pem_root_certs, &pem_private_key, &pem_cert_chain); diff --git a/src/ruby/ext/grpc/rb_compression_options.c b/src/ruby/ext/grpc/rb_compression_options.c index 4ba6991ef66..d10c603460c 100644 --- a/src/ruby/ext/grpc/rb_compression_options.c +++ b/src/ruby/ext/grpc/rb_compression_options.c @@ -52,23 +52,26 @@ typedef struct grpc_rb_compression_options { grpc_compression_options* wrapped; } grpc_rb_compression_options; -/* Destroys the compression options instances and free the - * wrapped grpc compression options. */ -static void grpc_rb_compression_options_free(void* p) { +static void grpc_rb_compression_options_free_internal(void* p) { grpc_rb_compression_options* wrapper = NULL; if (p == NULL) { return; }; wrapper = (grpc_rb_compression_options*)p; - if (wrapper->wrapped != NULL) { gpr_free(wrapper->wrapped); wrapper->wrapped = NULL; } - xfree(p); } +/* Destroys the compression options instances and free the + * wrapped grpc compression options. */ +static void grpc_rb_compression_options_free(void* p) { + grpc_rb_compression_options_free_internal(p); + grpc_ruby_shutdown(); +} + /* Ruby recognized data type for the CompressionOptions class. */ static rb_data_type_t grpc_rb_compression_options_data_type = { "grpc_compression_options", @@ -87,10 +90,9 @@ static rb_data_type_t grpc_rb_compression_options_data_type = { Allocate the wrapped grpc compression options and initialize it here too. */ static VALUE grpc_rb_compression_options_alloc(VALUE cls) { + grpc_ruby_init(); grpc_rb_compression_options* wrapper = NULL; - grpc_ruby_once_init(); - wrapper = gpr_malloc(sizeof(grpc_rb_compression_options)); wrapper->wrapped = NULL; wrapper->wrapped = gpr_malloc(sizeof(grpc_compression_options)); diff --git a/src/ruby/ext/grpc/rb_event_thread.c b/src/ruby/ext/grpc/rb_event_thread.c index 281e41c9a88..c9ca14ed06a 100644 --- a/src/ruby/ext/grpc/rb_event_thread.c +++ b/src/ruby/ext/grpc/rb_event_thread.c @@ -115,6 +115,7 @@ static void grpc_rb_event_unblocking_func(void* arg) { static VALUE grpc_rb_event_thread(VALUE arg) { grpc_rb_event* event; (void)arg; + grpc_ruby_init(); while (true) { event = (grpc_rb_event*)rb_thread_call_without_gvl( grpc_rb_wait_for_event_no_gil, NULL, grpc_rb_event_unblocking_func, @@ -128,6 +129,7 @@ static VALUE grpc_rb_event_thread(VALUE arg) { } } grpc_rb_event_queue_destroy(); + grpc_ruby_shutdown(); return Qnil; } diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c index 872aed0cfce..4916cee4f7c 100644 --- a/src/ruby/ext/grpc/rb_grpc.c +++ b/src/ruby/ext/grpc/rb_grpc.c @@ -276,10 +276,6 @@ static bool grpc_ruby_forked_after_init(void) { } #endif -static void grpc_rb_shutdown(void) { - if (!grpc_ruby_forked_after_init()) grpc_shutdown(); -} - /* Initialize the GRPC module structs */ /* grpc_rb_sNewServerRpc is the struct that holds new server rpc details. */ @@ -298,12 +294,6 @@ VALUE sym_metadata = Qundef; static gpr_once g_once_init = GPR_ONCE_INIT; -static void grpc_ruby_once_init_internal() { - grpc_ruby_set_init_pid(); - grpc_init(); - atexit(grpc_rb_shutdown); -} - void grpc_ruby_fork_guard() { if (grpc_ruby_forked_after_init()) { rb_raise(rb_eRuntimeError, "grpc cannot be used before and after forking"); @@ -313,19 +303,7 @@ void grpc_ruby_fork_guard() { static VALUE bg_thread_init_rb_mu = Qundef; static int bg_thread_init_done = 0; -void grpc_ruby_once_init() { - /* ruby_vm_at_exit doesn't seem to be working. It would crash once every - * blue moon, and some users are getting it repeatedly. See the discussions - * - https://github.com/grpc/grpc/pull/5337 - * - https://bugs.ruby-lang.org/issues/12095 - * - * In order to still be able to handle the (unlikely) situation where the - * extension is loaded by a first Ruby VM that is subsequently destroyed, - * then loaded again by another VM within the same process, we need to - * schedule our initialization and destruction only once. - */ - gpr_once_init(&g_once_init, grpc_ruby_once_init_internal); - +static void grpc_ruby_init_threads() { // Avoid calling calling into ruby library (when creating threads here) // in gpr_once_init. In general, it appears to be unsafe to call // into the ruby library while holding a non-ruby mutex, because a gil yield @@ -339,6 +317,27 @@ void grpc_ruby_once_init() { rb_mutex_unlock(bg_thread_init_rb_mu); } +static int64_t g_grpc_ruby_init_count; + +void grpc_ruby_init() { + gpr_once_init(&g_once_init, grpc_ruby_set_init_pid); + grpc_init(); + grpc_ruby_init_threads(); + // (only gpr_log after logging has been initialized) + gpr_log(GPR_DEBUG, + "GRPC_RUBY: grpc_ruby_init - prev g_grpc_ruby_init_count:%" PRId64, + g_grpc_ruby_init_count++); +} + +void grpc_ruby_shutdown() { + GPR_ASSERT(g_grpc_ruby_init_count > 0); + if (!grpc_ruby_forked_after_init()) grpc_shutdown(); + gpr_log( + GPR_DEBUG, + "GRPC_RUBY: grpc_ruby_shutdown - prev g_grpc_ruby_init_count:%" PRId64, + g_grpc_ruby_init_count--); +} + void Init_grpc_c() { if (!grpc_rb_load_core()) { rb_raise(rb_eLoadError, "Couldn't find or load gRPC's dynamic C core"); diff --git a/src/ruby/ext/grpc/rb_grpc.h b/src/ruby/ext/grpc/rb_grpc.h index 4118435ecf7..2c4675839ac 100644 --- a/src/ruby/ext/grpc/rb_grpc.h +++ b/src/ruby/ext/grpc/rb_grpc.h @@ -67,8 +67,10 @@ VALUE grpc_rb_cannot_init_copy(VALUE copy, VALUE self); /* grpc_rb_time_timeval creates a gpr_timespec from a ruby time object. */ gpr_timespec grpc_rb_time_timeval(VALUE time, int interval); -void grpc_ruby_once_init(); - void grpc_ruby_fork_guard(); +void grpc_ruby_init(); + +void grpc_ruby_shutdown(); + #endif /* GRPC_RB_H_ */ diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c index 2931f344092..4396de1c335 100644 --- a/src/ruby/ext/grpc/rb_server.c +++ b/src/ruby/ext/grpc/rb_server.c @@ -86,8 +86,7 @@ static void grpc_rb_server_maybe_destroy(grpc_rb_server* server) { } } -/* Destroys server instances. */ -static void grpc_rb_server_free(void* p) { +static void grpc_rb_server_free_internal(void* p) { grpc_rb_server* svr = NULL; gpr_timespec deadline; if (p == NULL) { @@ -104,6 +103,12 @@ static void grpc_rb_server_free(void* p) { xfree(p); } +/* Destroys server instances. */ +static void grpc_rb_server_free(void* p) { + grpc_rb_server_free_internal(p); + grpc_ruby_shutdown(); +} + static const rb_data_type_t grpc_rb_server_data_type = { "grpc_server", {GRPC_RB_GC_NOT_MARKED, @@ -123,6 +128,7 @@ static const rb_data_type_t grpc_rb_server_data_type = { /* Allocates grpc_rb_server instances. */ static VALUE grpc_rb_server_alloc(VALUE cls) { + grpc_ruby_init(); grpc_rb_server* wrapper = ALLOC(grpc_rb_server); wrapper->wrapped = NULL; wrapper->destroy_done = 0; @@ -142,8 +148,6 @@ static VALUE grpc_rb_server_init(VALUE self, VALUE channel_args) { grpc_channel_args args; MEMZERO(&args, grpc_channel_args, 1); - grpc_ruby_once_init(); - cq = grpc_completion_queue_create_for_pluck(NULL); TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, wrapper); From 52695cae917e125c2717b58accb7cb1526b7a265 Mon Sep 17 00:00:00 2001 From: Prashant Jaikumar Date: Sun, 10 Feb 2019 23:59:47 -0800 Subject: [PATCH 201/218] Fix TSAN flake in time_change_test --- test/cpp/end2end/time_change_test.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/cpp/end2end/time_change_test.cc b/test/cpp/end2end/time_change_test.cc index 9fbd01299d0..7f4e3caf6f9 100644 --- a/test/cpp/end2end/time_change_test.cc +++ b/test/cpp/end2end/time_change_test.cc @@ -74,14 +74,18 @@ static gpr_timespec now_impl(gpr_clock_type clock) { // offset the value returned by gpr_now(GPR_CLOCK_REALTIME) by msecs // milliseconds static void set_now_offset(int msecs) { + gpr_mu_lock(&g_mu); g_time_shift_sec = msecs / 1000; g_time_shift_nsec = (msecs % 1000) * 1e6; + gpr_mu_unlock(&g_mu); } // restore the original implementation of gpr_now() static void reset_now_offset() { + gpr_mu_lock(&g_mu); g_time_shift_sec = 0; g_time_shift_nsec = 0; + gpr_mu_unlock(&g_mu); } namespace grpc { From a832d66b09d5ba295726058153bdf5df6abf4565 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 1 Oct 2018 15:41:03 +0200 Subject: [PATCH 202/218] upgrade System.Interactive.Async to 3.2.0 --- src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj | 2 +- src/csharp/Grpc.Core/Grpc.Core.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj b/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj index 0dc73576bf5..eec8fc56de0 100755 --- a/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj +++ b/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj @@ -21,7 +21,7 @@ - + diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index b99c23ae131..43ace08e52c 100755 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -85,7 +85,7 @@ - + From b90dd36270be2c0be8bbdf16f49c6ed61f5bdf7c Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Mon, 11 Feb 2019 08:13:06 -0800 Subject: [PATCH 203/218] add comment --- src/core/lib/iomgr/fork_posix.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/lib/iomgr/fork_posix.cc b/src/core/lib/iomgr/fork_posix.cc index 0918e7ae1ba..7f8fb7e828b 100644 --- a/src/core/lib/iomgr/fork_posix.cc +++ b/src/core/lib/iomgr/fork_posix.cc @@ -48,6 +48,8 @@ bool registered_handlers = false; void grpc_prefork() { skipped_handler = true; + // This may be called after core shuts down, so verify initialized before + // instantiating an ExecCtx. if (!grpc_is_initialized()) { return; } From f96d630c33c07889a40009fa074365fe7b27d4ce Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Fri, 8 Feb 2019 09:01:27 -0800 Subject: [PATCH 204/218] Document ApplicationCallbackExecCtx, update ExecCtx comments --- src/core/lib/iomgr/exec_ctx.h | 66 ++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index 16ac14ba6c5..4a3d52e220e 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -58,8 +58,8 @@ grpc_millis grpc_timespec_to_millis_round_up(gpr_timespec timespec); namespace grpc_core { /** Execution context. * A bag of data that collects information along a callstack. - * It is created on the stack at public API entry points, and stored internally - * as a thread-local variable. + * It is created on the stack at core entry points (public API or iomgr), and + * stored internally as a thread-local variable. * * Generally, to create an exec_ctx instance, add the following line at the top * of the public API entry point or at the start of a thread's work function : @@ -70,7 +70,7 @@ namespace grpc_core { * grpc_core::ExecCtx::Get() * * Specific responsibilities (this may grow in the future): - * - track a list of work that needs to be delayed until the top of the + * - track a list of core work that needs to be delayed until the base of the * call stack (this provides a convenient mechanism to run callbacks * without worrying about locking issues) * - provide a decision maker (via IsReadyToFinish) that provides a @@ -80,10 +80,19 @@ namespace grpc_core { * CONVENTIONS: * - Instance of this must ALWAYS be constructed on the stack, never * heap allocated. - * - Exactly one instance of ExecCtx must be created per thread. Instances must - * always be called exec_ctx. * - Do not pass exec_ctx as a parameter to a function. Always access it using * grpc_core::ExecCtx::Get(). + * - NOTE: In the future, the convention is likely to change to allow only one + * ExecCtx on a thread's stack at the same time. The TODO below + * discusses this plan in more detail. + * + * TODO(yashykt): Only allow one "active" ExecCtx on a thread at the same time. + * Stage 1: If a new one is created on the stack, it should just + * pass-through to the underlying ExecCtx deeper in the thread's + * stack. + * Stage 2: Assert if a 2nd one is ever created on the stack + * since that implies a core re-entry outside of application + * callbacks. */ class ExecCtx { public: @@ -227,6 +236,53 @@ class ExecCtx { ExecCtx* last_exec_ctx_ = Get(); }; +/** Application-callback execution context. + * A bag of data that collects information along a callstack. + * It is created on the stack at core entry points, and stored internally + * as a thread-local variable. + * + * There are three key differences between this structure and ExecCtx: + * 1. ApplicationCallbackExecCtx builds a list of application-level + * callbacks, but ExecCtx builds a list of internal callbacks to invoke. + * 2. ApplicationCallbackExecCtx invokes its callbacks only at destruction; + * there is no explicit Flush method. + * 3. If more than one ApplicationCallbackExecCtx is created on the thread's + * stack, only the one closest to the base of the stack is actually + * active and this is the only one that enqueues application callbacks. + * (Unlike ExecCtx, it is not feasible to prevent multiple of these on the + * stack since the executing application callback may itself enter core. + * However, the new one created will just pass callbacks through to the + * base one and those will not be executed until the return to the + * destructor of the base one, preventing unlimited stack growth.) + * + * This structure exists because application callbacks may themselves cause a + * core re-entry (e.g., through a public API call) and if that call in turn + * causes another application-callback, there could be arbitrarily growing + * stacks of core re-entries. Instead, any application callbacks instead should + * not be invoked until other core work is done and other application callbacks + * have completed. To accomplish this, any application callback should be + * enqueued using grpc_core::ApplicationCallbackExecCtx::Enqueue . + * + * CONVENTIONS: + * - Instances of this must ALWAYS be constructed on the stack, never + * heap allocated. + * - Instances of this are generally constructed before ExecCtx when needed. + * The only exception is for ExecCtx's that are explicitly flushed and + * that survive beyond the scope of the function that can cause application + * callbacks to be invoked (e.g., in the timer thread). + * + * Generally, core entry points that may trigger application-level callbacks + * will have the following declarations: + * + * grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + * grpc_core::ExecCtx exec_ctx; + * + * This ordering is important to make sure that the ApplicationCallbackExecCtx + * is destroyed after the ExecCtx (to prevent the re-entry problem described + * above, as well as making sure that ExecCtx core callbacks are invoked first) + * + */ + class ApplicationCallbackExecCtx { public: ApplicationCallbackExecCtx() { From 93b7acd9bf11f0df780ec3a106792911b337db92 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Sun, 10 Feb 2019 22:09:15 -0800 Subject: [PATCH 205/218] Disable service config resolution with c-ares by default --- .../resolver/dns/c_ares/dns_resolver_ares.cc | 2 +- test/cpp/naming/gen_build_yaml.py | 1 + test/cpp/naming/resolver_component_test.cc | 27 ++++++++ .../naming/resolver_component_tests_runner.py | 61 +++++++++++++++++++ .../naming/resolver_test_record_groups.yaml | 60 ++++++++++++++++++ 5 files changed, 150 insertions(+), 1 deletion(-) 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 bf8b0ea5f62..69d4ee24368 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 @@ -151,7 +151,7 @@ AresDnsResolver::AresDnsResolver(const ResolverArgs& args) // Disable service config option const grpc_arg* arg = grpc_channel_args_find( channel_args_, GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION); - request_service_config_ = !grpc_channel_arg_get_bool(arg, false); + request_service_config_ = !grpc_channel_arg_get_bool(arg, true); // Min time b/t resolutions option arg = grpc_channel_args_find(channel_args_, GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS); diff --git a/test/cpp/naming/gen_build_yaml.py b/test/cpp/naming/gen_build_yaml.py index aeff927824d..9bf5ae9b2f8 100755 --- a/test/cpp/naming/gen_build_yaml.py +++ b/test/cpp/naming/gen_build_yaml.py @@ -49,6 +49,7 @@ def _resolver_test_cases(resolver_component_data): (test_case['expected_chosen_service_config'] or '')), ('expected_lb_policy', (test_case['expected_lb_policy'] or '')), ('enable_srv_queries', test_case['enable_srv_queries']), + ('enable_txt_queries', test_case['enable_txt_queries']), ], }) return out diff --git a/test/cpp/naming/resolver_component_test.cc b/test/cpp/naming/resolver_component_test.cc index ff9ebe70a8e..9532529e45d 100644 --- a/test/cpp/naming/resolver_component_test.cc +++ b/test/cpp/naming/resolver_component_test.cc @@ -99,6 +99,13 @@ DEFINE_string( "generate " "the python script runner doesn't allow us to pass a gflags bool to this " "binary."); +DEFINE_string( + enable_txt_queries, "", + "Whether or not to enable TXT queries for the ares resolver instance." + "It would be better if this arg could be bool, but the way that we " + "generate " + "the python script runner doesn't allow us to pass a gflags bool to this " + "binary."); DEFINE_string(expected_lb_policy, "", "Expected lb policy name that appears in resolver result channel " "arg. Empty for none."); @@ -461,6 +468,26 @@ void RunResolvesRelevantRecordsTest(void (*OnDoneLocked)(void* arg, gpr_log(GPR_DEBUG, "Invalid value for --enable_srv_queries."); abort(); } + gpr_log(GPR_DEBUG, "resolver_component_test: --enable_txt_queries: %s", + FLAGS_enable_txt_queries.c_str()); + // By default, TXT queries are disabled, so tests that expect no TXT query + // should avoid setting any channel arg. Test cases that do rely on the TXT + // query must explicitly enable TXT though. + if (FLAGS_enable_txt_queries == "True") { + // Unlike SRV queries, there isn't a channel arg specific to TXT records. + // Rather, we use the resolver-agnostic "service config" resolution option, + // for which c-ares has its own specific default value, which isn't + // necessarily shared by other resolvers. + grpc_arg txt_queries_arg = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_SERVICE_CONFIG_DISABLE_RESOLUTION), false); + grpc_channel_args* tmp_args = + grpc_channel_args_copy_and_add(resolver_args, &txt_queries_arg, 1); + grpc_channel_args_destroy(resolver_args); + resolver_args = tmp_args; + } else if (FLAGS_enable_txt_queries != "False") { + gpr_log(GPR_DEBUG, "Invalid value for --enable_txt_queries."); + abort(); + } // create resolver and resolve grpc_core::OrphanablePtr resolver = grpc_core::ResolverRegistry::CreateResolver(whole_uri, resolver_args, diff --git a/test/cpp/naming/resolver_component_tests_runner.py b/test/cpp/naming/resolver_component_tests_runner.py index a4438cb100e..a0eda79ec62 100755 --- a/test/cpp/naming/resolver_component_tests_runner.py +++ b/test/cpp/naming/resolver_component_tests_runner.py @@ -126,6 +126,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '', '--expected_lb_policy', '', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -139,6 +140,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '', '--expected_lb_policy', '', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -152,6 +154,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '', '--expected_lb_policy', '', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -165,6 +168,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '', '--expected_lb_policy', '', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -178,6 +182,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '', '--expected_lb_policy', '', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -191,6 +196,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService","waitForReady":true}]}]}', '--expected_lb_policy', 'round_robin', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -204,6 +210,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"NoSrvSimpleService","waitForReady":true}]}]}', '--expected_lb_policy', 'round_robin', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -217,6 +224,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '', '--expected_lb_policy', '', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -230,6 +238,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '', '--expected_lb_policy', '', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -243,6 +252,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"CppService","waitForReady":true}]}]}', '--expected_lb_policy', 'round_robin', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -256,6 +266,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"AlwaysPickedService","waitForReady":true}]}]}', '--expected_lb_policy', 'round_robin', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -269,6 +280,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '', '--expected_lb_policy', '', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -282,6 +294,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '', '--expected_lb_policy', '', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -295,6 +308,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwo","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooThree","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooFour","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooFive","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooSix","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooSeven","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooEight","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooNine","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTen","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooEleven","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]}]}', '--expected_lb_policy', '', '--enable_srv_queries', 'True', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -308,6 +322,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '', '--expected_lb_policy', '', '--enable_srv_queries', 'False', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -321,6 +336,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '', '--expected_lb_policy', '', '--enable_srv_queries', 'False', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -334,6 +350,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '', '--expected_lb_policy', '', '--enable_srv_queries', 'False', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -347,6 +364,7 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '', '--expected_lb_policy', '', '--enable_srv_queries', 'False', + '--enable_txt_queries', 'True', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: @@ -360,6 +378,49 @@ current_test_subprocess = subprocess.Popen([ '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService","waitForReady":true}]}]}', '--expected_lb_policy', 'round_robin', '--enable_srv_queries', 'False', + '--enable_txt_queries', 'True', + '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) +current_test_subprocess.communicate() +if current_test_subprocess.returncode != 0: + num_test_failures += 1 + +test_runner_log('Run test with target: %s' % 'srv-ipv4-simple-service-config-txt-disabled.resolver-tests-version-4.grpctestingexp.') +current_test_subprocess = subprocess.Popen([ + args.test_bin_path, + '--target_name', 'srv-ipv4-simple-service-config-txt-disabled.resolver-tests-version-4.grpctestingexp.', + '--expected_addrs', '1.2.3.4:1234,True', + '--expected_chosen_service_config', '', + '--expected_lb_policy', '', + '--enable_srv_queries', 'True', + '--enable_txt_queries', 'False', + '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) +current_test_subprocess.communicate() +if current_test_subprocess.returncode != 0: + num_test_failures += 1 + +test_runner_log('Run test with target: %s' % 'ipv4-cpp-config-has-zero-percentage-txt-disabled.resolver-tests-version-4.grpctestingexp.') +current_test_subprocess = subprocess.Popen([ + args.test_bin_path, + '--target_name', 'ipv4-cpp-config-has-zero-percentage-txt-disabled.resolver-tests-version-4.grpctestingexp.', + '--expected_addrs', '1.2.3.4:443,False', + '--expected_chosen_service_config', '', + '--expected_lb_policy', '', + '--enable_srv_queries', 'True', + '--enable_txt_queries', 'False', + '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) +current_test_subprocess.communicate() +if current_test_subprocess.returncode != 0: + num_test_failures += 1 + +test_runner_log('Run test with target: %s' % 'ipv4-second-language-is-cpp-txt-disabled.resolver-tests-version-4.grpctestingexp.') +current_test_subprocess = subprocess.Popen([ + args.test_bin_path, + '--target_name', 'ipv4-second-language-is-cpp-txt-disabled.resolver-tests-version-4.grpctestingexp.', + '--expected_addrs', '1.2.3.4:443,False', + '--expected_chosen_service_config', '', + '--expected_lb_policy', '', + '--enable_srv_queries', 'True', + '--enable_txt_queries', 'False', '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port]) current_test_subprocess.communicate() if current_test_subprocess.returncode != 0: diff --git a/test/cpp/naming/resolver_test_record_groups.yaml b/test/cpp/naming/resolver_test_record_groups.yaml index 3d8811a36f7..738fe658939 100644 --- a/test/cpp/naming/resolver_test_record_groups.yaml +++ b/test/cpp/naming/resolver_test_record_groups.yaml @@ -6,6 +6,7 @@ resolver_component_tests: expected_chosen_service_config: null expected_lb_policy: null enable_srv_queries: true + enable_txt_queries: true record_to_resolve: no-srv-ipv4-single-target records: no-srv-ipv4-single-target: @@ -15,6 +16,7 @@ resolver_component_tests: expected_chosen_service_config: null expected_lb_policy: null enable_srv_queries: true + enable_txt_queries: true record_to_resolve: srv-ipv4-single-target records: _grpclb._tcp.srv-ipv4-single-target: @@ -28,6 +30,7 @@ resolver_component_tests: expected_chosen_service_config: null expected_lb_policy: null enable_srv_queries: true + enable_txt_queries: true record_to_resolve: srv-ipv4-multi-target records: _grpclb._tcp.srv-ipv4-multi-target: @@ -41,6 +44,7 @@ resolver_component_tests: expected_chosen_service_config: null expected_lb_policy: null enable_srv_queries: true + enable_txt_queries: true record_to_resolve: srv-ipv6-single-target records: _grpclb._tcp.srv-ipv6-single-target: @@ -54,6 +58,7 @@ resolver_component_tests: expected_chosen_service_config: null expected_lb_policy: null enable_srv_queries: true + enable_txt_queries: true record_to_resolve: srv-ipv6-multi-target records: _grpclb._tcp.srv-ipv6-multi-target: @@ -67,6 +72,7 @@ resolver_component_tests: expected_chosen_service_config: '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService","waitForReady":true}]}]}' expected_lb_policy: round_robin enable_srv_queries: true + enable_txt_queries: true record_to_resolve: srv-ipv4-simple-service-config records: _grpclb._tcp.srv-ipv4-simple-service-config: @@ -81,6 +87,7 @@ resolver_component_tests: expected_chosen_service_config: '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"NoSrvSimpleService","waitForReady":true}]}]}' expected_lb_policy: round_robin enable_srv_queries: true + enable_txt_queries: true record_to_resolve: ipv4-no-srv-simple-service-config records: ipv4-no-srv-simple-service-config: @@ -93,6 +100,7 @@ resolver_component_tests: expected_chosen_service_config: null expected_lb_policy: null enable_srv_queries: true + enable_txt_queries: true record_to_resolve: ipv4-no-config-for-cpp records: ipv4-no-config-for-cpp: @@ -105,6 +113,7 @@ resolver_component_tests: expected_chosen_service_config: null expected_lb_policy: null enable_srv_queries: true + enable_txt_queries: true record_to_resolve: ipv4-cpp-config-has-zero-percentage records: ipv4-cpp-config-has-zero-percentage: @@ -117,6 +126,7 @@ resolver_component_tests: expected_chosen_service_config: '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"CppService","waitForReady":true}]}]}' expected_lb_policy: round_robin enable_srv_queries: true + enable_txt_queries: true record_to_resolve: ipv4-second-language-is-cpp records: ipv4-second-language-is-cpp: @@ -129,6 +139,7 @@ resolver_component_tests: expected_chosen_service_config: '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"AlwaysPickedService","waitForReady":true}]}]}' expected_lb_policy: round_robin enable_srv_queries: true + enable_txt_queries: true record_to_resolve: ipv4-config-with-percentages records: ipv4-config-with-percentages: @@ -142,6 +153,7 @@ resolver_component_tests: expected_chosen_service_config: null expected_lb_policy: null enable_srv_queries: true + enable_txt_queries: true record_to_resolve: srv-ipv4-target-has-backend-and-balancer records: _grpclb._tcp.srv-ipv4-target-has-backend-and-balancer: @@ -156,6 +168,7 @@ resolver_component_tests: expected_chosen_service_config: null expected_lb_policy: null enable_srv_queries: true + enable_txt_queries: true record_to_resolve: srv-ipv6-target-has-backend-and-balancer records: _grpclb._tcp.srv-ipv6-target-has-backend-and-balancer: @@ -169,6 +182,7 @@ resolver_component_tests: expected_chosen_service_config: '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwo","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooThree","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooFour","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooFive","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooSix","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooSeven","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooEight","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooNine","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTen","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooEleven","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]}]}' expected_lb_policy: null enable_srv_queries: true + enable_txt_queries: true record_to_resolve: ipv4-config-causing-fallback-to-tcp records: ipv4-config-causing-fallback-to-tcp: @@ -182,6 +196,7 @@ resolver_component_tests: expected_chosen_service_config: null expected_lb_policy: null enable_srv_queries: false + enable_txt_queries: true record_to_resolve: srv-ipv4-single-target-srv-disabled records: _grpclb._tcp.srv-ipv4-single-target-srv-disabled: @@ -197,6 +212,7 @@ resolver_component_tests: expected_chosen_service_config: null expected_lb_policy: null enable_srv_queries: false + enable_txt_queries: true record_to_resolve: srv-ipv4-multi-target-srv-disabled records: _grpclb._tcp.srv-ipv4-multi-target-srv-disabled: @@ -214,6 +230,7 @@ resolver_component_tests: expected_chosen_service_config: null expected_lb_policy: null enable_srv_queries: false + enable_txt_queries: true record_to_resolve: srv-ipv6-single-target-srv-disabled records: _grpclb._tcp.srv-ipv6-single-target-srv-disabled: @@ -229,6 +246,7 @@ resolver_component_tests: expected_chosen_service_config: null expected_lb_policy: null enable_srv_queries: false + enable_txt_queries: true record_to_resolve: srv-ipv6-multi-target-srv-disabled records: _grpclb._tcp.srv-ipv6-multi-target-srv-disabled: @@ -246,6 +264,7 @@ resolver_component_tests: expected_chosen_service_config: '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService","waitForReady":true}]}]}' expected_lb_policy: round_robin enable_srv_queries: false + enable_txt_queries: true record_to_resolve: srv-ipv4-simple-service-config-srv-disabled records: _grpclb._tcp.srv-ipv4-simple-service-config-srv-disabled: @@ -257,3 +276,44 @@ resolver_component_tests: _grpc_config.srv-ipv4-simple-service-config-srv-disabled: - {TTL: '2100', data: 'grpc_config=[{"serviceConfig":{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService","waitForReady":true}]}]}}]', type: TXT} +- expected_addrs: + - {address: '1.2.3.4:1234', is_balancer: true} + expected_chosen_service_config: null + expected_lb_policy: null + enable_srv_queries: true + enable_txt_queries: false + record_to_resolve: srv-ipv4-simple-service-config-txt-disabled + records: + _grpclb._tcp.srv-ipv4-simple-service-config-txt-disabled: + - {TTL: '2100', data: 0 0 1234 ipv4-simple-service-config-txt-disabled, type: SRV} + ipv4-simple-service-config-txt-disabled: + - {TTL: '2100', data: 1.2.3.4, type: A} + _grpc_config.srv-ipv4-simple-service-config-txt-disabled: + - {TTL: '2100', data: 'grpc_config=[{"serviceConfig":{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService","waitForReady":true}]}]}}]', + type: TXT} +- expected_addrs: + - {address: '1.2.3.4:443', is_balancer: false} + expected_chosen_service_config: null + expected_lb_policy: null + enable_srv_queries: true + enable_txt_queries: false + record_to_resolve: ipv4-cpp-config-has-zero-percentage-txt-disabled + records: + ipv4-cpp-config-has-zero-percentage-txt-disabled: + - {TTL: '2100', data: 1.2.3.4, type: A} + _grpc_config.ipv4-cpp-config-has-zero-percentage-txt-disabled: + - {TTL: '2100', data: 'grpc_config=[{"percentage":0,"serviceConfig":{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"CppService","waitForReady":true}]}]}}]', + type: TXT} +- expected_addrs: + - {address: '1.2.3.4:443', is_balancer: false} + expected_chosen_service_config: null + expected_lb_policy: null + enable_srv_queries: true + enable_txt_queries: false + record_to_resolve: ipv4-second-language-is-cpp-txt-disabled + records: + ipv4-second-language-is-cpp-txt-disabled: + - {TTL: '2100', data: 1.2.3.4, type: A} + _grpc_config.ipv4-second-language-is-cpp-txt-disabled: + - {TTL: '2100', data: 'grpc_config=[{"clientLanguage":["go"],"serviceConfig":{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"GoService","waitForReady":true}]}]}},{"clientLanguage":["c++"],"serviceConfig":{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"CppService","waitForReady":true}]}]}}]', + type: TXT} From 195a30bb8bc05f7fb1c2873f639621d6fea2948d Mon Sep 17 00:00:00 2001 From: Arjun Roy Date: Wed, 16 Jan 2019 16:30:39 -0800 Subject: [PATCH 206/218] Grpc: Change grpc_handshake and grpc_handshake_mgr to use CPP implementations. grpc_handshake is renamed to GrpcHandshake, using C++ class definitions instead of C-style vtable classes. Update callers to use new interfaces. We use RefCountedPtr to simplify reference tracking. --- BUILD | 1 - CMakeLists.txt | 6 - Makefile | 6 - build.yaml | 1 - config.m4 | 1 - config.w32 | 1 - gRPC-Core.podspec | 1 - grpc.gemspec | 1 - grpc.gyp | 4 - package.xml | 1 - .../client_channel/http_connect_handshaker.cc | 302 +++++----- .../chttp2/client/chttp2_connector.cc | 22 +- .../transport/chttp2/server/chttp2_server.cc | 37 +- src/core/lib/channel/handshaker.cc | 355 +++++------ src/core/lib/channel/handshaker.h | 211 +++---- src/core/lib/channel/handshaker_factory.cc | 42 -- src/core/lib/channel/handshaker_factory.h | 30 +- src/core/lib/channel/handshaker_registry.cc | 116 ++-- src/core/lib/channel/handshaker_registry.h | 37 +- .../lib/http/httpcli_security_connector.cc | 27 +- .../alts/alts_security_connector.cc | 18 +- .../fake/fake_security_connector.cc | 16 +- .../local/local_security_connector.cc | 18 +- .../security_connector/security_connector.h | 4 +- .../ssl/ssl_security_connector.cc | 10 +- .../security/transport/security_handshaker.cc | 567 +++++++++--------- .../security/transport/security_handshaker.h | 13 +- src/core/lib/surface/init.cc | 4 +- src/core/lib/surface/init_secure.cc | 2 +- src/python/grpcio/grpc_core_dependencies.py | 1 - .../readahead_handshaker_server_ssl.cc | 65 +- test/core/security/ssl_server_fuzzer.cc | 15 +- tools/doxygen/Doxyfile.core.internal | 1 - .../generated/sources_and_headers.json | 1 - 34 files changed, 882 insertions(+), 1055 deletions(-) delete mode 100644 src/core/lib/channel/handshaker_factory.cc diff --git a/BUILD b/BUILD index 3f1e735466d..ebb03580bb4 100644 --- a/BUILD +++ b/BUILD @@ -701,7 +701,6 @@ grpc_cc_library( "src/core/lib/channel/channelz_registry.cc", "src/core/lib/channel/connected_channel.cc", "src/core/lib/channel/handshaker.cc", - "src/core/lib/channel/handshaker_factory.cc", "src/core/lib/channel/handshaker_registry.cc", "src/core/lib/channel/status_util.cc", "src/core/lib/compression/compression.cc", diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f1a0f6af9b..b2de3f6fde5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -971,7 +971,6 @@ add_library(grpc src/core/lib/channel/channelz_registry.cc src/core/lib/channel/connected_channel.cc src/core/lib/channel/handshaker.cc - src/core/lib/channel/handshaker_factory.cc src/core/lib/channel/handshaker_registry.cc src/core/lib/channel/status_util.cc src/core/lib/compression/compression.cc @@ -1397,7 +1396,6 @@ add_library(grpc_cronet src/core/lib/channel/channelz_registry.cc src/core/lib/channel/connected_channel.cc src/core/lib/channel/handshaker.cc - src/core/lib/channel/handshaker_factory.cc src/core/lib/channel/handshaker_registry.cc src/core/lib/channel/status_util.cc src/core/lib/compression/compression.cc @@ -1808,7 +1806,6 @@ add_library(grpc_test_util src/core/lib/channel/channelz_registry.cc src/core/lib/channel/connected_channel.cc src/core/lib/channel/handshaker.cc - src/core/lib/channel/handshaker_factory.cc src/core/lib/channel/handshaker_registry.cc src/core/lib/channel/status_util.cc src/core/lib/compression/compression.cc @@ -2134,7 +2131,6 @@ add_library(grpc_test_util_unsecure src/core/lib/channel/channelz_registry.cc src/core/lib/channel/connected_channel.cc src/core/lib/channel/handshaker.cc - src/core/lib/channel/handshaker_factory.cc src/core/lib/channel/handshaker_registry.cc src/core/lib/channel/status_util.cc src/core/lib/compression/compression.cc @@ -2436,7 +2432,6 @@ add_library(grpc_unsecure src/core/lib/channel/channelz_registry.cc src/core/lib/channel/connected_channel.cc src/core/lib/channel/handshaker.cc - src/core/lib/channel/handshaker_factory.cc src/core/lib/channel/handshaker_registry.cc src/core/lib/channel/status_util.cc src/core/lib/compression/compression.cc @@ -3324,7 +3319,6 @@ add_library(grpc++_cronet src/core/lib/channel/channelz_registry.cc src/core/lib/channel/connected_channel.cc src/core/lib/channel/handshaker.cc - src/core/lib/channel/handshaker_factory.cc src/core/lib/channel/handshaker_registry.cc src/core/lib/channel/status_util.cc src/core/lib/compression/compression.cc diff --git a/Makefile b/Makefile index e41c0584c7d..069d001d3be 100644 --- a/Makefile +++ b/Makefile @@ -3497,7 +3497,6 @@ LIBGRPC_SRC = \ src/core/lib/channel/channelz_registry.cc \ src/core/lib/channel/connected_channel.cc \ src/core/lib/channel/handshaker.cc \ - src/core/lib/channel/handshaker_factory.cc \ src/core/lib/channel/handshaker_registry.cc \ src/core/lib/channel/status_util.cc \ src/core/lib/compression/compression.cc \ @@ -3917,7 +3916,6 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/channel/channelz_registry.cc \ src/core/lib/channel/connected_channel.cc \ src/core/lib/channel/handshaker.cc \ - src/core/lib/channel/handshaker_factory.cc \ src/core/lib/channel/handshaker_registry.cc \ src/core/lib/channel/status_util.cc \ src/core/lib/compression/compression.cc \ @@ -4321,7 +4319,6 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/channel/channelz_registry.cc \ src/core/lib/channel/connected_channel.cc \ src/core/lib/channel/handshaker.cc \ - src/core/lib/channel/handshaker_factory.cc \ src/core/lib/channel/handshaker_registry.cc \ src/core/lib/channel/status_util.cc \ src/core/lib/compression/compression.cc \ @@ -4634,7 +4631,6 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \ src/core/lib/channel/channelz_registry.cc \ src/core/lib/channel/connected_channel.cc \ src/core/lib/channel/handshaker.cc \ - src/core/lib/channel/handshaker_factory.cc \ src/core/lib/channel/handshaker_registry.cc \ src/core/lib/channel/status_util.cc \ src/core/lib/compression/compression.cc \ @@ -4910,7 +4906,6 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/channel/channelz_registry.cc \ src/core/lib/channel/connected_channel.cc \ src/core/lib/channel/handshaker.cc \ - src/core/lib/channel/handshaker_factory.cc \ src/core/lib/channel/handshaker_registry.cc \ src/core/lib/channel/status_util.cc \ src/core/lib/compression/compression.cc \ @@ -5775,7 +5770,6 @@ LIBGRPC++_CRONET_SRC = \ src/core/lib/channel/channelz_registry.cc \ src/core/lib/channel/connected_channel.cc \ src/core/lib/channel/handshaker.cc \ - src/core/lib/channel/handshaker_factory.cc \ src/core/lib/channel/handshaker_registry.cc \ src/core/lib/channel/status_util.cc \ src/core/lib/compression/compression.cc \ diff --git a/build.yaml b/build.yaml index ec00450f28a..f96b0cbcf22 100644 --- a/build.yaml +++ b/build.yaml @@ -242,7 +242,6 @@ filegroups: - src/core/lib/channel/channelz_registry.cc - src/core/lib/channel/connected_channel.cc - src/core/lib/channel/handshaker.cc - - src/core/lib/channel/handshaker_factory.cc - src/core/lib/channel/handshaker_registry.cc - src/core/lib/channel/status_util.cc - src/core/lib/compression/compression.cc diff --git a/config.m4 b/config.m4 index 1874f3ba1b0..5746caf694a 100644 --- a/config.m4 +++ b/config.m4 @@ -94,7 +94,6 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/channel/channelz_registry.cc \ src/core/lib/channel/connected_channel.cc \ src/core/lib/channel/handshaker.cc \ - src/core/lib/channel/handshaker_factory.cc \ src/core/lib/channel/handshaker_registry.cc \ src/core/lib/channel/status_util.cc \ src/core/lib/compression/compression.cc \ diff --git a/config.w32 b/config.w32 index 452e8fd18b1..5659d8b8408 100644 --- a/config.w32 +++ b/config.w32 @@ -69,7 +69,6 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\channel\\channelz_registry.cc " + "src\\core\\lib\\channel\\connected_channel.cc " + "src\\core\\lib\\channel\\handshaker.cc " + - "src\\core\\lib\\channel\\handshaker_factory.cc " + "src\\core\\lib\\channel\\handshaker_registry.cc " + "src\\core\\lib\\channel\\status_util.cc " + "src\\core\\lib\\compression\\compression.cc " + diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index da48fe7e953..625d1a9a50c 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -543,7 +543,6 @@ Pod::Spec.new do |s| 'src/core/lib/channel/channelz_registry.cc', 'src/core/lib/channel/connected_channel.cc', 'src/core/lib/channel/handshaker.cc', - 'src/core/lib/channel/handshaker_factory.cc', 'src/core/lib/channel/handshaker_registry.cc', 'src/core/lib/channel/status_util.cc', 'src/core/lib/compression/compression.cc', diff --git a/grpc.gemspec b/grpc.gemspec index 9a3c657cc85..a4e25d7bb22 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -477,7 +477,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/channel/channelz_registry.cc ) s.files += %w( src/core/lib/channel/connected_channel.cc ) s.files += %w( src/core/lib/channel/handshaker.cc ) - s.files += %w( src/core/lib/channel/handshaker_factory.cc ) s.files += %w( src/core/lib/channel/handshaker_registry.cc ) s.files += %w( src/core/lib/channel/status_util.cc ) s.files += %w( src/core/lib/compression/compression.cc ) diff --git a/grpc.gyp b/grpc.gyp index 6a0a2718c8e..113c17f0d09 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -276,7 +276,6 @@ 'src/core/lib/channel/channelz_registry.cc', 'src/core/lib/channel/connected_channel.cc', 'src/core/lib/channel/handshaker.cc', - 'src/core/lib/channel/handshaker_factory.cc', 'src/core/lib/channel/handshaker_registry.cc', 'src/core/lib/channel/status_util.cc', 'src/core/lib/compression/compression.cc', @@ -643,7 +642,6 @@ 'src/core/lib/channel/channelz_registry.cc', 'src/core/lib/channel/connected_channel.cc', 'src/core/lib/channel/handshaker.cc', - 'src/core/lib/channel/handshaker_factory.cc', 'src/core/lib/channel/handshaker_registry.cc', 'src/core/lib/channel/status_util.cc', 'src/core/lib/compression/compression.cc', @@ -889,7 +887,6 @@ 'src/core/lib/channel/channelz_registry.cc', 'src/core/lib/channel/connected_channel.cc', 'src/core/lib/channel/handshaker.cc', - 'src/core/lib/channel/handshaker_factory.cc', 'src/core/lib/channel/handshaker_registry.cc', 'src/core/lib/channel/status_util.cc', 'src/core/lib/compression/compression.cc', @@ -1111,7 +1108,6 @@ 'src/core/lib/channel/channelz_registry.cc', 'src/core/lib/channel/connected_channel.cc', 'src/core/lib/channel/handshaker.cc', - 'src/core/lib/channel/handshaker_factory.cc', 'src/core/lib/channel/handshaker_registry.cc', 'src/core/lib/channel/status_util.cc', 'src/core/lib/compression/compression.cc', diff --git a/package.xml b/package.xml index 69b6fdfa671..aa2bf62411c 100644 --- a/package.xml +++ b/package.xml @@ -482,7 +482,6 @@ - diff --git a/src/core/ext/filters/client_channel/http_connect_handshaker.cc b/src/core/ext/filters/client_channel/http_connect_handshaker.cc index 0716e468181..fa5aaa9e7ce 100644 --- a/src/core/ext/filters/client_channel/http_connect_handshaker.cc +++ b/src/core/ext/filters/client_channel/http_connect_handshaker.cc @@ -33,151 +33,160 @@ #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/http/format_request.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/uri/uri_parser.h" -typedef struct http_connect_handshaker { - // Base class. Must be first. - grpc_handshaker base; +namespace grpc_core { - gpr_refcount refcount; - gpr_mu mu; +namespace { - bool shutdown; +class HttpConnectHandshaker : public Handshaker { + public: + HttpConnectHandshaker(); + void Shutdown(grpc_error* why) override; + void DoHandshake(grpc_tcp_server_acceptor* acceptor, + grpc_closure* on_handshake_done, + HandshakerArgs* args) override; + const char* name() const override { return "http_connect"; } + + private: + virtual ~HttpConnectHandshaker(); + void CleanupArgsForFailureLocked(); + void HandshakeFailedLocked(grpc_error* error); + static void OnWriteDone(void* arg, grpc_error* error); + static void OnReadDone(void* arg, grpc_error* error); + + gpr_mu mu_; + + bool is_shutdown_ = false; // Endpoint and read buffer to destroy after a shutdown. - grpc_endpoint* endpoint_to_destroy; - grpc_slice_buffer* read_buffer_to_destroy; + grpc_endpoint* endpoint_to_destroy_ = nullptr; + grpc_slice_buffer* read_buffer_to_destroy_ = nullptr; // State saved while performing the handshake. - grpc_handshaker_args* args; - grpc_closure* on_handshake_done; + HandshakerArgs* args_ = nullptr; + grpc_closure* on_handshake_done_ = nullptr; // Objects for processing the HTTP CONNECT request and response. - grpc_slice_buffer write_buffer; - grpc_closure request_done_closure; - grpc_closure response_read_closure; - grpc_http_parser http_parser; - grpc_http_response http_response; -} http_connect_handshaker; + grpc_slice_buffer write_buffer_; + grpc_closure request_done_closure_; + grpc_closure response_read_closure_; + grpc_http_parser http_parser_; + grpc_http_response http_response_; +}; -// Unref and clean up handshaker. -static void http_connect_handshaker_unref(http_connect_handshaker* handshaker) { - if (gpr_unref(&handshaker->refcount)) { - gpr_mu_destroy(&handshaker->mu); - if (handshaker->endpoint_to_destroy != nullptr) { - grpc_endpoint_destroy(handshaker->endpoint_to_destroy); - } - if (handshaker->read_buffer_to_destroy != nullptr) { - grpc_slice_buffer_destroy_internal(handshaker->read_buffer_to_destroy); - gpr_free(handshaker->read_buffer_to_destroy); - } - grpc_slice_buffer_destroy_internal(&handshaker->write_buffer); - grpc_http_parser_destroy(&handshaker->http_parser); - grpc_http_response_destroy(&handshaker->http_response); - gpr_free(handshaker); +HttpConnectHandshaker::~HttpConnectHandshaker() { + gpr_mu_destroy(&mu_); + if (endpoint_to_destroy_ != nullptr) { + grpc_endpoint_destroy(endpoint_to_destroy_); + } + if (read_buffer_to_destroy_ != nullptr) { + grpc_slice_buffer_destroy_internal(read_buffer_to_destroy_); + gpr_free(read_buffer_to_destroy_); } + grpc_slice_buffer_destroy_internal(&write_buffer_); + grpc_http_parser_destroy(&http_parser_); + grpc_http_response_destroy(&http_response_); } // Set args fields to nullptr, saving the endpoint and read buffer for // later destruction. -static void cleanup_args_for_failure_locked( - http_connect_handshaker* handshaker) { - handshaker->endpoint_to_destroy = handshaker->args->endpoint; - handshaker->args->endpoint = nullptr; - handshaker->read_buffer_to_destroy = handshaker->args->read_buffer; - handshaker->args->read_buffer = nullptr; - grpc_channel_args_destroy(handshaker->args->args); - handshaker->args->args = nullptr; +void HttpConnectHandshaker::CleanupArgsForFailureLocked() { + endpoint_to_destroy_ = args_->endpoint; + args_->endpoint = nullptr; + read_buffer_to_destroy_ = args_->read_buffer; + args_->read_buffer = nullptr; + grpc_channel_args_destroy(args_->args); + args_->args = nullptr; } // If the handshake failed or we're shutting down, clean up and invoke the // callback with the error. -static void handshake_failed_locked(http_connect_handshaker* handshaker, - grpc_error* error) { +void HttpConnectHandshaker::HandshakeFailedLocked(grpc_error* error) { if (error == GRPC_ERROR_NONE) { // If we were shut down after an endpoint operation succeeded but // before the endpoint callback was invoked, we need to generate our // own error. error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown"); } - if (!handshaker->shutdown) { + if (!is_shutdown_) { // TODO(ctiller): It is currently necessary to shutdown endpoints // before destroying them, even if we know that there are no // pending read/write callbacks. This should be fixed, at which // point this can be removed. - grpc_endpoint_shutdown(handshaker->args->endpoint, GRPC_ERROR_REF(error)); + grpc_endpoint_shutdown(args_->endpoint, GRPC_ERROR_REF(error)); // Not shutting down, so the handshake failed. Clean up before // invoking the callback. - cleanup_args_for_failure_locked(handshaker); + CleanupArgsForFailureLocked(); // Set shutdown to true so that subsequent calls to // http_connect_handshaker_shutdown() do nothing. - handshaker->shutdown = true; + is_shutdown_ = true; } // Invoke callback. - GRPC_CLOSURE_SCHED(handshaker->on_handshake_done, error); + GRPC_CLOSURE_SCHED(on_handshake_done_, error); } // Callback invoked when finished writing HTTP CONNECT request. -static void on_write_done(void* arg, grpc_error* error) { - http_connect_handshaker* handshaker = - static_cast(arg); - gpr_mu_lock(&handshaker->mu); - if (error != GRPC_ERROR_NONE || handshaker->shutdown) { +void HttpConnectHandshaker::OnWriteDone(void* arg, grpc_error* error) { + auto* handshaker = static_cast(arg); + gpr_mu_lock(&handshaker->mu_); + if (error != GRPC_ERROR_NONE || handshaker->is_shutdown_) { // If the write failed or we're shutting down, clean up and invoke the // callback with the error. - handshake_failed_locked(handshaker, GRPC_ERROR_REF(error)); - gpr_mu_unlock(&handshaker->mu); - http_connect_handshaker_unref(handshaker); + handshaker->HandshakeFailedLocked(GRPC_ERROR_REF(error)); + gpr_mu_unlock(&handshaker->mu_); + handshaker->Unref(); } else { // Otherwise, read the response. // The read callback inherits our ref to the handshaker. - grpc_endpoint_read(handshaker->args->endpoint, - handshaker->args->read_buffer, - &handshaker->response_read_closure); - gpr_mu_unlock(&handshaker->mu); + grpc_endpoint_read(handshaker->args_->endpoint, + handshaker->args_->read_buffer, + &handshaker->response_read_closure_); + gpr_mu_unlock(&handshaker->mu_); } } // Callback invoked for reading HTTP CONNECT response. -static void on_read_done(void* arg, grpc_error* error) { - http_connect_handshaker* handshaker = - static_cast(arg); - gpr_mu_lock(&handshaker->mu); - if (error != GRPC_ERROR_NONE || handshaker->shutdown) { +void HttpConnectHandshaker::OnReadDone(void* arg, grpc_error* error) { + auto* handshaker = static_cast(arg); + + gpr_mu_lock(&handshaker->mu_); + if (error != GRPC_ERROR_NONE || handshaker->is_shutdown_) { // If the read failed or we're shutting down, clean up and invoke the // callback with the error. - handshake_failed_locked(handshaker, GRPC_ERROR_REF(error)); + handshaker->HandshakeFailedLocked(GRPC_ERROR_REF(error)); goto done; } // Add buffer to parser. - for (size_t i = 0; i < handshaker->args->read_buffer->count; ++i) { - if (GRPC_SLICE_LENGTH(handshaker->args->read_buffer->slices[i]) > 0) { + for (size_t i = 0; i < handshaker->args_->read_buffer->count; ++i) { + if (GRPC_SLICE_LENGTH(handshaker->args_->read_buffer->slices[i]) > 0) { size_t body_start_offset = 0; - error = grpc_http_parser_parse(&handshaker->http_parser, - handshaker->args->read_buffer->slices[i], + error = grpc_http_parser_parse(&handshaker->http_parser_, + handshaker->args_->read_buffer->slices[i], &body_start_offset); if (error != GRPC_ERROR_NONE) { - handshake_failed_locked(handshaker, error); + handshaker->HandshakeFailedLocked(error); goto done; } - if (handshaker->http_parser.state == GRPC_HTTP_BODY) { + if (handshaker->http_parser_.state == GRPC_HTTP_BODY) { // Remove the data we've already read from the read buffer, // leaving only the leftover bytes (if any). grpc_slice_buffer tmp_buffer; grpc_slice_buffer_init(&tmp_buffer); if (body_start_offset < - GRPC_SLICE_LENGTH(handshaker->args->read_buffer->slices[i])) { + GRPC_SLICE_LENGTH(handshaker->args_->read_buffer->slices[i])) { grpc_slice_buffer_add( &tmp_buffer, - grpc_slice_split_tail(&handshaker->args->read_buffer->slices[i], + grpc_slice_split_tail(&handshaker->args_->read_buffer->slices[i], body_start_offset)); } grpc_slice_buffer_addn(&tmp_buffer, - &handshaker->args->read_buffer->slices[i + 1], - handshaker->args->read_buffer->count - i - 1); - grpc_slice_buffer_swap(handshaker->args->read_buffer, &tmp_buffer); + &handshaker->args_->read_buffer->slices[i + 1], + handshaker->args_->read_buffer->count - i - 1); + grpc_slice_buffer_swap(handshaker->args_->read_buffer, &tmp_buffer); grpc_slice_buffer_destroy_internal(&tmp_buffer); break; } @@ -194,64 +203,53 @@ static void on_read_done(void* arg, grpc_error* error) { // need to fix the HTTP parser to understand when the body is // complete (e.g., handling chunked transfer encoding or looking // at the Content-Length: header). - if (handshaker->http_parser.state != GRPC_HTTP_BODY) { - grpc_slice_buffer_reset_and_unref_internal(handshaker->args->read_buffer); - grpc_endpoint_read(handshaker->args->endpoint, - handshaker->args->read_buffer, - &handshaker->response_read_closure); - gpr_mu_unlock(&handshaker->mu); + if (handshaker->http_parser_.state != GRPC_HTTP_BODY) { + grpc_slice_buffer_reset_and_unref_internal(handshaker->args_->read_buffer); + grpc_endpoint_read(handshaker->args_->endpoint, + handshaker->args_->read_buffer, + &handshaker->response_read_closure_); + gpr_mu_unlock(&handshaker->mu_); return; } // Make sure we got a 2xx response. - if (handshaker->http_response.status < 200 || - handshaker->http_response.status >= 300) { + if (handshaker->http_response_.status < 200 || + handshaker->http_response_.status >= 300) { char* msg; gpr_asprintf(&msg, "HTTP proxy returned response code %d", - handshaker->http_response.status); + handshaker->http_response_.status); error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); - handshake_failed_locked(handshaker, error); + handshaker->HandshakeFailedLocked(error); goto done; } // Success. Invoke handshake-done callback. - GRPC_CLOSURE_SCHED(handshaker->on_handshake_done, error); + GRPC_CLOSURE_SCHED(handshaker->on_handshake_done_, error); done: // Set shutdown to true so that subsequent calls to // http_connect_handshaker_shutdown() do nothing. - handshaker->shutdown = true; - gpr_mu_unlock(&handshaker->mu); - http_connect_handshaker_unref(handshaker); + handshaker->is_shutdown_ = true; + gpr_mu_unlock(&handshaker->mu_); + handshaker->Unref(); } // // Public handshaker methods // -static void http_connect_handshaker_destroy(grpc_handshaker* handshaker_in) { - http_connect_handshaker* handshaker = - reinterpret_cast(handshaker_in); - http_connect_handshaker_unref(handshaker); -} - -static void http_connect_handshaker_shutdown(grpc_handshaker* handshaker_in, - grpc_error* why) { - http_connect_handshaker* handshaker = - reinterpret_cast(handshaker_in); - gpr_mu_lock(&handshaker->mu); - if (!handshaker->shutdown) { - handshaker->shutdown = true; - grpc_endpoint_shutdown(handshaker->args->endpoint, GRPC_ERROR_REF(why)); - cleanup_args_for_failure_locked(handshaker); +void HttpConnectHandshaker::Shutdown(grpc_error* why) { + gpr_mu_lock(&mu_); + if (!is_shutdown_) { + is_shutdown_ = true; + grpc_endpoint_shutdown(args_->endpoint, GRPC_ERROR_REF(why)); + CleanupArgsForFailureLocked(); } - gpr_mu_unlock(&handshaker->mu); + gpr_mu_unlock(&mu_); GRPC_ERROR_UNREF(why); } -static void http_connect_handshaker_do_handshake( - grpc_handshaker* handshaker_in, grpc_tcp_server_acceptor* acceptor, - grpc_closure* on_handshake_done, grpc_handshaker_args* args) { - http_connect_handshaker* handshaker = - reinterpret_cast(handshaker_in); +void HttpConnectHandshaker::DoHandshake(grpc_tcp_server_acceptor* acceptor, + grpc_closure* on_handshake_done, + HandshakerArgs* args) { // Check for HTTP CONNECT channel arg. // If not found, invoke on_handshake_done without doing anything. const grpc_arg* arg = @@ -260,9 +258,9 @@ static void http_connect_handshaker_do_handshake( if (server_name == nullptr) { // Set shutdown to true so that subsequent calls to // http_connect_handshaker_shutdown() do nothing. - gpr_mu_lock(&handshaker->mu); - handshaker->shutdown = true; - gpr_mu_unlock(&handshaker->mu); + gpr_mu_lock(&mu_); + is_shutdown_ = true; + gpr_mu_unlock(&mu_); GRPC_CLOSURE_SCHED(on_handshake_done, GRPC_ERROR_NONE); return; } @@ -280,6 +278,7 @@ static void http_connect_handshaker_do_handshake( gpr_malloc(sizeof(grpc_http_header) * num_header_strings)); for (size_t i = 0; i < num_header_strings; ++i) { char* sep = strchr(header_strings[i], ':'); + if (sep == nullptr) { gpr_log(GPR_ERROR, "skipping unparseable HTTP CONNECT header: %s", header_strings[i]); @@ -292,9 +291,9 @@ static void http_connect_handshaker_do_handshake( } } // Save state in the handshaker object. - gpr_mu_lock(&handshaker->mu); - handshaker->args = args; - handshaker->on_handshake_done = on_handshake_done; + MutexLock lock(&mu_); + args_ = args; + on_handshake_done_ = on_handshake_done; // Log connection via proxy. char* proxy_name = grpc_endpoint_get_peer(args->endpoint); gpr_log(GPR_INFO, "Connecting to server %s via HTTP proxy %s", server_name, @@ -302,15 +301,18 @@ static void http_connect_handshaker_do_handshake( gpr_free(proxy_name); // Construct HTTP CONNECT request. grpc_httpcli_request request; - memset(&request, 0, sizeof(request)); request.host = server_name; + request.ssl_host_override = nullptr; request.http.method = (char*)"CONNECT"; request.http.path = server_name; + request.http.version = GRPC_HTTP_HTTP10; // Set by OnReadDone request.http.hdrs = headers; request.http.hdr_count = num_headers; + request.http.body_length = 0; + request.http.body = nullptr; request.handshaker = &grpc_httpcli_plaintext; grpc_slice request_slice = grpc_httpcli_format_connect_request(&request); - grpc_slice_buffer_add(&handshaker->write_buffer, request_slice); + grpc_slice_buffer_add(&write_buffer_, request_slice); // Clean up. gpr_free(headers); for (size_t i = 0; i < num_header_strings; ++i) { @@ -318,54 +320,42 @@ static void http_connect_handshaker_do_handshake( } gpr_free(header_strings); // Take a new ref to be held by the write callback. - gpr_ref(&handshaker->refcount); - grpc_endpoint_write(args->endpoint, &handshaker->write_buffer, - &handshaker->request_done_closure, nullptr); - gpr_mu_unlock(&handshaker->mu); + Ref().release(); + grpc_endpoint_write(args->endpoint, &write_buffer_, &request_done_closure_, + nullptr); } -static const grpc_handshaker_vtable http_connect_handshaker_vtable = { - http_connect_handshaker_destroy, http_connect_handshaker_shutdown, - http_connect_handshaker_do_handshake, "http_connect"}; - -static grpc_handshaker* grpc_http_connect_handshaker_create() { - http_connect_handshaker* handshaker = - static_cast(gpr_malloc(sizeof(*handshaker))); - memset(handshaker, 0, sizeof(*handshaker)); - grpc_handshaker_init(&http_connect_handshaker_vtable, &handshaker->base); - gpr_mu_init(&handshaker->mu); - gpr_ref_init(&handshaker->refcount, 1); - grpc_slice_buffer_init(&handshaker->write_buffer); - GRPC_CLOSURE_INIT(&handshaker->request_done_closure, on_write_done, - handshaker, grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&handshaker->response_read_closure, on_read_done, - handshaker, grpc_schedule_on_exec_ctx); - grpc_http_parser_init(&handshaker->http_parser, GRPC_HTTP_RESPONSE, - &handshaker->http_response); - return &handshaker->base; +HttpConnectHandshaker::HttpConnectHandshaker() { + gpr_mu_init(&mu_); + grpc_slice_buffer_init(&write_buffer_); + GRPC_CLOSURE_INIT(&request_done_closure_, &HttpConnectHandshaker::OnWriteDone, + this, grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&response_read_closure_, &HttpConnectHandshaker::OnReadDone, + this, grpc_schedule_on_exec_ctx); + grpc_http_parser_init(&http_parser_, GRPC_HTTP_RESPONSE, &http_response_); } // // handshaker factory // -static void handshaker_factory_add_handshakers( - grpc_handshaker_factory* factory, const grpc_channel_args* args, - grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) { - grpc_handshake_manager_add(handshake_mgr, - grpc_http_connect_handshaker_create()); -} - -static void handshaker_factory_destroy(grpc_handshaker_factory* factory) {} +class HttpConnectHandshakerFactory : public HandshakerFactory { + public: + void AddHandshakers(const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr) override { + handshake_mgr->Add(MakeRefCounted()); + } + ~HttpConnectHandshakerFactory() override = default; +}; -static const grpc_handshaker_factory_vtable handshaker_factory_vtable = { - handshaker_factory_add_handshakers, handshaker_factory_destroy}; +} // namespace -static grpc_handshaker_factory handshaker_factory = { - &handshaker_factory_vtable}; +} // namespace grpc_core void grpc_http_connect_register_handshaker_factory() { - grpc_handshaker_factory_register(true /* at_start */, HANDSHAKER_CLIENT, - &handshaker_factory); + using namespace grpc_core; + HandshakerRegistry::RegisterHandshakerFactory( + true /* at_start */, HANDSHAKER_CLIENT, + UniquePtr(New())); } diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.cc b/src/core/ext/transport/chttp2/client/chttp2_connector.cc index 1e9a75d0630..c324c2c9243 100644 --- a/src/core/ext/transport/chttp2/client/chttp2_connector.cc +++ b/src/core/ext/transport/chttp2/client/chttp2_connector.cc @@ -55,7 +55,7 @@ typedef struct { grpc_closure connected; - grpc_handshake_manager* handshake_mgr; + grpc_core::RefCountedPtr handshake_mgr; } chttp2_connector; static void chttp2_connector_ref(grpc_connector* con) { @@ -79,7 +79,7 @@ static void chttp2_connector_shutdown(grpc_connector* con, grpc_error* why) { gpr_mu_lock(&c->mu); c->shutdown = true; if (c->handshake_mgr != nullptr) { - grpc_handshake_manager_shutdown(c->handshake_mgr, GRPC_ERROR_REF(why)); + c->handshake_mgr->Shutdown(GRPC_ERROR_REF(why)); } // If handshaking is not yet in progress, shutdown the endpoint. // Otherwise, the handshaker will do this for us. @@ -91,7 +91,7 @@ static void chttp2_connector_shutdown(grpc_connector* con, grpc_error* why) { } static void on_handshake_done(void* arg, grpc_error* error) { - grpc_handshaker_args* args = static_cast(arg); + auto* args = static_cast(arg); chttp2_connector* c = static_cast(args->user_data); gpr_mu_lock(&c->mu); if (error != GRPC_ERROR_NONE || c->shutdown) { @@ -152,20 +152,20 @@ static void on_handshake_done(void* arg, grpc_error* error) { grpc_closure* notify = c->notify; c->notify = nullptr; GRPC_CLOSURE_SCHED(notify, error); - grpc_handshake_manager_destroy(c->handshake_mgr); - c->handshake_mgr = nullptr; + c->handshake_mgr.reset(); gpr_mu_unlock(&c->mu); chttp2_connector_unref(reinterpret_cast(c)); } static void start_handshake_locked(chttp2_connector* c) { - c->handshake_mgr = grpc_handshake_manager_create(); - grpc_handshakers_add(HANDSHAKER_CLIENT, c->args.channel_args, - c->args.interested_parties, c->handshake_mgr); + c->handshake_mgr = grpc_core::MakeRefCounted(); + grpc_core::HandshakerRegistry::AddHandshakers( + grpc_core::HANDSHAKER_CLIENT, c->args.channel_args, + c->args.interested_parties, c->handshake_mgr.get()); grpc_endpoint_add_to_pollset_set(c->endpoint, c->args.interested_parties); - grpc_handshake_manager_do_handshake( - c->handshake_mgr, c->endpoint, c->args.channel_args, c->args.deadline, - nullptr /* acceptor */, on_handshake_done, c); + c->handshake_mgr->DoHandshake(c->endpoint, c->args.channel_args, + c->args.deadline, nullptr /* acceptor */, + on_handshake_done, c); c->endpoint = nullptr; // Endpoint handed off to handshake manager. } diff --git a/src/core/ext/transport/chttp2/server/chttp2_server.cc b/src/core/ext/transport/chttp2/server/chttp2_server.cc index 3d09187b9ba..040ea2044b1 100644 --- a/src/core/ext/transport/chttp2/server/chttp2_server.cc +++ b/src/core/ext/transport/chttp2/server/chttp2_server.cc @@ -54,7 +54,7 @@ typedef struct { bool shutdown; grpc_closure tcp_server_shutdown_complete; grpc_closure* server_destroy_listener_done; - grpc_handshake_manager* pending_handshake_mgrs; + grpc_core::HandshakeManager* pending_handshake_mgrs; grpc_core::RefCountedPtr channelz_listen_socket; } server_state; @@ -64,7 +64,7 @@ typedef struct { server_state* svr_state; grpc_pollset* accepting_pollset; grpc_tcp_server_acceptor* acceptor; - grpc_handshake_manager* handshake_mgr; + grpc_core::RefCountedPtr handshake_mgr; // State for enforcing handshake timeout on receiving HTTP/2 settings. grpc_chttp2_transport* transport; grpc_millis deadline; @@ -112,7 +112,7 @@ static void on_receive_settings(void* arg, grpc_error* error) { } static void on_handshake_done(void* arg, grpc_error* error) { - grpc_handshaker_args* args = static_cast(arg); + auto* args = static_cast(arg); server_connection_state* connection_state = static_cast(args->user_data); gpr_mu_lock(&connection_state->svr_state->mu); @@ -175,11 +175,10 @@ static void on_handshake_done(void* arg, grpc_error* error) { } } } - grpc_handshake_manager_pending_list_remove( - &connection_state->svr_state->pending_handshake_mgrs, - connection_state->handshake_mgr); + connection_state->handshake_mgr->RemoveFromPendingMgrList( + &connection_state->svr_state->pending_handshake_mgrs); gpr_mu_unlock(&connection_state->svr_state->mu); - grpc_handshake_manager_destroy(connection_state->handshake_mgr); + connection_state->handshake_mgr.reset(); gpr_free(connection_state->acceptor); grpc_tcp_server_unref(connection_state->svr_state->tcp_server); server_connection_state_unref(connection_state); @@ -211,9 +210,8 @@ static void on_accept(void* arg, grpc_endpoint* tcp, gpr_free(acceptor); return; } - grpc_handshake_manager* handshake_mgr = grpc_handshake_manager_create(); - grpc_handshake_manager_pending_list_add(&state->pending_handshake_mgrs, - handshake_mgr); + auto handshake_mgr = grpc_core::MakeRefCounted(); + handshake_mgr->AddToPendingMgrList(&state->pending_handshake_mgrs); grpc_tcp_server_ref(state->tcp_server); gpr_mu_unlock(&state->mu); server_connection_state* connection_state = @@ -227,19 +225,19 @@ static void on_accept(void* arg, grpc_endpoint* tcp, connection_state->interested_parties = grpc_pollset_set_create(); grpc_pollset_set_add_pollset(connection_state->interested_parties, connection_state->accepting_pollset); - grpc_handshakers_add(HANDSHAKER_SERVER, state->args, - connection_state->interested_parties, - connection_state->handshake_mgr); + grpc_core::HandshakerRegistry::AddHandshakers( + grpc_core::HANDSHAKER_SERVER, state->args, + connection_state->interested_parties, + connection_state->handshake_mgr.get()); const grpc_arg* timeout_arg = grpc_channel_args_find(state->args, GRPC_ARG_SERVER_HANDSHAKE_TIMEOUT_MS); connection_state->deadline = grpc_core::ExecCtx::Get()->Now() + grpc_channel_arg_get_integer(timeout_arg, {120 * GPR_MS_PER_SEC, 1, INT_MAX}); - grpc_handshake_manager_do_handshake(connection_state->handshake_mgr, tcp, - state->args, connection_state->deadline, - acceptor, on_handshake_done, - connection_state); + connection_state->handshake_mgr->DoHandshake( + tcp, state->args, connection_state->deadline, acceptor, on_handshake_done, + connection_state); } /* Server callback: start listening on our ports */ @@ -260,8 +258,9 @@ static void tcp_server_shutdown_complete(void* arg, grpc_error* error) { gpr_mu_lock(&state->mu); grpc_closure* destroy_done = state->server_destroy_listener_done; GPR_ASSERT(state->shutdown); - grpc_handshake_manager_pending_list_shutdown_all( - state->pending_handshake_mgrs, GRPC_ERROR_REF(error)); + if (state->pending_handshake_mgrs != nullptr) { + state->pending_handshake_mgrs->ShutdownAllPending(GRPC_ERROR_REF(error)); + } state->channelz_listen_socket.reset(); gpr_mu_unlock(&state->mu); // Flush queued work before destroying handshaker factory, since that diff --git a/src/core/lib/channel/handshaker.cc b/src/core/lib/channel/handshaker.cc index e516b56b743..6bb05cee24e 100644 --- a/src/core/lib/channel/handshaker.cc +++ b/src/core/lib/channel/handshaker.cc @@ -30,302 +30,229 @@ #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/slice/slice_internal.h" -grpc_core::TraceFlag grpc_handshaker_trace(false, "handshaker"); +namespace grpc_core { -// -// grpc_handshaker -// +TraceFlag grpc_handshaker_trace(false, "handshaker"); -void grpc_handshaker_init(const grpc_handshaker_vtable* vtable, - grpc_handshaker* handshaker) { - handshaker->vtable = vtable; -} - -void grpc_handshaker_destroy(grpc_handshaker* handshaker) { - handshaker->vtable->destroy(handshaker); -} - -void grpc_handshaker_shutdown(grpc_handshaker* handshaker, grpc_error* why) { - handshaker->vtable->shutdown(handshaker, why); -} - -void grpc_handshaker_do_handshake(grpc_handshaker* handshaker, - grpc_tcp_server_acceptor* acceptor, - grpc_closure* on_handshake_done, - grpc_handshaker_args* args) { - handshaker->vtable->do_handshake(handshaker, acceptor, on_handshake_done, - args); -} +namespace { -const char* grpc_handshaker_name(grpc_handshaker* handshaker) { - return handshaker->vtable->name; +char* HandshakerArgsString(HandshakerArgs* args) { + char* args_str = grpc_channel_args_string(args->args); + size_t num_args = args->args != nullptr ? args->args->num_args : 0; + size_t read_buffer_length = + args->read_buffer != nullptr ? args->read_buffer->length : 0; + char* str; + gpr_asprintf(&str, + "{endpoint=%p, args=%p {size=%" PRIuPTR + ": %s}, read_buffer=%p (length=%" PRIuPTR "), exit_early=%d}", + args->endpoint, args->args, num_args, args_str, + args->read_buffer, read_buffer_length, args->exit_early); + gpr_free(args_str); + return str; } -// -// grpc_handshake_manager -// +} // namespace -struct grpc_handshake_manager { - gpr_mu mu; - gpr_refcount refs; - bool shutdown; - // An array of handshakers added via grpc_handshake_manager_add(). - size_t count; - grpc_handshaker** handshakers; - // The index of the handshaker to invoke next and closure to invoke it. - size_t index; - grpc_closure call_next_handshaker; - // The acceptor to call the handshakers with. - grpc_tcp_server_acceptor* acceptor; - // Deadline timer across all handshakers. - grpc_timer deadline_timer; - grpc_closure on_timeout; - // The final callback and user_data to invoke after the last handshaker. - grpc_closure on_handshake_done; - void* user_data; - // Handshaker args. - grpc_handshaker_args args; - // Links to the previous and next managers in a list of all pending handshakes - // Used at server side only. - grpc_handshake_manager* prev; - grpc_handshake_manager* next; -}; +HandshakeManager::HandshakeManager() { gpr_mu_init(&mu_); } -grpc_handshake_manager* grpc_handshake_manager_create() { - grpc_handshake_manager* mgr = static_cast( - gpr_zalloc(sizeof(grpc_handshake_manager))); - gpr_mu_init(&mgr->mu); - gpr_ref_init(&mgr->refs, 1); - return mgr; -} - -void grpc_handshake_manager_pending_list_add(grpc_handshake_manager** head, - grpc_handshake_manager* mgr) { - GPR_ASSERT(mgr->prev == nullptr); - GPR_ASSERT(mgr->next == nullptr); - mgr->next = *head; +/// Add \a mgr to the server side list of all pending handshake managers, the +/// list starts with \a *head. +// Not thread-safe. Caller needs to synchronize. +void HandshakeManager::AddToPendingMgrList(HandshakeManager** head) { + GPR_ASSERT(prev_ == nullptr); + GPR_ASSERT(next_ == nullptr); + next_ = *head; if (*head) { - (*head)->prev = mgr; + (*head)->prev_ = this; } - *head = mgr; + *head = this; } -void grpc_handshake_manager_pending_list_remove(grpc_handshake_manager** head, - grpc_handshake_manager* mgr) { - if (mgr->next != nullptr) { - mgr->next->prev = mgr->prev; +/// Remove \a mgr from the server side list of all pending handshake managers. +// Not thread-safe. Caller needs to synchronize. +void HandshakeManager::RemoveFromPendingMgrList(HandshakeManager** head) { + if (next_ != nullptr) { + next_->prev_ = prev_; } - if (mgr->prev != nullptr) { - mgr->prev->next = mgr->next; + if (prev_ != nullptr) { + prev_->next_ = next_; } else { - GPR_ASSERT(*head == mgr); - *head = mgr->next; + GPR_ASSERT(*head == this); + *head = next_; } } -void grpc_handshake_manager_pending_list_shutdown_all( - grpc_handshake_manager* head, grpc_error* why) { +/// Shutdown all pending handshake managers starting at head on the server +/// side. Not thread-safe. Caller needs to synchronize. +void HandshakeManager::ShutdownAllPending(grpc_error* why) { + auto* head = this; while (head != nullptr) { - grpc_handshake_manager_shutdown(head, GRPC_ERROR_REF(why)); - head = head->next; + head->Shutdown(GRPC_ERROR_REF(why)); + head = head->next_; } GRPC_ERROR_UNREF(why); } -static bool is_power_of_2(size_t n) { return (n & (n - 1)) == 0; } - -void grpc_handshake_manager_add(grpc_handshake_manager* mgr, - grpc_handshaker* handshaker) { +void HandshakeManager::Add(RefCountedPtr handshaker) { if (grpc_handshaker_trace.enabled()) { gpr_log( GPR_INFO, "handshake_manager %p: adding handshaker %s [%p] at index %" PRIuPTR, - mgr, grpc_handshaker_name(handshaker), handshaker, mgr->count); - } - gpr_mu_lock(&mgr->mu); - // To avoid allocating memory for each handshaker we add, we double - // the number of elements every time we need more. - size_t realloc_count = 0; - if (mgr->count == 0) { - realloc_count = 2; - } else if (mgr->count >= 2 && is_power_of_2(mgr->count)) { - realloc_count = mgr->count * 2; - } - if (realloc_count > 0) { - mgr->handshakers = static_cast(gpr_realloc( - mgr->handshakers, realloc_count * sizeof(grpc_handshaker*))); + this, handshaker->name(), handshaker.get(), handshakers_.size()); } - mgr->handshakers[mgr->count++] = handshaker; - gpr_mu_unlock(&mgr->mu); + MutexLock lock(&mu_); + handshakers_.push_back(std::move(handshaker)); } -static void grpc_handshake_manager_unref(grpc_handshake_manager* mgr) { - if (gpr_unref(&mgr->refs)) { - for (size_t i = 0; i < mgr->count; ++i) { - grpc_handshaker_destroy(mgr->handshakers[i]); - } - gpr_free(mgr->handshakers); - gpr_mu_destroy(&mgr->mu); - gpr_free(mgr); - } -} - -void grpc_handshake_manager_destroy(grpc_handshake_manager* mgr) { - grpc_handshake_manager_unref(mgr); +HandshakeManager::~HandshakeManager() { + handshakers_.clear(); + gpr_mu_destroy(&mu_); } -void grpc_handshake_manager_shutdown(grpc_handshake_manager* mgr, - grpc_error* why) { - gpr_mu_lock(&mgr->mu); - // Shutdown the handshaker that's currently in progress, if any. - if (!mgr->shutdown && mgr->index > 0) { - mgr->shutdown = true; - grpc_handshaker_shutdown(mgr->handshakers[mgr->index - 1], - GRPC_ERROR_REF(why)); +void HandshakeManager::Shutdown(grpc_error* why) { + { + MutexLock lock(&mu_); + // Shutdown the handshaker that's currently in progress, if any. + if (!is_shutdown_ && index_ > 0) { + is_shutdown_ = true; + handshakers_[index_ - 1]->Shutdown(GRPC_ERROR_REF(why)); + } } - gpr_mu_unlock(&mgr->mu); GRPC_ERROR_UNREF(why); } -static char* handshaker_args_string(grpc_handshaker_args* args) { - char* args_str = grpc_channel_args_string(args->args); - size_t num_args = args->args != nullptr ? args->args->num_args : 0; - size_t read_buffer_length = - args->read_buffer != nullptr ? args->read_buffer->length : 0; - char* str; - gpr_asprintf(&str, - "{endpoint=%p, args=%p {size=%" PRIuPTR - ": %s}, read_buffer=%p (length=%" PRIuPTR "), exit_early=%d}", - args->endpoint, args->args, num_args, args_str, - args->read_buffer, read_buffer_length, args->exit_early); - gpr_free(args_str); - return str; -} - // Helper function to call either the next handshaker or the // on_handshake_done callback. // Returns true if we've scheduled the on_handshake_done callback. -static bool call_next_handshaker_locked(grpc_handshake_manager* mgr, - grpc_error* error) { +bool HandshakeManager::CallNextHandshakerLocked(grpc_error* error) { if (grpc_handshaker_trace.enabled()) { - char* args_str = handshaker_args_string(&mgr->args); + char* args_str = HandshakerArgsString(&args_); gpr_log(GPR_INFO, "handshake_manager %p: error=%s shutdown=%d index=%" PRIuPTR ", args=%s", - mgr, grpc_error_string(error), mgr->shutdown, mgr->index, args_str); + this, grpc_error_string(error), is_shutdown_, index_, args_str); gpr_free(args_str); } - GPR_ASSERT(mgr->index <= mgr->count); + GPR_ASSERT(index_ <= handshakers_.size()); // If we got an error or we've been shut down or we're exiting early or // we've finished the last handshaker, invoke the on_handshake_done // callback. Otherwise, call the next handshaker. - if (error != GRPC_ERROR_NONE || mgr->shutdown || mgr->args.exit_early || - mgr->index == mgr->count) { - if (error == GRPC_ERROR_NONE && mgr->shutdown) { + if (error != GRPC_ERROR_NONE || is_shutdown_ || args_.exit_early || + index_ == handshakers_.size()) { + if (error == GRPC_ERROR_NONE && is_shutdown_) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("handshaker shutdown"); // It is possible that the endpoint has already been destroyed by // a shutdown call while this callback was sitting on the ExecCtx // with no error. - if (mgr->args.endpoint != nullptr) { + if (args_.endpoint != nullptr) { // TODO(roth): It is currently necessary to shutdown endpoints // before destroying then, even when we know that there are no // pending read/write callbacks. This should be fixed, at which // point this can be removed. - grpc_endpoint_shutdown(mgr->args.endpoint, GRPC_ERROR_REF(error)); - grpc_endpoint_destroy(mgr->args.endpoint); - mgr->args.endpoint = nullptr; - grpc_channel_args_destroy(mgr->args.args); - mgr->args.args = nullptr; - grpc_slice_buffer_destroy_internal(mgr->args.read_buffer); - gpr_free(mgr->args.read_buffer); - mgr->args.read_buffer = nullptr; + grpc_endpoint_shutdown(args_.endpoint, GRPC_ERROR_REF(error)); + grpc_endpoint_destroy(args_.endpoint); + args_.endpoint = nullptr; + grpc_channel_args_destroy(args_.args); + args_.args = nullptr; + grpc_slice_buffer_destroy_internal(args_.read_buffer); + gpr_free(args_.read_buffer); + args_.read_buffer = nullptr; } } if (grpc_handshaker_trace.enabled()) { gpr_log(GPR_INFO, "handshake_manager %p: handshaking complete -- scheduling " "on_handshake_done with error=%s", - mgr, grpc_error_string(error)); + this, grpc_error_string(error)); } // Cancel deadline timer, since we're invoking the on_handshake_done // callback now. - grpc_timer_cancel(&mgr->deadline_timer); - GRPC_CLOSURE_SCHED(&mgr->on_handshake_done, error); - mgr->shutdown = true; + grpc_timer_cancel(&deadline_timer_); + GRPC_CLOSURE_SCHED(&on_handshake_done_, error); + is_shutdown_ = true; } else { + auto handshaker = handshakers_[index_]; if (grpc_handshaker_trace.enabled()) { gpr_log( GPR_INFO, "handshake_manager %p: calling handshaker %s [%p] at index %" PRIuPTR, - mgr, grpc_handshaker_name(mgr->handshakers[mgr->index]), - mgr->handshakers[mgr->index], mgr->index); + this, handshaker->name(), handshaker.get(), index_); } - grpc_handshaker_do_handshake(mgr->handshakers[mgr->index], mgr->acceptor, - &mgr->call_next_handshaker, &mgr->args); + handshaker->DoHandshake(acceptor_, &call_next_handshaker_, &args_); } - ++mgr->index; - return mgr->shutdown; + ++index_; + return is_shutdown_; } -// A function used as the handshaker-done callback when chaining -// handshakers together. -static void call_next_handshaker(void* arg, grpc_error* error) { - grpc_handshake_manager* mgr = static_cast(arg); - gpr_mu_lock(&mgr->mu); - bool done = call_next_handshaker_locked(mgr, GRPC_ERROR_REF(error)); - gpr_mu_unlock(&mgr->mu); +void HandshakeManager::CallNextHandshakerFn(void* arg, grpc_error* error) { + auto* mgr = static_cast(arg); + bool done; + { + MutexLock lock(&mgr->mu_); + done = mgr->CallNextHandshakerLocked(GRPC_ERROR_REF(error)); + } // If we're invoked the final callback, we won't be coming back // to this function, so we can release our reference to the // handshake manager. if (done) { - grpc_handshake_manager_unref(mgr); + mgr->Unref(); } } -// Callback invoked when deadline is exceeded. -static void on_timeout(void* arg, grpc_error* error) { - grpc_handshake_manager* mgr = static_cast(arg); - if (error == GRPC_ERROR_NONE) { // Timer fired, rather than being cancelled. - grpc_handshake_manager_shutdown( - mgr, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake timed out")); +void HandshakeManager::OnTimeoutFn(void* arg, grpc_error* error) { + auto* mgr = static_cast(arg); + if (error == GRPC_ERROR_NONE) { // Timer fired, rather than being cancelled + mgr->Shutdown(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake timed out")); } - grpc_handshake_manager_unref(mgr); + mgr->Unref(); } -void grpc_handshake_manager_do_handshake(grpc_handshake_manager* mgr, - grpc_endpoint* endpoint, - const grpc_channel_args* channel_args, - grpc_millis deadline, - grpc_tcp_server_acceptor* acceptor, - grpc_iomgr_cb_func on_handshake_done, - void* user_data) { - gpr_mu_lock(&mgr->mu); - GPR_ASSERT(mgr->index == 0); - GPR_ASSERT(!mgr->shutdown); - // Construct handshaker args. These will be passed through all - // handshakers and eventually be freed by the on_handshake_done callback. - mgr->args.endpoint = endpoint; - mgr->args.args = grpc_channel_args_copy(channel_args); - mgr->args.user_data = user_data; - mgr->args.read_buffer = static_cast( - gpr_malloc(sizeof(*mgr->args.read_buffer))); - grpc_slice_buffer_init(mgr->args.read_buffer); - // Initialize state needed for calling handshakers. - mgr->acceptor = acceptor; - GRPC_CLOSURE_INIT(&mgr->call_next_handshaker, call_next_handshaker, mgr, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&mgr->on_handshake_done, on_handshake_done, &mgr->args, - grpc_schedule_on_exec_ctx); - // Start deadline timer, which owns a ref. - gpr_ref(&mgr->refs); - GRPC_CLOSURE_INIT(&mgr->on_timeout, on_timeout, mgr, - grpc_schedule_on_exec_ctx); - grpc_timer_init(&mgr->deadline_timer, deadline, &mgr->on_timeout); - // Start first handshaker, which also owns a ref. - gpr_ref(&mgr->refs); - bool done = call_next_handshaker_locked(mgr, GRPC_ERROR_NONE); - gpr_mu_unlock(&mgr->mu); +void HandshakeManager::DoHandshake(grpc_endpoint* endpoint, + const grpc_channel_args* channel_args, + grpc_millis deadline, + grpc_tcp_server_acceptor* acceptor, + grpc_iomgr_cb_func on_handshake_done, + void* user_data) { + bool done; + { + MutexLock lock(&mu_); + GPR_ASSERT(index_ == 0); + GPR_ASSERT(!is_shutdown_); + // Construct handshaker args. These will be passed through all + // handshakers and eventually be freed by the on_handshake_done callback. + args_.endpoint = endpoint; + args_.args = grpc_channel_args_copy(channel_args); + args_.user_data = user_data; + args_.read_buffer = + static_cast(gpr_malloc(sizeof(*args_.read_buffer))); + grpc_slice_buffer_init(args_.read_buffer); + // Initialize state needed for calling handshakers. + acceptor_ = acceptor; + GRPC_CLOSURE_INIT(&call_next_handshaker_, + &HandshakeManager::CallNextHandshakerFn, this, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&on_handshake_done_, on_handshake_done, &args_, + grpc_schedule_on_exec_ctx); + // Start deadline timer, which owns a ref. + Ref().release(); + GRPC_CLOSURE_INIT(&on_timeout_, &HandshakeManager::OnTimeoutFn, this, + grpc_schedule_on_exec_ctx); + grpc_timer_init(&deadline_timer_, deadline, &on_timeout_); + // Start first handshaker, which also owns a ref. + Ref().release(); + done = CallNextHandshakerLocked(GRPC_ERROR_NONE); + } if (done) { - grpc_handshake_manager_unref(mgr); + Unref(); } } + +} // namespace grpc_core + +void grpc_handshake_manager_add(grpc_handshake_manager* mgr, + grpc_handshaker* handshaker) { + // This is a transition method to aid the API change for handshakers. + using namespace grpc_core; + RefCountedPtr refd_hs(static_cast(handshaker)); + mgr->Add(refd_hs); +} diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h index a65990fceb4..912d524c8db 100644 --- a/src/core/lib/channel/handshaker.h +++ b/src/core/lib/channel/handshaker.h @@ -21,12 +21,21 @@ #include +#include + #include +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/tcp_server.h" +#include "src/core/lib/iomgr/timer.h" + +namespace grpc_core { /// Handshakers are used to perform initial handshakes on a connection /// before the client sends the initial request. Some examples of what @@ -35,12 +44,6 @@ /// /// In general, handshakers should be used via a handshake manager. -/// -/// grpc_handshaker -/// - -typedef struct grpc_handshaker grpc_handshaker; - /// Arguments passed through handshakers and to the on_handshake_done callback. /// /// For handshakers, all members are input/output parameters; for @@ -55,115 +58,121 @@ typedef struct grpc_handshaker grpc_handshaker; /// /// For the on_handshake_done callback, all members are input arguments, /// which the callback takes ownership of. -typedef struct { - grpc_endpoint* endpoint; - grpc_channel_args* args; - grpc_slice_buffer* read_buffer; +struct HandshakerArgs { + grpc_endpoint* endpoint = nullptr; + grpc_channel_args* args = nullptr; + grpc_slice_buffer* read_buffer = nullptr; // A handshaker may set this to true before invoking on_handshake_done // to indicate that subsequent handshakers should be skipped. - bool exit_early; + bool exit_early = false; // User data passed through the handshake manager. Not used by // individual handshakers. - void* user_data; -} grpc_handshaker_args; + void* user_data = nullptr; +}; -typedef struct { - /// Destroys the handshaker. - void (*destroy)(grpc_handshaker* handshaker); +/// +/// Handshaker +/// - /// Shuts down the handshaker (e.g., to clean up when the operation is - /// aborted in the middle). - void (*shutdown)(grpc_handshaker* handshaker, grpc_error* why); - - /// Performs handshaking, modifying \a args as needed (e.g., to - /// replace \a endpoint with a wrapped endpoint). - /// When finished, invokes \a on_handshake_done. - /// \a acceptor will be NULL for client-side handshakers. - void (*do_handshake)(grpc_handshaker* handshaker, - grpc_tcp_server_acceptor* acceptor, - grpc_closure* on_handshake_done, - grpc_handshaker_args* args); - - /// The name of the handshaker, for debugging purposes. - const char* name; -} grpc_handshaker_vtable; - -/// Base struct. To subclass, make this the first member of the -/// implementation struct. -struct grpc_handshaker { - const grpc_handshaker_vtable* vtable; +class Handshaker : public RefCounted { + public: + virtual ~Handshaker() = default; + virtual void Shutdown(grpc_error* why) GRPC_ABSTRACT; + virtual void DoHandshake(grpc_tcp_server_acceptor* acceptor, + grpc_closure* on_handshake_done, + HandshakerArgs* args) GRPC_ABSTRACT; + virtual const char* name() const GRPC_ABSTRACT; + GRPC_ABSTRACT_BASE_CLASS }; -/// Called by concrete implementations to initialize the base struct. -void grpc_handshaker_init(const grpc_handshaker_vtable* vtable, - grpc_handshaker* handshaker); +// +// HandshakeManager +// -void grpc_handshaker_destroy(grpc_handshaker* handshaker); -void grpc_handshaker_shutdown(grpc_handshaker* handshaker, grpc_error* why); -void grpc_handshaker_do_handshake(grpc_handshaker* handshaker, - grpc_tcp_server_acceptor* acceptor, - grpc_closure* on_handshake_done, - grpc_handshaker_args* args); -const char* grpc_handshaker_name(grpc_handshaker* handshaker); +class HandshakeManager : public RefCounted { + public: + HandshakeManager(); + ~HandshakeManager(); -/// -/// grpc_handshake_manager -/// + /// Add \a mgr to the server side list of all pending handshake managers, the + /// list starts with \a *head. + // Not thread-safe. Caller needs to synchronize. + void AddToPendingMgrList(HandshakeManager** head); + + /// Remove \a mgr from the server side list of all pending handshake managers. + // Not thread-safe. Caller needs to synchronize. + void RemoveFromPendingMgrList(HandshakeManager** head); -typedef struct grpc_handshake_manager grpc_handshake_manager; + /// Shutdown all pending handshake managers starting at head on the server + /// side. Not thread-safe. Caller needs to synchronize. + void ShutdownAllPending(grpc_error* why); -/// Creates a new handshake manager. Caller takes ownership. -grpc_handshake_manager* grpc_handshake_manager_create(); + /// Adds a handshaker to the handshake manager. + /// Takes ownership of \a handshaker. + void Add(RefCountedPtr handshaker); -/// Adds a handshaker to the handshake manager. -/// Takes ownership of \a handshaker. + /// Shuts down the handshake manager (e.g., to clean up when the operation is + /// aborted in the middle). + void Shutdown(grpc_error* why); + + /// Invokes handshakers in the order they were added. + /// Takes ownership of \a endpoint, and then passes that ownership to + /// the \a on_handshake_done callback. + /// Does NOT take ownership of \a channel_args. Instead, makes a copy before + /// invoking the first handshaker. + /// \a acceptor will be nullptr for client-side handshakers. + /// + /// When done, invokes \a on_handshake_done with a HandshakerArgs + /// object as its argument. If the callback is invoked with error != + /// GRPC_ERROR_NONE, then handshaking failed and the handshaker has done + /// the necessary clean-up. Otherwise, the callback takes ownership of + /// the arguments. + void DoHandshake(grpc_endpoint* endpoint, + const grpc_channel_args* channel_args, grpc_millis deadline, + grpc_tcp_server_acceptor* acceptor, + grpc_iomgr_cb_func on_handshake_done, void* user_data); + + private: + bool CallNextHandshakerLocked(grpc_error* error); + + // A function used as the handshaker-done callback when chaining + // handshakers together. + static void CallNextHandshakerFn(void* arg, grpc_error* error); + + // Callback invoked when deadline is exceeded. + static void OnTimeoutFn(void* arg, grpc_error* error); + + static const size_t HANDSHAKERS_INIT_SIZE = 2; + + gpr_mu mu_; + bool is_shutdown_ = false; + // An array of handshakers added via grpc_handshake_manager_add(). + InlinedVector, HANDSHAKERS_INIT_SIZE> handshakers_; + // The index of the handshaker to invoke next and closure to invoke it. + size_t index_ = 0; + grpc_closure call_next_handshaker_; + // The acceptor to call the handshakers with. + grpc_tcp_server_acceptor* acceptor_; + // Deadline timer across all handshakers. + grpc_timer deadline_timer_; + grpc_closure on_timeout_; + // The final callback and user_data to invoke after the last handshaker. + grpc_closure on_handshake_done_; + // Handshaker args. + HandshakerArgs args_; + // Links to the previous and next managers in a list of all pending handshakes + // Used at server side only. + HandshakeManager* prev_ = nullptr; + HandshakeManager* next_ = nullptr; +}; + +} // namespace grpc_core + +// TODO(arjunroy): These are transitional to account for the new handshaker API +// and will eventually be removed entirely. +typedef grpc_core::HandshakeManager grpc_handshake_manager; +typedef grpc_core::Handshaker grpc_handshaker; void grpc_handshake_manager_add(grpc_handshake_manager* mgr, grpc_handshaker* handshaker); -/// Destroys the handshake manager. -void grpc_handshake_manager_destroy(grpc_handshake_manager* mgr); - -/// Shuts down the handshake manager (e.g., to clean up when the operation is -/// aborted in the middle). -/// The caller must still call grpc_handshake_manager_destroy() after -/// calling this function. -void grpc_handshake_manager_shutdown(grpc_handshake_manager* mgr, - grpc_error* why); - -/// Invokes handshakers in the order they were added. -/// Takes ownership of \a endpoint, and then passes that ownership to -/// the \a on_handshake_done callback. -/// Does NOT take ownership of \a channel_args. Instead, makes a copy before -/// invoking the first handshaker. -/// \a acceptor will be nullptr for client-side handshakers. -/// -/// When done, invokes \a on_handshake_done with a grpc_handshaker_args -/// object as its argument. If the callback is invoked with error != -/// GRPC_ERROR_NONE, then handshaking failed and the handshaker has done -/// the necessary clean-up. Otherwise, the callback takes ownership of -/// the arguments. -void grpc_handshake_manager_do_handshake(grpc_handshake_manager* mgr, - grpc_endpoint* endpoint, - const grpc_channel_args* channel_args, - grpc_millis deadline, - grpc_tcp_server_acceptor* acceptor, - grpc_iomgr_cb_func on_handshake_done, - void* user_data); - -/// Add \a mgr to the server side list of all pending handshake managers, the -/// list starts with \a *head. -// Not thread-safe. Caller needs to synchronize. -void grpc_handshake_manager_pending_list_add(grpc_handshake_manager** head, - grpc_handshake_manager* mgr); - -/// Remove \a mgr from the server side list of all pending handshake managers. -// Not thread-safe. Caller needs to synchronize. -void grpc_handshake_manager_pending_list_remove(grpc_handshake_manager** head, - grpc_handshake_manager* mgr); - -/// Shutdown all pending handshake managers on the server side. -// Not thread-safe. Caller needs to synchronize. -void grpc_handshake_manager_pending_list_shutdown_all( - grpc_handshake_manager* head, grpc_error* why); - #endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H */ diff --git a/src/core/lib/channel/handshaker_factory.cc b/src/core/lib/channel/handshaker_factory.cc deleted file mode 100644 index 8ade8fe4e23..00000000000 --- a/src/core/lib/channel/handshaker_factory.cc +++ /dev/null @@ -1,42 +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. - * - */ - -#include - -#include "src/core/lib/channel/handshaker_factory.h" - -#include - -void grpc_handshaker_factory_add_handshakers( - grpc_handshaker_factory* handshaker_factory, const grpc_channel_args* args, - grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) { - if (handshaker_factory != nullptr) { - GPR_ASSERT(handshaker_factory->vtable != nullptr); - handshaker_factory->vtable->add_handshakers( - handshaker_factory, args, interested_parties, handshake_mgr); - } -} - -void grpc_handshaker_factory_destroy( - grpc_handshaker_factory* handshaker_factory) { - if (handshaker_factory != nullptr) { - GPR_ASSERT(handshaker_factory->vtable != nullptr); - handshaker_factory->vtable->destroy(handshaker_factory); - } -} diff --git a/src/core/lib/channel/handshaker_factory.h b/src/core/lib/channel/handshaker_factory.h index e17a6781798..3972af1f439 100644 --- a/src/core/lib/channel/handshaker_factory.h +++ b/src/core/lib/channel/handshaker_factory.h @@ -27,26 +27,18 @@ // A handshaker factory is used to create handshakers. -typedef struct grpc_handshaker_factory grpc_handshaker_factory; - -typedef struct { - void (*add_handshakers)(grpc_handshaker_factory* handshaker_factory, - const grpc_channel_args* args, - grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr); - void (*destroy)(grpc_handshaker_factory* handshaker_factory); -} grpc_handshaker_factory_vtable; - -struct grpc_handshaker_factory { - const grpc_handshaker_factory_vtable* vtable; -}; +namespace grpc_core { + +class HandshakerFactory { + public: + virtual void AddHandshakers(const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr) GRPC_ABSTRACT; + virtual ~HandshakerFactory() = default; -void grpc_handshaker_factory_add_handshakers( - grpc_handshaker_factory* handshaker_factory, const grpc_channel_args* args, - grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr); + GRPC_ABSTRACT_BASE_CLASS +}; -void grpc_handshaker_factory_destroy( - grpc_handshaker_factory* handshaker_factory); +} // namespace grpc_core #endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_FACTORY_H */ diff --git a/src/core/lib/channel/handshaker_registry.cc b/src/core/lib/channel/handshaker_registry.cc index fbafc43e795..b65129a6ed6 100644 --- a/src/core/lib/channel/handshaker_registry.cc +++ b/src/core/lib/channel/handshaker_registry.cc @@ -19,8 +19,11 @@ #include #include "src/core/lib/channel/handshaker_registry.h" +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/memory.h" #include +#include #include @@ -28,74 +31,83 @@ // grpc_handshaker_factory_list // -typedef struct { - grpc_handshaker_factory** list; - size_t num_factories; -} grpc_handshaker_factory_list; - -static void grpc_handshaker_factory_list_register( - grpc_handshaker_factory_list* list, bool at_start, - grpc_handshaker_factory* factory) { - list->list = static_cast(gpr_realloc( - list->list, - (list->num_factories + 1) * sizeof(grpc_handshaker_factory*))); - if (at_start) { - memmove(list->list + 1, list->list, - sizeof(grpc_handshaker_factory*) * list->num_factories); - list->list[0] = factory; - } else { - list->list[list->num_factories] = factory; - } - ++list->num_factories; -} +namespace grpc_core { + +namespace { + +class HandshakerFactoryList { + public: + void Register(bool at_start, UniquePtr factory); + void AddHandshakers(const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr); + + private: + InlinedVector, 2> factories_; +}; -static void grpc_handshaker_factory_list_add_handshakers( - grpc_handshaker_factory_list* list, const grpc_channel_args* args, - grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) { - for (size_t i = 0; i < list->num_factories; ++i) { - grpc_handshaker_factory_add_handshakers(list->list[i], args, - interested_parties, handshake_mgr); +HandshakerFactoryList* g_handshaker_factory_lists = nullptr; + +} // namespace + +void HandshakerFactoryList::Register(bool at_start, + UniquePtr factory) { + factories_.push_back(std::move(factory)); + if (at_start) { + auto* end = &factories_[factories_.size() - 1]; + std::rotate(&factories_[0], end, end + 1); } } -static void grpc_handshaker_factory_list_destroy( - grpc_handshaker_factory_list* list) { - for (size_t i = 0; i < list->num_factories; ++i) { - grpc_handshaker_factory_destroy(list->list[i]); +void HandshakerFactoryList::AddHandshakers(const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr) { + for (size_t idx = 0; idx < factories_.size(); ++idx) { + auto& handshaker_factory = factories_[idx]; + handshaker_factory->AddHandshakers(args, interested_parties, handshake_mgr); } - gpr_free(list->list); } // // plugin // -static grpc_handshaker_factory_list - g_handshaker_factory_lists[NUM_HANDSHAKER_TYPES]; - -void grpc_handshaker_factory_registry_init() { - memset(g_handshaker_factory_lists, 0, sizeof(g_handshaker_factory_lists)); +void HandshakerRegistry::Init() { + GPR_ASSERT(g_handshaker_factory_lists == nullptr); + g_handshaker_factory_lists = static_cast( + gpr_malloc(sizeof(*g_handshaker_factory_lists) * NUM_HANDSHAKER_TYPES)); + GPR_ASSERT(g_handshaker_factory_lists != nullptr); + for (auto idx = 0; idx < NUM_HANDSHAKER_TYPES; ++idx) { + auto factory_list = g_handshaker_factory_lists + idx; + new (factory_list) HandshakerFactoryList(); + } } -void grpc_handshaker_factory_registry_shutdown() { - for (size_t i = 0; i < NUM_HANDSHAKER_TYPES; ++i) { - grpc_handshaker_factory_list_destroy(&g_handshaker_factory_lists[i]); +void HandshakerRegistry::Shutdown() { + GPR_ASSERT(g_handshaker_factory_lists != nullptr); + for (auto idx = 0; idx < NUM_HANDSHAKER_TYPES; ++idx) { + auto factory_list = g_handshaker_factory_lists + idx; + factory_list->~HandshakerFactoryList(); } + gpr_free(g_handshaker_factory_lists); + g_handshaker_factory_lists = nullptr; } -void grpc_handshaker_factory_register(bool at_start, - grpc_handshaker_type handshaker_type, - grpc_handshaker_factory* factory) { - grpc_handshaker_factory_list_register( - &g_handshaker_factory_lists[handshaker_type], at_start, factory); +void HandshakerRegistry::RegisterHandshakerFactory( + bool at_start, HandshakerType handshaker_type, + UniquePtr factory) { + GPR_ASSERT(g_handshaker_factory_lists != nullptr); + auto& factory_list = g_handshaker_factory_lists[handshaker_type]; + factory_list.Register(at_start, std::move(factory)); } -void grpc_handshakers_add(grpc_handshaker_type handshaker_type, - const grpc_channel_args* args, - grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) { - grpc_handshaker_factory_list_add_handshakers( - &g_handshaker_factory_lists[handshaker_type], args, interested_parties, - handshake_mgr); +void HandshakerRegistry::AddHandshakers(HandshakerType handshaker_type, + const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr) { + GPR_ASSERT(g_handshaker_factory_lists != nullptr); + auto& factory_list = g_handshaker_factory_lists[handshaker_type]; + factory_list.AddHandshakers(args, interested_parties, handshake_mgr); } + +} // namespace grpc_core diff --git a/src/core/lib/channel/handshaker_registry.h b/src/core/lib/channel/handshaker_registry.h index 3dd4316de67..1b93a8dd47e 100644 --- a/src/core/lib/channel/handshaker_registry.h +++ b/src/core/lib/channel/handshaker_registry.h @@ -25,25 +25,30 @@ #include "src/core/lib/channel/handshaker_factory.h" +namespace grpc_core { + typedef enum { HANDSHAKER_CLIENT = 0, HANDSHAKER_SERVER, NUM_HANDSHAKER_TYPES, // Must be last. -} grpc_handshaker_type; - -void grpc_handshaker_factory_registry_init(); -void grpc_handshaker_factory_registry_shutdown(); - -/// Registers a new handshaker factory. Takes ownership. -/// If \a at_start is true, the new handshaker will be at the beginning of -/// the list. Otherwise, it will be added to the end. -void grpc_handshaker_factory_register(bool at_start, - grpc_handshaker_type handshaker_type, - grpc_handshaker_factory* factory); - -void grpc_handshakers_add(grpc_handshaker_type handshaker_type, - const grpc_channel_args* args, - grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr); +} HandshakerType; + +class HandshakerRegistry { + public: + /// Registers a new handshaker factory. Takes ownership. + /// If \a at_start is true, the new handshaker will be at the beginning of + /// the list. Otherwise, it will be added to the end. + static void RegisterHandshakerFactory(bool at_start, + HandshakerType handshaker_type, + UniquePtr factory); + static void AddHandshakers(HandshakerType handshaker_type, + const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr); + static void Init(); + static void Shutdown(); +}; + +} // namespace grpc_core #endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_REGISTRY_H */ diff --git a/src/core/lib/http/httpcli_security_connector.cc b/src/core/lib/http/httpcli_security_connector.cc index fdea7511cca..3f288e045a6 100644 --- a/src/core/lib/http/httpcli_security_connector.cc +++ b/src/core/lib/http/httpcli_security_connector.cc @@ -67,7 +67,7 @@ class grpc_httpcli_ssl_channel_security_connector final } void add_handshakers(grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) override { + grpc_core::HandshakeManager* handshake_mgr) override { tsi_handshaker* handshaker = nullptr; if (handshaker_factory_ != nullptr) { tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker( @@ -77,8 +77,7 @@ class grpc_httpcli_ssl_channel_security_connector final tsi_result_to_string(result)); } } - grpc_handshake_manager_add( - handshake_mgr, grpc_security_handshaker_create(handshaker, this)); + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(handshaker, this)); } tsi_ssl_client_handshaker_factory* handshaker_factory() const { @@ -155,11 +154,11 @@ httpcli_ssl_channel_security_connector_create( typedef struct { void (*func)(void* arg, grpc_endpoint* endpoint); void* arg; - grpc_handshake_manager* handshake_mgr; + grpc_core::RefCountedPtr handshake_mgr; } on_done_closure; static void on_handshake_done(void* arg, grpc_error* error) { - grpc_handshaker_args* args = static_cast(arg); + auto* args = static_cast(arg); on_done_closure* c = static_cast(args->user_data); if (error != GRPC_ERROR_NONE) { const char* msg = grpc_error_string(error); @@ -172,14 +171,13 @@ static void on_handshake_done(void* arg, grpc_error* error) { gpr_free(args->read_buffer); c->func(c->arg, args->endpoint); } - grpc_handshake_manager_destroy(c->handshake_mgr); - gpr_free(c); + grpc_core::Delete(c); } static void ssl_handshake(void* arg, grpc_endpoint* tcp, const char* host, grpc_millis deadline, void (*on_done)(void* arg, grpc_endpoint* endpoint)) { - on_done_closure* c = static_cast(gpr_malloc(sizeof(*c))); + auto* c = grpc_core::New(); const char* pem_root_certs = grpc_core::DefaultSslRootStore::GetPemRootCerts(); const tsi_ssl_root_certs_store* root_store = @@ -198,12 +196,13 @@ static void ssl_handshake(void* arg, grpc_endpoint* tcp, const char* host, GPR_ASSERT(sc != nullptr); grpc_arg channel_arg = grpc_security_connector_to_arg(sc.get()); grpc_channel_args args = {1, &channel_arg}; - c->handshake_mgr = grpc_handshake_manager_create(); - grpc_handshakers_add(HANDSHAKER_CLIENT, &args, - nullptr /* interested_parties */, c->handshake_mgr); - grpc_handshake_manager_do_handshake( - c->handshake_mgr, tcp, nullptr /* channel_args */, deadline, - nullptr /* acceptor */, on_handshake_done, c /* user_data */); + c->handshake_mgr = grpc_core::MakeRefCounted(); + grpc_core::HandshakerRegistry::AddHandshakers( + grpc_core::HANDSHAKER_CLIENT, &args, /*interested_parties=*/nullptr, + c->handshake_mgr.get()); + c->handshake_mgr->DoHandshake(tcp, /*channel_args=*/nullptr, deadline, + /*acceptor=*/nullptr, on_handshake_done, + /*user_data=*/c); sc.reset(DEBUG_LOCATION, "httpcli"); } diff --git a/src/core/lib/security/security_connector/alts/alts_security_connector.cc b/src/core/lib/security/security_connector/alts/alts_security_connector.cc index 3ad0cc353cb..38b1f856d52 100644 --- a/src/core/lib/security/security_connector/alts/alts_security_connector.cc +++ b/src/core/lib/security/security_connector/alts/alts_security_connector.cc @@ -80,8 +80,9 @@ class grpc_alts_channel_security_connector final ~grpc_alts_channel_security_connector() override { gpr_free(target_name_); } - void add_handshakers(grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_manager) override { + void add_handshakers( + grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_manager) override { tsi_handshaker* handshaker = nullptr; const grpc_alts_credentials* creds = static_cast(channel_creds()); @@ -89,8 +90,8 @@ class grpc_alts_channel_security_connector final creds->handshaker_service_url(), true, interested_parties, &handshaker) == TSI_OK); - grpc_handshake_manager_add( - handshake_manager, grpc_security_handshaker_create(handshaker, this)); + handshake_manager->Add( + grpc_core::SecurityHandshakerCreate(handshaker, this)); } void check_peer(tsi_peer peer, grpc_endpoint* ep, @@ -139,16 +140,17 @@ class grpc_alts_server_security_connector final } ~grpc_alts_server_security_connector() override = default; - void add_handshakers(grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_manager) override { + void add_handshakers( + grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_manager) override { tsi_handshaker* handshaker = nullptr; const grpc_alts_server_credentials* creds = static_cast(server_creds()); GPR_ASSERT(alts_tsi_handshaker_create( creds->options(), nullptr, creds->handshaker_service_url(), false, interested_parties, &handshaker) == TSI_OK); - grpc_handshake_manager_add( - handshake_manager, grpc_security_handshaker_create(handshaker, this)); + handshake_manager->Add( + grpc_core::SecurityHandshakerCreate(handshaker, this)); } void check_peer(tsi_peer peer, grpc_endpoint* ep, diff --git a/src/core/lib/security/security_connector/fake/fake_security_connector.cc b/src/core/lib/security/security_connector/fake/fake_security_connector.cc index e3b8affb360..a0e2e6f030b 100644 --- a/src/core/lib/security/security_connector/fake/fake_security_connector.cc +++ b/src/core/lib/security/security_connector/fake/fake_security_connector.cc @@ -92,11 +92,9 @@ class grpc_fake_channel_security_connector final } void add_handshakers(grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) override { - grpc_handshake_manager_add( - handshake_mgr, - grpc_security_handshaker_create( - tsi_create_fake_handshaker(/*is_client=*/true), this)); + grpc_core::HandshakeManager* handshake_mgr) override { + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate( + tsi_create_fake_handshaker(/*is_client=*/true), this)); } bool check_call_host(const char* host, grpc_auth_context* auth_context, @@ -273,11 +271,9 @@ class grpc_fake_server_security_connector } void add_handshakers(grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) override { - grpc_handshake_manager_add( - handshake_mgr, - grpc_security_handshaker_create( - tsi_create_fake_handshaker(/*=is_client*/ false), this)); + grpc_core::HandshakeManager* handshake_mgr) override { + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate( + tsi_create_fake_handshaker(/*=is_client*/ false), this)); } int cmp(const grpc_security_connector* other) const override { diff --git a/src/core/lib/security/security_connector/local/local_security_connector.cc b/src/core/lib/security/security_connector/local/local_security_connector.cc index 7cc482c16c5..c1a101d4ab8 100644 --- a/src/core/lib/security/security_connector/local/local_security_connector.cc +++ b/src/core/lib/security/security_connector/local/local_security_connector.cc @@ -128,13 +128,14 @@ class grpc_local_channel_security_connector final ~grpc_local_channel_security_connector() override { gpr_free(target_name_); } - void add_handshakers(grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_manager) override { + void add_handshakers( + grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_manager) override { tsi_handshaker* handshaker = nullptr; GPR_ASSERT(local_tsi_handshaker_create(true /* is_client */, &handshaker) == TSI_OK); - grpc_handshake_manager_add( - handshake_manager, grpc_security_handshaker_create(handshaker, this)); + handshake_manager->Add( + grpc_core::SecurityHandshakerCreate(handshaker, this)); } int cmp(const grpc_security_connector* other_sc) const override { @@ -184,13 +185,14 @@ class grpc_local_server_security_connector final : grpc_server_security_connector(nullptr, std::move(server_creds)) {} ~grpc_local_server_security_connector() override = default; - void add_handshakers(grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_manager) override { + void add_handshakers( + grpc_pollset_set* interested_parties, + grpc_core::HandshakeManager* handshake_manager) override { tsi_handshaker* handshaker = nullptr; GPR_ASSERT(local_tsi_handshaker_create(false /* is_client */, &handshaker) == TSI_OK); - grpc_handshake_manager_add( - handshake_manager, grpc_security_handshaker_create(handshaker, this)); + handshake_manager->Add( + grpc_core::SecurityHandshakerCreate(handshaker, this)); } void check_peer(tsi_peer peer, grpc_endpoint* ep, diff --git a/src/core/lib/security/security_connector/security_connector.h b/src/core/lib/security/security_connector/security_connector.h index 74b0ef21a62..4c74c5cfea0 100644 --- a/src/core/lib/security/security_connector/security_connector.h +++ b/src/core/lib/security/security_connector/security_connector.h @@ -109,7 +109,7 @@ class grpc_channel_security_connector : public grpc_security_connector { grpc_error* error) GRPC_ABSTRACT; /// Registers handshakers with \a handshake_mgr. virtual void add_handshakers(grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) + grpc_core::HandshakeManager* handshake_mgr) GRPC_ABSTRACT; const grpc_channel_credentials* channel_creds() const { @@ -150,7 +150,7 @@ class grpc_server_security_connector : public grpc_security_connector { ~grpc_server_security_connector() override = default; virtual void add_handshakers(grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) + grpc_core::HandshakeManager* handshake_mgr) GRPC_ABSTRACT; const grpc_server_credentials* server_creds() const { diff --git a/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc b/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc index 7414ab1a37f..37cb41b9637 100644 --- a/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +++ b/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc @@ -128,7 +128,7 @@ class grpc_ssl_channel_security_connector final } void add_handshakers(grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) override { + grpc_core::HandshakeManager* handshake_mgr) override { // Instantiate TSI handshaker. tsi_handshaker* tsi_hs = nullptr; tsi_result result = tsi_ssl_client_handshaker_factory_create_handshaker( @@ -142,8 +142,7 @@ class grpc_ssl_channel_security_connector final return; } // Create handshakers. - grpc_handshake_manager_add(handshake_mgr, - grpc_security_handshaker_create(tsi_hs, this)); + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this)); } void check_peer(tsi_peer peer, grpc_endpoint* ep, @@ -283,7 +282,7 @@ class grpc_ssl_server_security_connector } void add_handshakers(grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) override { + grpc_core::HandshakeManager* handshake_mgr) override { // Instantiate TSI handshaker. try_fetch_ssl_server_credentials(); tsi_handshaker* tsi_hs = nullptr; @@ -295,8 +294,7 @@ class grpc_ssl_server_security_connector return; } // Create handshakers. - grpc_handshake_manager_add(handshake_mgr, - grpc_security_handshaker_create(tsi_hs, this)); + handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this)); } void check_peer(tsi_peer peer, grpc_endpoint* ep, diff --git a/src/core/lib/security/transport/security_handshaker.cc b/src/core/lib/security/transport/security_handshaker.cc index 01831dab10f..a6fd2481a4a 100644 --- a/src/core/lib/security/transport/security_handshaker.cc +++ b/src/core/lib/security/transport/security_handshaker.cc @@ -39,74 +39,113 @@ #define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256 -namespace { -struct security_handshaker { - security_handshaker(tsi_handshaker* handshaker, - grpc_security_connector* connector); - ~security_handshaker() { - gpr_mu_destroy(&mu); - tsi_handshaker_destroy(handshaker); - tsi_handshaker_result_destroy(handshaker_result); - if (endpoint_to_destroy != nullptr) { - grpc_endpoint_destroy(endpoint_to_destroy); - } - if (read_buffer_to_destroy != nullptr) { - grpc_slice_buffer_destroy_internal(read_buffer_to_destroy); - gpr_free(read_buffer_to_destroy); - } - gpr_free(handshake_buffer); - grpc_slice_buffer_destroy_internal(&outgoing); - auth_context.reset(DEBUG_LOCATION, "handshake"); - connector.reset(DEBUG_LOCATION, "handshake"); - } +namespace grpc_core { - void Ref() { refs.Ref(); } - void Unref() { - if (refs.Unref()) { - grpc_core::Delete(this); - } - } +namespace { - grpc_handshaker base; +class SecurityHandshaker : public Handshaker { + public: + SecurityHandshaker(tsi_handshaker* handshaker, + grpc_security_connector* connector); + ~SecurityHandshaker() override; + void Shutdown(grpc_error* why) override; + void DoHandshake(grpc_tcp_server_acceptor* acceptor, + grpc_closure* on_handshake_done, + HandshakerArgs* args) override; + const char* name() const override { return "security"; } + + private: + grpc_error* DoHandshakerNextLocked(const unsigned char* bytes_received, + size_t bytes_received_size); + + grpc_error* OnHandshakeNextDoneLocked( + tsi_result result, const unsigned char* bytes_to_send, + size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result); + void HandshakeFailedLocked(grpc_error* error); + void CleanupArgsForFailureLocked(); + + static void OnHandshakeDataReceivedFromPeerFn(void* arg, grpc_error* error); + static void OnHandshakeDataSentToPeerFn(void* arg, grpc_error* error); + static void OnHandshakeNextDoneGrpcWrapper( + tsi_result result, void* user_data, const unsigned char* bytes_to_send, + size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result); + static void OnPeerCheckedFn(void* arg, grpc_error* error); + void OnPeerCheckedInner(grpc_error* error); + size_t MoveReadBufferIntoHandshakeBuffer(); + grpc_error* CheckPeerLocked(); // State set at creation time. - tsi_handshaker* handshaker; - grpc_core::RefCountedPtr connector; + tsi_handshaker* handshaker_; + RefCountedPtr connector_; - gpr_mu mu; - grpc_core::RefCount refs; + gpr_mu mu_; - bool shutdown = false; + bool is_shutdown_ = false; // Endpoint and read buffer to destroy after a shutdown. - grpc_endpoint* endpoint_to_destroy = nullptr; - grpc_slice_buffer* read_buffer_to_destroy = nullptr; + grpc_endpoint* endpoint_to_destroy_ = nullptr; + grpc_slice_buffer* read_buffer_to_destroy_ = nullptr; // State saved while performing the handshake. - grpc_handshaker_args* args = nullptr; - grpc_closure* on_handshake_done = nullptr; - - size_t handshake_buffer_size; - unsigned char* handshake_buffer; - grpc_slice_buffer outgoing; - grpc_closure on_handshake_data_sent_to_peer; - grpc_closure on_handshake_data_received_from_peer; - grpc_closure on_peer_checked; - grpc_core::RefCountedPtr auth_context; - tsi_handshaker_result* handshaker_result = nullptr; + HandshakerArgs* args_ = nullptr; + grpc_closure* on_handshake_done_ = nullptr; + + size_t handshake_buffer_size_; + unsigned char* handshake_buffer_; + grpc_slice_buffer outgoing_; + grpc_closure on_handshake_data_sent_to_peer_; + grpc_closure on_handshake_data_received_from_peer_; + grpc_closure on_peer_checked_; + RefCountedPtr auth_context_; + tsi_handshaker_result* handshaker_result_ = nullptr; }; -} // namespace -static size_t move_read_buffer_into_handshake_buffer(security_handshaker* h) { - size_t bytes_in_read_buffer = h->args->read_buffer->length; - if (h->handshake_buffer_size < bytes_in_read_buffer) { - h->handshake_buffer = static_cast( - gpr_realloc(h->handshake_buffer, bytes_in_read_buffer)); - h->handshake_buffer_size = bytes_in_read_buffer; +SecurityHandshaker::SecurityHandshaker(tsi_handshaker* handshaker, + grpc_security_connector* connector) + : handshaker_(handshaker), + connector_(connector->Ref(DEBUG_LOCATION, "handshake")), + handshake_buffer_size_(GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE), + handshake_buffer_( + static_cast(gpr_malloc(handshake_buffer_size_))) { + gpr_mu_init(&mu_); + grpc_slice_buffer_init(&outgoing_); + GRPC_CLOSURE_INIT(&on_handshake_data_sent_to_peer_, + &SecurityHandshaker::OnHandshakeDataSentToPeerFn, this, + grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&on_handshake_data_received_from_peer_, + &SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn, + this, grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&on_peer_checked_, &SecurityHandshaker::OnPeerCheckedFn, + this, grpc_schedule_on_exec_ctx); +} + +SecurityHandshaker::~SecurityHandshaker() { + gpr_mu_destroy(&mu_); + tsi_handshaker_destroy(handshaker_); + tsi_handshaker_result_destroy(handshaker_result_); + if (endpoint_to_destroy_ != nullptr) { + grpc_endpoint_destroy(endpoint_to_destroy_); + } + if (read_buffer_to_destroy_ != nullptr) { + grpc_slice_buffer_destroy_internal(read_buffer_to_destroy_); + gpr_free(read_buffer_to_destroy_); + } + gpr_free(handshake_buffer_); + grpc_slice_buffer_destroy_internal(&outgoing_); + auth_context_.reset(DEBUG_LOCATION, "handshake"); + connector_.reset(DEBUG_LOCATION, "handshake"); +} + +size_t SecurityHandshaker::MoveReadBufferIntoHandshakeBuffer() { + size_t bytes_in_read_buffer = args_->read_buffer->length; + if (handshake_buffer_size_ < bytes_in_read_buffer) { + handshake_buffer_ = static_cast( + gpr_realloc(handshake_buffer_, bytes_in_read_buffer)); + handshake_buffer_size_ = bytes_in_read_buffer; } size_t offset = 0; - while (h->args->read_buffer->count > 0) { - grpc_slice next_slice = grpc_slice_buffer_take_first(h->args->read_buffer); - memcpy(h->handshake_buffer + offset, GRPC_SLICE_START_PTR(next_slice), + while (args_->read_buffer->count > 0) { + grpc_slice next_slice = grpc_slice_buffer_take_first(args_->read_buffer); + memcpy(handshake_buffer_ + offset, GRPC_SLICE_START_PTR(next_slice), GRPC_SLICE_LENGTH(next_slice)); offset += GRPC_SLICE_LENGTH(next_slice); grpc_slice_unref_internal(next_slice); @@ -114,21 +153,20 @@ static size_t move_read_buffer_into_handshake_buffer(security_handshaker* h) { return bytes_in_read_buffer; } -// Set args fields to NULL, saving the endpoint and read buffer for +// Set args_ fields to NULL, saving the endpoint and read buffer for // later destruction. -static void cleanup_args_for_failure_locked(security_handshaker* h) { - h->endpoint_to_destroy = h->args->endpoint; - h->args->endpoint = nullptr; - h->read_buffer_to_destroy = h->args->read_buffer; - h->args->read_buffer = nullptr; - grpc_channel_args_destroy(h->args->args); - h->args->args = nullptr; +void SecurityHandshaker::CleanupArgsForFailureLocked() { + endpoint_to_destroy_ = args_->endpoint; + args_->endpoint = nullptr; + read_buffer_to_destroy_ = args_->read_buffer; + args_->read_buffer = nullptr; + grpc_channel_args_destroy(args_->args); + args_->args = nullptr; } // If the handshake failed or we're shutting down, clean up and invoke the // callback with the error. -static void security_handshake_failed_locked(security_handshaker* h, - grpc_error* error) { +void SecurityHandshaker::HandshakeFailedLocked(grpc_error* error) { if (error == GRPC_ERROR_NONE) { // If we were shut down after the handshake succeeded but before an // endpoint callback was invoked, we need to generate our own error. @@ -137,50 +175,51 @@ static void security_handshake_failed_locked(security_handshaker* h, const char* msg = grpc_error_string(error); gpr_log(GPR_DEBUG, "Security handshake failed: %s", msg); - if (!h->shutdown) { + if (!is_shutdown_) { // TODO(ctiller): It is currently necessary to shutdown endpoints // before destroying them, even if we know that there are no // pending read/write callbacks. This should be fixed, at which // point this can be removed. - grpc_endpoint_shutdown(h->args->endpoint, GRPC_ERROR_REF(error)); + grpc_endpoint_shutdown(args_->endpoint, GRPC_ERROR_REF(error)); // Not shutting down, so the write failed. Clean up before // invoking the callback. - cleanup_args_for_failure_locked(h); + CleanupArgsForFailureLocked(); // Set shutdown to true so that subsequent calls to // security_handshaker_shutdown() do nothing. - h->shutdown = true; + is_shutdown_ = true; } // Invoke callback. - GRPC_CLOSURE_SCHED(h->on_handshake_done, error); + GRPC_CLOSURE_SCHED(on_handshake_done_, error); } -static void on_peer_checked_inner(security_handshaker* h, grpc_error* error) { - if (error != GRPC_ERROR_NONE || h->shutdown) { - security_handshake_failed_locked(h, GRPC_ERROR_REF(error)); +void SecurityHandshaker::OnPeerCheckedInner(grpc_error* error) { + MutexLock lock(&mu_); + if (error != GRPC_ERROR_NONE || is_shutdown_) { + HandshakeFailedLocked(GRPC_ERROR_REF(error)); return; } // Create zero-copy frame protector, if implemented. tsi_zero_copy_grpc_protector* zero_copy_protector = nullptr; tsi_result result = tsi_handshaker_result_create_zero_copy_grpc_protector( - h->handshaker_result, nullptr, &zero_copy_protector); + handshaker_result_, nullptr, &zero_copy_protector); if (result != TSI_OK && result != TSI_UNIMPLEMENTED) { error = grpc_set_tsi_error_result( GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Zero-copy frame protector creation failed"), result); - security_handshake_failed_locked(h, error); + HandshakeFailedLocked(error); return; } // Create frame protector if zero-copy frame protector is NULL. tsi_frame_protector* protector = nullptr; if (zero_copy_protector == nullptr) { - result = tsi_handshaker_result_create_frame_protector(h->handshaker_result, + result = tsi_handshaker_result_create_frame_protector(handshaker_result_, nullptr, &protector); if (result != TSI_OK) { error = grpc_set_tsi_error_result(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Frame protector creation failed"), result); - security_handshake_failed_locked(h, error); + HandshakeFailedLocked(error); return; } } @@ -188,68 +227,63 @@ static void on_peer_checked_inner(security_handshaker* h, grpc_error* error) { const unsigned char* unused_bytes = nullptr; size_t unused_bytes_size = 0; result = tsi_handshaker_result_get_unused_bytes( - h->handshaker_result, &unused_bytes, &unused_bytes_size); + handshaker_result_, &unused_bytes, &unused_bytes_size); // Create secure endpoint. if (unused_bytes_size > 0) { grpc_slice slice = grpc_slice_from_copied_buffer((char*)unused_bytes, unused_bytes_size); - h->args->endpoint = grpc_secure_endpoint_create( - protector, zero_copy_protector, h->args->endpoint, &slice, 1); + args_->endpoint = grpc_secure_endpoint_create( + protector, zero_copy_protector, args_->endpoint, &slice, 1); grpc_slice_unref_internal(slice); } else { - h->args->endpoint = grpc_secure_endpoint_create( - protector, zero_copy_protector, h->args->endpoint, nullptr, 0); + args_->endpoint = grpc_secure_endpoint_create( + protector, zero_copy_protector, args_->endpoint, nullptr, 0); } - tsi_handshaker_result_destroy(h->handshaker_result); - h->handshaker_result = nullptr; + tsi_handshaker_result_destroy(handshaker_result_); + handshaker_result_ = nullptr; // Add auth context to channel args. - grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context.get()); - grpc_channel_args* tmp_args = h->args->args; - h->args->args = - grpc_channel_args_copy_and_add(tmp_args, &auth_context_arg, 1); + grpc_arg auth_context_arg = grpc_auth_context_to_arg(auth_context_.get()); + grpc_channel_args* tmp_args = args_->args; + args_->args = grpc_channel_args_copy_and_add(tmp_args, &auth_context_arg, 1); grpc_channel_args_destroy(tmp_args); // Invoke callback. - GRPC_CLOSURE_SCHED(h->on_handshake_done, GRPC_ERROR_NONE); + GRPC_CLOSURE_SCHED(on_handshake_done_, GRPC_ERROR_NONE); // Set shutdown to true so that subsequent calls to // security_handshaker_shutdown() do nothing. - h->shutdown = true; + is_shutdown_ = true; } -static void on_peer_checked(void* arg, grpc_error* error) { - security_handshaker* h = static_cast(arg); - gpr_mu_lock(&h->mu); - on_peer_checked_inner(h, error); - gpr_mu_unlock(&h->mu); - h->Unref(); +void SecurityHandshaker::OnPeerCheckedFn(void* arg, grpc_error* error) { + RefCountedPtr(static_cast(arg)) + ->OnPeerCheckedInner(error); } -static grpc_error* check_peer_locked(security_handshaker* h) { +grpc_error* SecurityHandshaker::CheckPeerLocked() { tsi_peer peer; tsi_result result = - tsi_handshaker_result_extract_peer(h->handshaker_result, &peer); + tsi_handshaker_result_extract_peer(handshaker_result_, &peer); if (result != TSI_OK) { return grpc_set_tsi_error_result( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Peer extraction failed"), result); } - h->connector->check_peer(peer, h->args->endpoint, &h->auth_context, - &h->on_peer_checked); + connector_->check_peer(peer, args_->endpoint, &auth_context_, + &on_peer_checked_); return GRPC_ERROR_NONE; } -static grpc_error* on_handshake_next_done_locked( - security_handshaker* h, tsi_result result, - const unsigned char* bytes_to_send, size_t bytes_to_send_size, - tsi_handshaker_result* handshaker_result) { +grpc_error* SecurityHandshaker::OnHandshakeNextDoneLocked( + tsi_result result, const unsigned char* bytes_to_send, + size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result) { grpc_error* error = GRPC_ERROR_NONE; // Handshaker was shutdown. - if (h->shutdown) { + if (is_shutdown_) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown"); } // Read more if we need to. if (result == TSI_INCOMPLETE_DATA) { GPR_ASSERT(bytes_to_send_size == 0); - grpc_endpoint_read(h->args->endpoint, h->args->read_buffer, - &h->on_handshake_data_received_from_peer); + grpc_endpoint_read(args_->endpoint, args_->read_buffer, + &on_handshake_data_received_from_peer_); return error; } if (result != TSI_OK) { @@ -258,55 +292,52 @@ static grpc_error* on_handshake_next_done_locked( } // Update handshaker result. if (handshaker_result != nullptr) { - GPR_ASSERT(h->handshaker_result == nullptr); - h->handshaker_result = handshaker_result; + GPR_ASSERT(handshaker_result_ == nullptr); + handshaker_result_ = handshaker_result; } if (bytes_to_send_size > 0) { // Send data to peer, if needed. grpc_slice to_send = grpc_slice_from_copied_buffer( reinterpret_cast(bytes_to_send), bytes_to_send_size); - grpc_slice_buffer_reset_and_unref_internal(&h->outgoing); - grpc_slice_buffer_add(&h->outgoing, to_send); - grpc_endpoint_write(h->args->endpoint, &h->outgoing, - &h->on_handshake_data_sent_to_peer, nullptr); + grpc_slice_buffer_reset_and_unref_internal(&outgoing_); + grpc_slice_buffer_add(&outgoing_, to_send); + grpc_endpoint_write(args_->endpoint, &outgoing_, + &on_handshake_data_sent_to_peer_, nullptr); } else if (handshaker_result == nullptr) { // There is nothing to send, but need to read from peer. - grpc_endpoint_read(h->args->endpoint, h->args->read_buffer, - &h->on_handshake_data_received_from_peer); + grpc_endpoint_read(args_->endpoint, args_->read_buffer, + &on_handshake_data_received_from_peer_); } else { // Handshake has finished, check peer and so on. - error = check_peer_locked(h); + error = CheckPeerLocked(); } return error; } -static void on_handshake_next_done_grpc_wrapper( +void SecurityHandshaker::OnHandshakeNextDoneGrpcWrapper( tsi_result result, void* user_data, const unsigned char* bytes_to_send, size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result) { - security_handshaker* h = static_cast(user_data); - gpr_mu_lock(&h->mu); - grpc_error* error = on_handshake_next_done_locked( - h, result, bytes_to_send, bytes_to_send_size, handshaker_result); + RefCountedPtr h( + static_cast(user_data)); + MutexLock lock(&h->mu_); + grpc_error* error = h->OnHandshakeNextDoneLocked( + result, bytes_to_send, bytes_to_send_size, handshaker_result); if (error != GRPC_ERROR_NONE) { - security_handshake_failed_locked(h, error); - gpr_mu_unlock(&h->mu); - h->Unref(); + h->HandshakeFailedLocked(error); } else { - gpr_mu_unlock(&h->mu); + h.release(); // Avoid unref } } -static grpc_error* do_handshaker_next_locked( - security_handshaker* h, const unsigned char* bytes_received, - size_t bytes_received_size) { +grpc_error* SecurityHandshaker::DoHandshakerNextLocked( + const unsigned char* bytes_received, size_t bytes_received_size) { // Invoke TSI handshaker. const unsigned char* bytes_to_send = nullptr; size_t bytes_to_send_size = 0; - tsi_handshaker_result* handshaker_result = nullptr; + tsi_handshaker_result* hs_result = nullptr; tsi_result result = tsi_handshaker_next( - h->handshaker, bytes_received, bytes_received_size, &bytes_to_send, - &bytes_to_send_size, &handshaker_result, - &on_handshake_next_done_grpc_wrapper, h); + handshaker_, bytes_received, bytes_received_size, &bytes_to_send, + &bytes_to_send_size, &hs_result, &OnHandshakeNextDoneGrpcWrapper, this); if (result == TSI_ASYNC) { // Handshaker operating asynchronously. Nothing else to do here; // callback will be invoked in a TSI thread. @@ -314,233 +345,169 @@ static grpc_error* do_handshaker_next_locked( } // Handshaker returned synchronously. Invoke callback directly in // this thread with our existing exec_ctx. - return on_handshake_next_done_locked(h, result, bytes_to_send, - bytes_to_send_size, handshaker_result); + return OnHandshakeNextDoneLocked(result, bytes_to_send, bytes_to_send_size, + hs_result); } -static void on_handshake_data_received_from_peer(void* arg, grpc_error* error) { - security_handshaker* h = static_cast(arg); - gpr_mu_lock(&h->mu); - if (error != GRPC_ERROR_NONE || h->shutdown) { - security_handshake_failed_locked( - h, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Handshake read failed", &error, 1)); - gpr_mu_unlock(&h->mu); - h->Unref(); +void SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn(void* arg, + grpc_error* error) { + RefCountedPtr h(static_cast(arg)); + MutexLock lock(&h->mu_); + if (error != GRPC_ERROR_NONE || h->is_shutdown_) { + h->HandshakeFailedLocked(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Handshake read failed", &error, 1)); return; } // Copy all slices received. - size_t bytes_received_size = move_read_buffer_into_handshake_buffer(h); + size_t bytes_received_size = h->MoveReadBufferIntoHandshakeBuffer(); // Call TSI handshaker. - error = - do_handshaker_next_locked(h, h->handshake_buffer, bytes_received_size); + error = h->DoHandshakerNextLocked(h->handshake_buffer_, bytes_received_size); if (error != GRPC_ERROR_NONE) { - security_handshake_failed_locked(h, error); - gpr_mu_unlock(&h->mu); - h->Unref(); + h->HandshakeFailedLocked(error); } else { - gpr_mu_unlock(&h->mu); + h.release(); // Avoid unref } } -static void on_handshake_data_sent_to_peer(void* arg, grpc_error* error) { - security_handshaker* h = static_cast(arg); - gpr_mu_lock(&h->mu); - if (error != GRPC_ERROR_NONE || h->shutdown) { - security_handshake_failed_locked( - h, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Handshake write failed", &error, 1)); - gpr_mu_unlock(&h->mu); - h->Unref(); +void SecurityHandshaker::OnHandshakeDataSentToPeerFn(void* arg, + grpc_error* error) { + RefCountedPtr h(static_cast(arg)); + MutexLock lock(&h->mu_); + if (error != GRPC_ERROR_NONE || h->is_shutdown_) { + h->HandshakeFailedLocked(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Handshake write failed", &error, 1)); return; } // We may be done. - if (h->handshaker_result == nullptr) { - grpc_endpoint_read(h->args->endpoint, h->args->read_buffer, - &h->on_handshake_data_received_from_peer); + if (h->handshaker_result_ == nullptr) { + grpc_endpoint_read(h->args_->endpoint, h->args_->read_buffer, + &h->on_handshake_data_received_from_peer_); } else { - error = check_peer_locked(h); + error = h->CheckPeerLocked(); if (error != GRPC_ERROR_NONE) { - security_handshake_failed_locked(h, error); - gpr_mu_unlock(&h->mu); - h->Unref(); + h->HandshakeFailedLocked(error); return; } } - gpr_mu_unlock(&h->mu); + h.release(); // Avoid unref } // // public handshaker API // -static void security_handshaker_destroy(grpc_handshaker* handshaker) { - security_handshaker* h = reinterpret_cast(handshaker); - h->Unref(); -} - -static void security_handshaker_shutdown(grpc_handshaker* handshaker, - grpc_error* why) { - security_handshaker* h = reinterpret_cast(handshaker); - gpr_mu_lock(&h->mu); - if (!h->shutdown) { - h->shutdown = true; - tsi_handshaker_shutdown(h->handshaker); - grpc_endpoint_shutdown(h->args->endpoint, GRPC_ERROR_REF(why)); - cleanup_args_for_failure_locked(h); +void SecurityHandshaker::Shutdown(grpc_error* why) { + MutexLock lock(&mu_); + if (!is_shutdown_) { + is_shutdown_ = true; + tsi_handshaker_shutdown(handshaker_); + grpc_endpoint_shutdown(args_->endpoint, GRPC_ERROR_REF(why)); + CleanupArgsForFailureLocked(); } - gpr_mu_unlock(&h->mu); GRPC_ERROR_UNREF(why); } -static void security_handshaker_do_handshake(grpc_handshaker* handshaker, - grpc_tcp_server_acceptor* acceptor, - grpc_closure* on_handshake_done, - grpc_handshaker_args* args) { - security_handshaker* h = reinterpret_cast(handshaker); - gpr_mu_lock(&h->mu); - h->args = args; - h->on_handshake_done = on_handshake_done; - h->Ref(); - size_t bytes_received_size = move_read_buffer_into_handshake_buffer(h); +void SecurityHandshaker::DoHandshake(grpc_tcp_server_acceptor* acceptor, + grpc_closure* on_handshake_done, + HandshakerArgs* args) { + auto ref = Ref(); + MutexLock lock(&mu_); + args_ = args; + on_handshake_done_ = on_handshake_done; + size_t bytes_received_size = MoveReadBufferIntoHandshakeBuffer(); grpc_error* error = - do_handshaker_next_locked(h, h->handshake_buffer, bytes_received_size); + DoHandshakerNextLocked(handshake_buffer_, bytes_received_size); if (error != GRPC_ERROR_NONE) { - security_handshake_failed_locked(h, error); - gpr_mu_unlock(&h->mu); - h->Unref(); - return; + HandshakeFailedLocked(error); + } else { + ref.release(); // Avoid unref } - gpr_mu_unlock(&h->mu); -} - -static const grpc_handshaker_vtable security_handshaker_vtable = { - security_handshaker_destroy, security_handshaker_shutdown, - security_handshaker_do_handshake, "security"}; - -namespace { -security_handshaker::security_handshaker(tsi_handshaker* handshaker, - grpc_security_connector* connector) - : handshaker(handshaker), - connector(connector->Ref(DEBUG_LOCATION, "handshake")), - handshake_buffer_size(GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE), - handshake_buffer( - static_cast(gpr_malloc(handshake_buffer_size))) { - grpc_handshaker_init(&security_handshaker_vtable, &base); - gpr_mu_init(&mu); - grpc_slice_buffer_init(&outgoing); - GRPC_CLOSURE_INIT(&on_handshake_data_sent_to_peer, - ::on_handshake_data_sent_to_peer, this, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&on_handshake_data_received_from_peer, - ::on_handshake_data_received_from_peer, this, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&on_peer_checked, ::on_peer_checked, this, - grpc_schedule_on_exec_ctx); -} -} // namespace - -static grpc_handshaker* security_handshaker_create( - tsi_handshaker* handshaker, grpc_security_connector* connector) { - security_handshaker* h = - grpc_core::New(handshaker, connector); - return &h->base; } // -// fail_handshaker +// FailHandshaker // -static void fail_handshaker_destroy(grpc_handshaker* handshaker) { - gpr_free(handshaker); -} - -static void fail_handshaker_shutdown(grpc_handshaker* handshaker, - grpc_error* why) { - GRPC_ERROR_UNREF(why); -} - -static void fail_handshaker_do_handshake(grpc_handshaker* handshaker, - grpc_tcp_server_acceptor* acceptor, - grpc_closure* on_handshake_done, - grpc_handshaker_args* args) { - GRPC_CLOSURE_SCHED(on_handshake_done, - GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Failed to create security handshaker")); -} - -static const grpc_handshaker_vtable fail_handshaker_vtable = { - fail_handshaker_destroy, fail_handshaker_shutdown, - fail_handshaker_do_handshake, "security_fail"}; +class FailHandshaker : public Handshaker { + public: + const char* name() const override { return "security_fail"; } + void Shutdown(grpc_error* why) override { GRPC_ERROR_UNREF(why); } + void DoHandshake(grpc_tcp_server_acceptor* acceptor, + grpc_closure* on_handshake_done, + HandshakerArgs* args) override { + GRPC_CLOSURE_SCHED(on_handshake_done, + GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Failed to create security handshaker")); + } -static grpc_handshaker* fail_handshaker_create() { - grpc_handshaker* h = static_cast(gpr_malloc(sizeof(*h))); - grpc_handshaker_init(&fail_handshaker_vtable, h); - return h; -} + private: + virtual ~FailHandshaker() = default; +}; // // handshaker factories // -static void client_handshaker_factory_add_handshakers( - grpc_handshaker_factory* handshaker_factory, const grpc_channel_args* args, - grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) { - grpc_channel_security_connector* security_connector = - reinterpret_cast( - grpc_security_connector_find_in_args(args)); - if (security_connector) { - security_connector->add_handshakers(interested_parties, handshake_mgr); +class ClientSecurityHandshakerFactory : public HandshakerFactory { + public: + void AddHandshakers(const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr) override { + auto* security_connector = + reinterpret_cast( + grpc_security_connector_find_in_args(args)); + if (security_connector) { + security_connector->add_handshakers(interested_parties, handshake_mgr); + } } -} + ~ClientSecurityHandshakerFactory() override = default; +}; -static void server_handshaker_factory_add_handshakers( - grpc_handshaker_factory* hf, const grpc_channel_args* args, - grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) { - grpc_server_security_connector* security_connector = - reinterpret_cast( - grpc_security_connector_find_in_args(args)); - if (security_connector) { - security_connector->add_handshakers(interested_parties, handshake_mgr); +class ServerSecurityHandshakerFactory : public HandshakerFactory { + public: + void AddHandshakers(const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr) override { + auto* security_connector = + reinterpret_cast( + grpc_security_connector_find_in_args(args)); + if (security_connector) { + security_connector->add_handshakers(interested_parties, handshake_mgr); + } } -} - -static void handshaker_factory_destroy( - grpc_handshaker_factory* handshaker_factory) {} - -static const grpc_handshaker_factory_vtable client_handshaker_factory_vtable = { - client_handshaker_factory_add_handshakers, handshaker_factory_destroy}; - -static grpc_handshaker_factory client_handshaker_factory = { - &client_handshaker_factory_vtable}; - -static const grpc_handshaker_factory_vtable server_handshaker_factory_vtable = { - server_handshaker_factory_add_handshakers, handshaker_factory_destroy}; + ~ServerSecurityHandshakerFactory() override = default; +}; -static grpc_handshaker_factory server_handshaker_factory = { - &server_handshaker_factory_vtable}; +} // namespace // // exported functions // -grpc_handshaker* grpc_security_handshaker_create( +RefCountedPtr SecurityHandshakerCreate( tsi_handshaker* handshaker, grpc_security_connector* connector) { // If no TSI handshaker was created, return a handshaker that always fails. // Otherwise, return a real security handshaker. if (handshaker == nullptr) { - return fail_handshaker_create(); + return MakeRefCounted(); } else { - return security_handshaker_create(handshaker, connector); + return MakeRefCounted(handshaker, connector); } } -void grpc_security_register_handshaker_factories() { - grpc_handshaker_factory_register(false /* at_start */, HANDSHAKER_CLIENT, - &client_handshaker_factory); - grpc_handshaker_factory_register(false /* at_start */, HANDSHAKER_SERVER, - &server_handshaker_factory); +grpc_handshaker* grpc_security_handshaker_create( + tsi_handshaker* handshaker, grpc_security_connector* connector) { + return SecurityHandshakerCreate(handshaker, connector).release(); } + +void SecurityRegisterHandshakerFactories() { + HandshakerRegistry::RegisterHandshakerFactory( + false /* at_start */, HANDSHAKER_CLIENT, + UniquePtr(New())); + HandshakerRegistry::RegisterHandshakerFactory( + false /* at_start */, HANDSHAKER_SERVER, + UniquePtr(New())); +} + +} // namespace grpc_core diff --git a/src/core/lib/security/transport/security_handshaker.h b/src/core/lib/security/transport/security_handshaker.h index 88483b02e74..263fe555967 100644 --- a/src/core/lib/security/transport/security_handshaker.h +++ b/src/core/lib/security/transport/security_handshaker.h @@ -24,11 +24,20 @@ #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/security/security_connector/security_connector.h" +namespace grpc_core { + /// Creates a security handshaker using \a handshaker. -grpc_handshaker* grpc_security_handshaker_create( +RefCountedPtr SecurityHandshakerCreate( tsi_handshaker* handshaker, grpc_security_connector* connector); /// Registers security handshaker factories. -void grpc_security_register_handshaker_factories(); +void SecurityRegisterHandshakerFactories(); + +} // namespace grpc_core + +// TODO(arjunroy): This is transitional to account for the new handshaker API +// and will eventually be removed entirely. +grpc_handshaker* grpc_security_handshaker_create( + tsi_handshaker* handshaker, grpc_security_connector* connector); #endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_SECURITY_HANDSHAKER_H */ diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc index f704a64b1c9..e507de87c2a 100644 --- a/src/core/lib/surface/init.cc +++ b/src/core/lib/surface/init.cc @@ -134,7 +134,7 @@ void grpc_init(void) { grpc_core::ExecCtx::GlobalInit(); grpc_iomgr_init(); gpr_timers_global_init(); - grpc_handshaker_factory_registry_init(); + grpc_core::HandshakerRegistry::Init(); grpc_security_init(); for (i = 0; i < g_number_of_plugins; i++) { if (g_all_of_the_plugins[i].init != nullptr) { @@ -177,7 +177,7 @@ void grpc_shutdown(void) { gpr_timers_global_destroy(); grpc_tracer_shutdown(); grpc_mdctx_global_shutdown(); - grpc_handshaker_factory_registry_shutdown(); + grpc_core::HandshakerRegistry::Shutdown(); grpc_slice_intern_shutdown(); grpc_core::channelz::ChannelzRegistry::Shutdown(); grpc_stats_shutdown(); diff --git a/src/core/lib/surface/init_secure.cc b/src/core/lib/surface/init_secure.cc index 765350cced0..0e83a11a5f0 100644 --- a/src/core/lib/surface/init_secure.cc +++ b/src/core/lib/surface/init_secure.cc @@ -78,4 +78,4 @@ void grpc_register_security_filters(void) { maybe_prepend_server_auth_filter, nullptr); } -void grpc_security_init() { grpc_security_register_handshaker_factories(); } +void grpc_security_init() { grpc_core::SecurityRegisterHandshakerFactories(); } diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 19d27412205..71de0c4abe0 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -68,7 +68,6 @@ CORE_SOURCE_FILES = [ 'src/core/lib/channel/channelz_registry.cc', 'src/core/lib/channel/connected_channel.cc', 'src/core/lib/channel/handshaker.cc', - 'src/core/lib/channel/handshaker_factory.cc', 'src/core/lib/channel/handshaker_registry.cc', 'src/core/lib/channel/status_util.cc', 'src/core/lib/compression/compression.cc', diff --git a/test/core/handshake/readahead_handshaker_server_ssl.cc b/test/core/handshake/readahead_handshaker_server_ssl.cc index 14d96b5d89c..e4584105e65 100644 --- a/test/core/handshake/readahead_handshaker_server_ssl.cc +++ b/test/core/handshake/readahead_handshaker_server_ssl.cc @@ -49,51 +49,38 @@ * to the security_handshaker). This test is meant to protect code relying on * this functionality that lives outside of this repo. */ -static void readahead_handshaker_destroy(grpc_handshaker* handshaker) { - gpr_free(handshaker); -} - -static void readahead_handshaker_shutdown(grpc_handshaker* handshaker, - grpc_error* error) {} - -static void readahead_handshaker_do_handshake( - grpc_handshaker* handshaker, grpc_tcp_server_acceptor* acceptor, - grpc_closure* on_handshake_done, grpc_handshaker_args* args) { - grpc_endpoint_read(args->endpoint, args->read_buffer, on_handshake_done); -} +namespace grpc_core { -const grpc_handshaker_vtable readahead_handshaker_vtable = { - readahead_handshaker_destroy, readahead_handshaker_shutdown, - readahead_handshaker_do_handshake, "read_ahead"}; - -static grpc_handshaker* readahead_handshaker_create() { - grpc_handshaker* h = - static_cast(gpr_zalloc(sizeof(grpc_handshaker))); - grpc_handshaker_init(&readahead_handshaker_vtable, h); - return h; -} - -static void readahead_handshaker_factory_add_handshakers( - grpc_handshaker_factory* hf, const grpc_channel_args* args, - grpc_pollset_set* interested_parties, - grpc_handshake_manager* handshake_mgr) { - grpc_handshake_manager_add(handshake_mgr, readahead_handshaker_create()); -} +class ReadAheadHandshaker : public Handshaker { + public: + virtual ~ReadAheadHandshaker() {} + const char* name() const override { return "read_ahead"; } + void Shutdown(grpc_error* why) override {} + void DoHandshake(grpc_tcp_server_acceptor* acceptor, + grpc_closure* on_handshake_done, + HandshakerArgs* args) override { + grpc_endpoint_read(args->endpoint, args->read_buffer, on_handshake_done); + } +}; -static void readahead_handshaker_factory_destroy( - grpc_handshaker_factory* handshaker_factory) {} +class ReadAheadHandshakerFactory : public HandshakerFactory { + public: + void AddHandshakers(const grpc_channel_args* args, + grpc_pollset_set* interested_parties, + HandshakeManager* handshake_mgr) override { + handshake_mgr->Add(MakeRefCounted()); + } + ~ReadAheadHandshakerFactory() override = default; +}; -static const grpc_handshaker_factory_vtable - readahead_handshaker_factory_vtable = { - readahead_handshaker_factory_add_handshakers, - readahead_handshaker_factory_destroy}; +} // namespace grpc_core int main(int argc, char* argv[]) { - grpc_handshaker_factory readahead_handshaker_factory = { - &readahead_handshaker_factory_vtable}; + using namespace grpc_core; grpc_init(); - grpc_handshaker_factory_register(true /* at_start */, HANDSHAKER_SERVER, - &readahead_handshaker_factory); + HandshakerRegistry::RegisterHandshakerFactory( + true /* at_start */, HANDSHAKER_SERVER, + UniquePtr(New())); const char* full_alpn_list[] = {"grpc-exp", "h2"}; GPR_ASSERT(server_ssl_test(full_alpn_list, 2, "grpc-exp")); grpc_shutdown(); diff --git a/test/core/security/ssl_server_fuzzer.cc b/test/core/security/ssl_server_fuzzer.cc index c9380126dd0..8533644aceb 100644 --- a/test/core/security/ssl_server_fuzzer.cc +++ b/test/core/security/ssl_server_fuzzer.cc @@ -41,7 +41,8 @@ struct handshake_state { }; static void on_handshake_done(void* arg, grpc_error* error) { - grpc_handshaker_args* args = static_cast(arg); + grpc_core::HandshakerArgs* args = + static_cast(arg); struct handshake_state* state = static_cast(args->user_data); GPR_ASSERT(state->done_callback_called == false); @@ -89,11 +90,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { struct handshake_state state; state.done_callback_called = false; - grpc_handshake_manager* handshake_mgr = grpc_handshake_manager_create(); - sc->add_handshakers(nullptr, handshake_mgr); - grpc_handshake_manager_do_handshake( - handshake_mgr, mock_endpoint, nullptr /* channel_args */, deadline, - nullptr /* acceptor */, on_handshake_done, &state); + auto handshake_mgr = + grpc_core::MakeRefCounted(); + sc->add_handshakers(nullptr, handshake_mgr.get()); + handshake_mgr->DoHandshake(mock_endpoint, nullptr /* channel_args */, + deadline, nullptr /* acceptor */, + on_handshake_done, &state); grpc_core::ExecCtx::Get()->Flush(); // If the given string happens to be part of the correct client hello, the @@ -108,7 +110,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { GPR_ASSERT(state.done_callback_called); - grpc_handshake_manager_destroy(handshake_mgr); sc.reset(DEBUG_LOCATION, "test"); grpc_server_credentials_release(creds); grpc_slice_unref(cert_slice); diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 2aced414218..86b57b23d9a 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1080,7 +1080,6 @@ src/core/lib/channel/connected_channel.h \ src/core/lib/channel/context.h \ src/core/lib/channel/handshaker.cc \ src/core/lib/channel/handshaker.h \ -src/core/lib/channel/handshaker_factory.cc \ src/core/lib/channel/handshaker_factory.h \ src/core/lib/channel/handshaker_registry.cc \ src/core/lib/channel/handshaker_registry.h \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index ab01b8fca6a..84d5c45095f 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -9440,7 +9440,6 @@ "src/core/lib/channel/channelz_registry.cc", "src/core/lib/channel/connected_channel.cc", "src/core/lib/channel/handshaker.cc", - "src/core/lib/channel/handshaker_factory.cc", "src/core/lib/channel/handshaker_registry.cc", "src/core/lib/channel/status_util.cc", "src/core/lib/compression/compression.cc", From a47c979ba07937cd6f5e67b0763a0908502f9b28 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Mon, 14 Jan 2019 14:29:27 -0800 Subject: [PATCH 207/218] Enable TCP callback tests if the event engine allows --- src/core/lib/iomgr/iomgr.h | 5 ++ src/core/lib/iomgr/iomgr_posix.cc | 4 + src/core/lib/iomgr/iomgr_windows.cc | 2 + .../end2end/client_callback_end2end_test.cc | 66 +++++++++++++- test/cpp/end2end/end2end_test.cc | 86 ++++++++++++++++++- test/cpp/end2end/test_service_impl.cc | 17 +++- 6 files changed, 173 insertions(+), 7 deletions(-) diff --git a/src/core/lib/iomgr/iomgr.h b/src/core/lib/iomgr/iomgr.h index 6261aa550c3..74775de8146 100644 --- a/src/core/lib/iomgr/iomgr.h +++ b/src/core/lib/iomgr/iomgr.h @@ -39,6 +39,11 @@ void grpc_iomgr_shutdown(); * background poller. */ void grpc_iomgr_shutdown_background_closure(); +/* Returns true if polling engine runs in the background, false otherwise. + * Currently only 'epollbg' runs in the background. + */ +bool grpc_iomgr_run_in_background(); + /** Returns true if the caller is a worker thread for any background poller. */ bool grpc_iomgr_is_any_background_poller_thread(); diff --git a/src/core/lib/iomgr/iomgr_posix.cc b/src/core/lib/iomgr/iomgr_posix.cc index 278c8de6886..690e81f3b1d 100644 --- a/src/core/lib/iomgr/iomgr_posix.cc +++ b/src/core/lib/iomgr/iomgr_posix.cc @@ -74,4 +74,8 @@ void grpc_set_default_iomgr_platform() { grpc_set_iomgr_platform_vtable(&vtable); } +bool grpc_iomgr_run_in_background() { + return grpc_event_engine_run_in_background(); +} + #endif /* GRPC_POSIX_SOCKET_IOMGR */ diff --git a/src/core/lib/iomgr/iomgr_windows.cc b/src/core/lib/iomgr/iomgr_windows.cc index 0579e16aa76..e517a6caee4 100644 --- a/src/core/lib/iomgr/iomgr_windows.cc +++ b/src/core/lib/iomgr/iomgr_windows.cc @@ -92,4 +92,6 @@ void grpc_set_default_iomgr_platform() { grpc_set_iomgr_platform_vtable(&vtable); } +bool grpc_iomgr_run_in_background() { return false; } + #endif /* GRPC_WINSOCK_SOCKET */ diff --git a/test/cpp/end2end/client_callback_end2end_test.cc b/test/cpp/end2end/client_callback_end2end_test.cc index a999321992f..30db5b8c01c 100644 --- a/test/cpp/end2end/client_callback_end2end_test.cc +++ b/test/cpp/end2end/client_callback_end2end_test.cc @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -30,7 +31,9 @@ #include #include +#include "src/core/lib/iomgr/iomgr.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" +#include "test/core/util/port.h" #include "test/core/util/test_config.h" #include "test/cpp/end2end/test_service_impl.h" #include "test/cpp/util/byte_buffer_proto_helper.h" @@ -38,15 +41,30 @@ #include +// MAYBE_SKIP_TEST is a macro to determine if this particular test configuration +// should be skipped based on a decision made at SetUp time. In particular, any +// callback tests can only be run if the iomgr can run in the background or if +// the transport is in-process. +#define MAYBE_SKIP_TEST \ + do { \ + if (do_not_test_) { \ + return; \ + } \ + } while (0) + namespace grpc { namespace testing { namespace { +enum class Protocol { INPROC, TCP }; + class TestScenario { public: - TestScenario(bool serve_callback) : callback_server(serve_callback) {} + TestScenario(bool serve_callback, Protocol protocol) + : callback_server(serve_callback), protocol(protocol) {} void Log() const; bool callback_server; + Protocol protocol; }; static std::ostream& operator<<(std::ostream& out, @@ -69,6 +87,16 @@ class ClientCallbackEnd2endTest void SetUp() override { ServerBuilder builder; + if (GetParam().protocol == Protocol::TCP) { + if (!grpc_iomgr_run_in_background()) { + do_not_test_ = true; + return; + } + int port = grpc_pick_unused_port_or_die(); + server_address_ << "localhost:" << port; + builder.AddListeningPort(server_address_.str(), + InsecureServerCredentials()); + } if (!GetParam().callback_server) { builder.RegisterService(&service_); } else { @@ -81,7 +109,17 @@ class ClientCallbackEnd2endTest void ResetStub() { ChannelArguments args; - channel_ = server_->InProcessChannel(args); + switch (GetParam().protocol) { + case Protocol::TCP: + channel_ = + CreateChannel(server_address_.str(), InsecureChannelCredentials()); + break; + case Protocol::INPROC: + channel_ = server_->InProcessChannel(args); + break; + default: + assert(false); + } stub_ = grpc::testing::EchoTestService::NewStub(channel_); generic_stub_.reset(new GenericStub(channel_)); } @@ -243,26 +281,31 @@ class ClientCallbackEnd2endTest rpc.Await(); } } - bool is_server_started_; + bool do_not_test_{false}; + bool is_server_started_{false}; std::shared_ptr channel_; std::unique_ptr stub_; std::unique_ptr generic_stub_; TestServiceImpl service_; CallbackTestServiceImpl callback_service_; std::unique_ptr server_; + std::ostringstream server_address_; }; TEST_P(ClientCallbackEnd2endTest, SimpleRpc) { + MAYBE_SKIP_TEST; ResetStub(); SendRpcs(1, false); } TEST_P(ClientCallbackEnd2endTest, SequentialRpcs) { + MAYBE_SKIP_TEST; ResetStub(); SendRpcs(10, false); } TEST_P(ClientCallbackEnd2endTest, SendClientInitialMetadata) { + MAYBE_SKIP_TEST; ResetStub(); SimpleRequest request; SimpleResponse response; @@ -289,38 +332,45 @@ TEST_P(ClientCallbackEnd2endTest, SendClientInitialMetadata) { } TEST_P(ClientCallbackEnd2endTest, SimpleRpcWithBinaryMetadata) { + MAYBE_SKIP_TEST; ResetStub(); SendRpcs(1, true); } TEST_P(ClientCallbackEnd2endTest, SequentialRpcsWithVariedBinaryMetadataValue) { + MAYBE_SKIP_TEST; ResetStub(); SendRpcs(10, true); } TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcs) { + MAYBE_SKIP_TEST; ResetStub(); SendRpcsGeneric(10, false); } TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidi) { + MAYBE_SKIP_TEST; ResetStub(); SendGenericEchoAsBidi(10, 1); } TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidiWithReactorReuse) { + MAYBE_SKIP_TEST; ResetStub(); SendGenericEchoAsBidi(10, 10); } #if GRPC_ALLOW_EXCEPTIONS TEST_P(ClientCallbackEnd2endTest, ExceptingRpc) { + MAYBE_SKIP_TEST; ResetStub(); SendRpcsGeneric(10, true); } #endif TEST_P(ClientCallbackEnd2endTest, MultipleRpcsWithVariedBinaryMetadataValue) { + MAYBE_SKIP_TEST; ResetStub(); std::vector threads; threads.reserve(10); @@ -333,6 +383,7 @@ TEST_P(ClientCallbackEnd2endTest, MultipleRpcsWithVariedBinaryMetadataValue) { } TEST_P(ClientCallbackEnd2endTest, MultipleRpcs) { + MAYBE_SKIP_TEST; ResetStub(); std::vector threads; threads.reserve(10); @@ -345,6 +396,7 @@ TEST_P(ClientCallbackEnd2endTest, MultipleRpcs) { } TEST_P(ClientCallbackEnd2endTest, CancelRpcBeforeStart) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -370,6 +422,7 @@ TEST_P(ClientCallbackEnd2endTest, CancelRpcBeforeStart) { } TEST_P(ClientCallbackEnd2endTest, RequestStream) { + MAYBE_SKIP_TEST; ResetStub(); class Client : public grpc::experimental::ClientWriteReactor { public: @@ -416,6 +469,7 @@ TEST_P(ClientCallbackEnd2endTest, RequestStream) { } TEST_P(ClientCallbackEnd2endTest, ResponseStream) { + MAYBE_SKIP_TEST; ResetStub(); class Client : public grpc::experimental::ClientReadReactor { public: @@ -463,6 +517,7 @@ TEST_P(ClientCallbackEnd2endTest, ResponseStream) { } TEST_P(ClientCallbackEnd2endTest, BidiStream) { + MAYBE_SKIP_TEST; ResetStub(); class Client : public grpc::experimental::ClientBidiReactor { @@ -519,7 +574,10 @@ TEST_P(ClientCallbackEnd2endTest, BidiStream) { test.Await(); } -TestScenario scenarios[] = {TestScenario{false}, TestScenario{true}}; +TestScenario scenarios[]{{false, Protocol::INPROC}, + {false, Protocol::TCP}, + {true, Protocol::INPROC}, + {true, Protocol::TCP}}; INSTANTIATE_TEST_CASE_P(ClientCallbackEnd2endTest, ClientCallbackEnd2endTest, ::testing::ValuesIn(scenarios)); diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 4bddbb4bdf2..f58a472bfaf 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -35,6 +35,7 @@ #include #include "src/core/lib/gpr/env.h" +#include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" @@ -52,6 +53,17 @@ using grpc::testing::EchoResponse; using grpc::testing::kTlsCredentialsType; using std::chrono::system_clock; +// MAYBE_SKIP_TEST is a macro to determine if this particular test configuration +// should be skipped based on a decision made at SetUp time. In particular, +// tests that use the callback server can only be run if the iomgr can run in +// the background or if the transport is in-process. +#define MAYBE_SKIP_TEST \ + do { \ + if (do_not_test_) { \ + return; \ + } \ + } while (0) + namespace grpc { namespace testing { namespace { @@ -237,6 +249,14 @@ class End2endTest : public ::testing::TestWithParam { GetParam().Log(); } + void SetUp() override { + if (GetParam().callback_server && !GetParam().inproc && + !grpc_iomgr_run_in_background()) { + do_not_test_ = true; + return; + } + } + void TearDown() override { if (is_server_started_) { server_->Shutdown(); @@ -361,6 +381,7 @@ class End2endTest : public ::testing::TestWithParam { DummyInterceptor::Reset(); } + bool do_not_test_{false}; bool is_server_started_; std::shared_ptr channel_; std::unique_ptr stub_; @@ -416,6 +437,7 @@ class End2endServerTryCancelTest : public End2endTest { // NOTE: Do not call this function with server_try_cancel == DO_NOT_CANCEL. void TestRequestStreamServerCancel( ServerTryCancelRequestPhase server_try_cancel, int num_msgs_to_send) { + MAYBE_SKIP_TEST; RestartServer(std::shared_ptr()); ResetStub(); EchoRequest request; @@ -494,6 +516,7 @@ class End2endServerTryCancelTest : public End2endTest { // NOTE: Do not call this function with server_try_cancel == DO_NOT_CANCEL. void TestResponseStreamServerCancel( ServerTryCancelRequestPhase server_try_cancel) { + MAYBE_SKIP_TEST; RestartServer(std::shared_ptr()); ResetStub(); EchoRequest request; @@ -575,6 +598,7 @@ class End2endServerTryCancelTest : public End2endTest { // NOTE: Do not call this function with server_try_cancel == DO_NOT_CANCEL. void TestBidiStreamServerCancel(ServerTryCancelRequestPhase server_try_cancel, int num_messages) { + MAYBE_SKIP_TEST; RestartServer(std::shared_ptr()); ResetStub(); EchoRequest request; @@ -650,6 +674,7 @@ class End2endServerTryCancelTest : public End2endTest { }; TEST_P(End2endServerTryCancelTest, RequestEchoServerCancel) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -712,6 +737,7 @@ TEST_P(End2endServerTryCancelTest, BidiStreamServerCancelAfter) { } TEST_P(End2endTest, SimpleRpcWithCustomUserAgentPrefix) { + MAYBE_SKIP_TEST; // User-Agent is an HTTP header for HTTP transports only if (GetParam().inproc) { return; @@ -735,6 +761,7 @@ TEST_P(End2endTest, SimpleRpcWithCustomUserAgentPrefix) { } TEST_P(End2endTest, MultipleRpcsWithVariedBinaryMetadataValue) { + MAYBE_SKIP_TEST; ResetStub(); std::vector threads; threads.reserve(10); @@ -747,6 +774,7 @@ TEST_P(End2endTest, MultipleRpcsWithVariedBinaryMetadataValue) { } TEST_P(End2endTest, MultipleRpcs) { + MAYBE_SKIP_TEST; ResetStub(); std::vector threads; threads.reserve(10); @@ -759,6 +787,7 @@ TEST_P(End2endTest, MultipleRpcs) { } TEST_P(End2endTest, EmptyBinaryMetadata) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -771,6 +800,7 @@ TEST_P(End2endTest, EmptyBinaryMetadata) { } TEST_P(End2endTest, ReconnectChannel) { + MAYBE_SKIP_TEST; if (GetParam().inproc) { return; } @@ -796,6 +826,7 @@ TEST_P(End2endTest, ReconnectChannel) { } TEST_P(End2endTest, RequestStreamOneRequest) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -812,6 +843,7 @@ TEST_P(End2endTest, RequestStreamOneRequest) { } TEST_P(End2endTest, RequestStreamOneRequestWithCoalescingApi) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -827,6 +859,7 @@ TEST_P(End2endTest, RequestStreamOneRequestWithCoalescingApi) { } TEST_P(End2endTest, RequestStreamTwoRequests) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -843,6 +876,7 @@ TEST_P(End2endTest, RequestStreamTwoRequests) { } TEST_P(End2endTest, RequestStreamTwoRequestsWithWriteThrough) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -859,6 +893,7 @@ TEST_P(End2endTest, RequestStreamTwoRequestsWithWriteThrough) { } TEST_P(End2endTest, RequestStreamTwoRequestsWithCoalescingApi) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -875,6 +910,7 @@ TEST_P(End2endTest, RequestStreamTwoRequestsWithCoalescingApi) { } TEST_P(End2endTest, ResponseStream) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -893,6 +929,7 @@ TEST_P(End2endTest, ResponseStream) { } TEST_P(End2endTest, ResponseStreamWithCoalescingApi) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -914,6 +951,7 @@ TEST_P(End2endTest, ResponseStreamWithCoalescingApi) { // This was added to prevent regression from issue: // https://github.com/grpc/grpc/issues/11546 TEST_P(End2endTest, ResponseStreamWithEverythingCoalesced) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -935,6 +973,7 @@ TEST_P(End2endTest, ResponseStreamWithEverythingCoalesced) { } TEST_P(End2endTest, BidiStream) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -959,6 +998,7 @@ TEST_P(End2endTest, BidiStream) { } TEST_P(End2endTest, BidiStreamWithCoalescingApi) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -994,6 +1034,7 @@ TEST_P(End2endTest, BidiStreamWithCoalescingApi) { // This was added to prevent regression from issue: // https://github.com/grpc/grpc/issues/11546 TEST_P(End2endTest, BidiStreamWithEverythingCoalesced) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1019,6 +1060,7 @@ TEST_P(End2endTest, BidiStreamWithEverythingCoalesced) { // Talk to the two services with the same name but different package names. // The two stubs are created on the same channel. TEST_P(End2endTest, DiffPackageServices) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1047,6 +1089,7 @@ void CancelRpc(ClientContext* context, int delay_us, ServiceType* service) { } TEST_P(End2endTest, CancelRpcBeforeStart) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1063,6 +1106,7 @@ TEST_P(End2endTest, CancelRpcBeforeStart) { // Client cancels request stream after sending two messages TEST_P(End2endTest, ClientCancelsRequestStream) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1086,6 +1130,7 @@ TEST_P(End2endTest, ClientCancelsRequestStream) { // Client cancels server stream after sending some messages TEST_P(End2endTest, ClientCancelsResponseStream) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1121,6 +1166,7 @@ TEST_P(End2endTest, ClientCancelsResponseStream) { // Client cancels bidi stream after sending some messages TEST_P(End2endTest, ClientCancelsBidi) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1156,6 +1202,7 @@ TEST_P(End2endTest, ClientCancelsBidi) { } TEST_P(End2endTest, RpcMaxMessageSize) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1178,6 +1225,7 @@ void ReaderThreadFunc(ClientReaderWriter* stream, // Run a Read and a WritesDone simultaneously. TEST_P(End2endTest, SimultaneousReadWritesDone) { + MAYBE_SKIP_TEST; ResetStub(); ClientContext context; gpr_event ev; @@ -1192,6 +1240,7 @@ TEST_P(End2endTest, SimultaneousReadWritesDone) { } TEST_P(End2endTest, ChannelState) { + MAYBE_SKIP_TEST; if (GetParam().inproc) { return; } @@ -1242,6 +1291,7 @@ TEST_P(End2endTest, ChannelStateTimeout) { // Talking to a non-existing service. TEST_P(End2endTest, NonExistingService) { + MAYBE_SKIP_TEST; ResetChannel(); std::unique_ptr stub; stub = grpc::testing::UnimplementedEchoService::NewStub(channel_); @@ -1259,6 +1309,7 @@ TEST_P(End2endTest, NonExistingService) { // Ask the server to send back a serialized proto in trailer. // This is an example of setting error details. TEST_P(End2endTest, BinaryTrailerTest) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1285,6 +1336,7 @@ TEST_P(End2endTest, BinaryTrailerTest) { } TEST_P(End2endTest, ExpectErrorTest) { + MAYBE_SKIP_TEST; ResetStub(); std::vector expected_status; @@ -1336,11 +1388,13 @@ class ProxyEnd2endTest : public End2endTest { }; TEST_P(ProxyEnd2endTest, SimpleRpc) { + MAYBE_SKIP_TEST; ResetStub(); SendRpc(stub_.get(), 1, false); } TEST_P(ProxyEnd2endTest, SimpleRpcWithEmptyMessages) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1351,6 +1405,7 @@ TEST_P(ProxyEnd2endTest, SimpleRpcWithEmptyMessages) { } TEST_P(ProxyEnd2endTest, MultipleRpcs) { + MAYBE_SKIP_TEST; ResetStub(); std::vector threads; threads.reserve(10); @@ -1364,6 +1419,7 @@ TEST_P(ProxyEnd2endTest, MultipleRpcs) { // Set a 10us deadline and make sure proper error is returned. TEST_P(ProxyEnd2endTest, RpcDeadlineExpires) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1389,6 +1445,7 @@ TEST_P(ProxyEnd2endTest, RpcDeadlineExpires) { // Set a long but finite deadline. TEST_P(ProxyEnd2endTest, RpcLongDeadline) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1405,6 +1462,7 @@ TEST_P(ProxyEnd2endTest, RpcLongDeadline) { // Ask server to echo back the deadline it sees. TEST_P(ProxyEnd2endTest, EchoDeadline) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1430,6 +1488,7 @@ TEST_P(ProxyEnd2endTest, EchoDeadline) { // Ask server to echo back the deadline it sees. The rpc has no deadline. TEST_P(ProxyEnd2endTest, EchoDeadlineForNoDeadlineRpc) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1445,6 +1504,7 @@ TEST_P(ProxyEnd2endTest, EchoDeadlineForNoDeadlineRpc) { } TEST_P(ProxyEnd2endTest, UnimplementedRpc) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1460,6 +1520,7 @@ TEST_P(ProxyEnd2endTest, UnimplementedRpc) { // Client cancels rpc after 10ms TEST_P(ProxyEnd2endTest, ClientCancelsRpc) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1494,6 +1555,7 @@ TEST_P(ProxyEnd2endTest, ClientCancelsRpc) { // Server cancels rpc after 1ms TEST_P(ProxyEnd2endTest, ServerCancelsRpc) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1508,6 +1570,7 @@ TEST_P(ProxyEnd2endTest, ServerCancelsRpc) { // Make the response larger than the flow control window. TEST_P(ProxyEnd2endTest, HugeResponse) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1525,6 +1588,7 @@ TEST_P(ProxyEnd2endTest, HugeResponse) { } TEST_P(ProxyEnd2endTest, Peer) { + MAYBE_SKIP_TEST; // Peer is not meaningful for inproc if (GetParam().inproc) { return; @@ -1553,6 +1617,7 @@ class SecureEnd2endTest : public End2endTest { }; TEST_P(SecureEnd2endTest, SimpleRpcWithHost) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; @@ -1584,6 +1649,7 @@ bool MetadataContains( } TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginAndProcessorSuccess) { + MAYBE_SKIP_TEST; auto* processor = new TestAuthMetadataProcessor(true); StartServer(std::shared_ptr(processor)); ResetStub(); @@ -1609,6 +1675,7 @@ TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginAndProcessorSuccess) { } TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginAndProcessorFailure) { + MAYBE_SKIP_TEST; auto* processor = new TestAuthMetadataProcessor(true); StartServer(std::shared_ptr(processor)); ResetStub(); @@ -1624,6 +1691,7 @@ TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginAndProcessorFailure) { } TEST_P(SecureEnd2endTest, SetPerCallCredentials) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1646,6 +1714,7 @@ TEST_P(SecureEnd2endTest, SetPerCallCredentials) { } TEST_P(SecureEnd2endTest, OverridePerCallCredentials) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1677,6 +1746,7 @@ TEST_P(SecureEnd2endTest, OverridePerCallCredentials) { } TEST_P(SecureEnd2endTest, AuthMetadataPluginKeyFailure) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1694,6 +1764,7 @@ TEST_P(SecureEnd2endTest, AuthMetadataPluginKeyFailure) { } TEST_P(SecureEnd2endTest, AuthMetadataPluginValueFailure) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1711,6 +1782,7 @@ TEST_P(SecureEnd2endTest, AuthMetadataPluginValueFailure) { } TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1732,6 +1804,7 @@ TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) { } TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginAndProcessorSuccess) { + MAYBE_SKIP_TEST; auto* processor = new TestAuthMetadataProcessor(false); StartServer(std::shared_ptr(processor)); ResetStub(); @@ -1757,6 +1830,7 @@ TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginAndProcessorSuccess) { } TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginAndProcessorFailure) { + MAYBE_SKIP_TEST; auto* processor = new TestAuthMetadataProcessor(false); StartServer(std::shared_ptr(processor)); ResetStub(); @@ -1772,6 +1846,7 @@ TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginAndProcessorFailure) { } TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginFailure) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1793,6 +1868,7 @@ TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginFailure) { } TEST_P(SecureEnd2endTest, CompositeCallCreds) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1821,6 +1897,7 @@ TEST_P(SecureEnd2endTest, CompositeCallCreds) { } TEST_P(SecureEnd2endTest, ClientAuthContext) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; EchoResponse response; @@ -1865,6 +1942,7 @@ class ResourceQuotaEnd2endTest : public End2endTest { }; TEST_P(ResourceQuotaEnd2endTest, SimpleRequest) { + MAYBE_SKIP_TEST; ResetStub(); EchoRequest request; @@ -1899,11 +1977,17 @@ std::vector CreateTestScenarios(bool use_proxy, credentials_types.push_back(kInsecureCredentialsType); } - // For now test callback server only with inproc + // Test callback with inproc or if the event-engine allows it GPR_ASSERT(!credentials_types.empty()); for (const auto& cred : credentials_types) { scenarios.emplace_back(false, false, false, cred, false); scenarios.emplace_back(true, false, false, cred, false); + if (test_callback_server) { + // Note that these scenarios will be dynamically disabled if the event + // engine doesn't run in the background + scenarios.emplace_back(false, false, false, cred, true); + scenarios.emplace_back(true, false, false, cred, true); + } if (use_proxy) { scenarios.emplace_back(false, true, false, cred, false); scenarios.emplace_back(true, true, false, cred, false); diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc index 6729ad14f4a..8c2df1acc33 100644 --- a/test/cpp/end2end/test_service_impl.cc +++ b/test/cpp/end2end/test_service_impl.cc @@ -670,6 +670,8 @@ CallbackTestServiceImpl::ResponseStream() { void OnWriteDone(bool ok) override { if (num_msgs_sent_ < server_responses_to_send_) { NextWrite(); + } else if (server_coalescing_api_ != 0) { + // We would have already done Finish just after the WriteLast } else if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { // Let OnCancel recover this } else if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { @@ -695,6 +697,8 @@ CallbackTestServiceImpl::ResponseStream() { server_coalescing_api_ != 0) { num_msgs_sent_++; StartWriteLast(&response_, WriteOptions()); + // If we use WriteLast, we shouldn't wait before attempting Finish + FinishOnce(Status::OK); } else { num_msgs_sent_++; StartWrite(&response_); @@ -753,10 +757,14 @@ CallbackTestServiceImpl::BidiStream() { response_.set_message(request_.message()); if (num_msgs_read_ == server_write_last_) { StartWriteLast(&response_, WriteOptions()); + // If we use WriteLast, we shouldn't wait before attempting Finish } else { StartWrite(&response_); + return; } - } else if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + } + + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { // Let OnCancel handle this } else if (server_try_cancel_ == CANCEL_AFTER_PROCESSING) { ServerTryCancelNonblocking(ctx_); @@ -764,7 +772,12 @@ CallbackTestServiceImpl::BidiStream() { FinishOnce(Status::OK); } } - void OnWriteDone(bool ok) override { StartRead(&request_); } + void OnWriteDone(bool ok) override { + std::lock_guard l(finish_mu_); + if (!finished_) { + StartRead(&request_); + } + } private: void FinishOnce(const Status& s) { From 5a44f700bb687f21e89ebf337f2a4170c45db36c Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 11 Feb 2019 16:23:16 -0800 Subject: [PATCH 208/218] Increase allocated space for cmsgs --- src/core/lib/iomgr/tcp_posix.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index 61db36bd99e..fb56e15295c 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -715,11 +715,13 @@ static void process_errors(grpc_tcp* tcp) { msg.msg_iovlen = 0; msg.msg_flags = 0; - // Allocate aligned space for cmsgs received along with a timestamps + /* Allocate aligned space for cmsgs received along with timestamps */ union { - char rbuf[CMSG_SPACE(sizeof(grpc_core::scm_timestamping)) + + /* Allocate enough space so we don't need to keep increasing this as size + * of OPT_STATS increase */ + char rbuf[1024 /*CMSG_SPACE(sizeof(grpc_core::scm_timestamping)) + CMSG_SPACE(sizeof(sock_extended_err) + sizeof(sockaddr_in)) + - CMSG_SPACE(16 * NLA_ALIGN(NLA_HDRLEN + sizeof(uint64_t)))]; + CMSG_SPACE(16 * NLA_ALIGN(NLA_HDRLEN + sizeof(uint64_t)))*/]; struct cmsghdr align; } aligned_buf; memset(&aligned_buf, 0, sizeof(aligned_buf)); @@ -739,10 +741,8 @@ static void process_errors(grpc_tcp* tcp) { if (r == -1) { return; } - if (grpc_tcp_trace.enabled()) { - if ((msg.msg_flags & MSG_CTRUNC) == 1) { - gpr_log(GPR_INFO, "Error message was truncated."); - } + if ((msg.msg_flags & MSG_CTRUNC) == 1) { + gpr_log(GPR_ERROR, "Error message was truncated."); } if (msg.msg_controllen == 0) { From 6a372ff4426b0be01e1198ef2b4e60dd382d2b5f Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 11 Feb 2019 16:58:24 -0800 Subject: [PATCH 209/218] Use constexpr --- src/core/lib/iomgr/tcp_posix.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index fb56e15295c..b850b907ff6 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -715,13 +715,15 @@ static void process_errors(grpc_tcp* tcp) { msg.msg_iovlen = 0; msg.msg_flags = 0; + /* Allocate enough space so we don't need to keep increasing this as size + * of OPT_STATS increase */ + constexpr size_t cmsg_alloc_space = + 1024 /*CMSG_SPACE(sizeof(grpc_core::scm_timestamping)) + + CMSG_SPACE(sizeof(sock_extended_err) + sizeof(sockaddr_in)) + + CMSG_SPACE(16 * NLA_ALIGN(NLA_HDRLEN + sizeof(uint64_t)))*/; /* Allocate aligned space for cmsgs received along with timestamps */ union { - /* Allocate enough space so we don't need to keep increasing this as size - * of OPT_STATS increase */ - char rbuf[1024 /*CMSG_SPACE(sizeof(grpc_core::scm_timestamping)) + - CMSG_SPACE(sizeof(sock_extended_err) + sizeof(sockaddr_in)) + - CMSG_SPACE(16 * NLA_ALIGN(NLA_HDRLEN + sizeof(uint64_t)))*/]; + char rbuf[cmsg_alloc_space]; struct cmsghdr align; } aligned_buf; memset(&aligned_buf, 0, sizeof(aligned_buf)); From 5eeb651a5fd91de85ba30b2063aa8b8f82a33c55 Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Mon, 11 Feb 2019 17:16:15 -0800 Subject: [PATCH 210/218] Add extra space for opt_stats as part of the formula as opposed to 1024 --- src/core/lib/iomgr/tcp_posix.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index b850b907ff6..13ceffc6960 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -718,9 +718,9 @@ static void process_errors(grpc_tcp* tcp) { /* Allocate enough space so we don't need to keep increasing this as size * of OPT_STATS increase */ constexpr size_t cmsg_alloc_space = - 1024 /*CMSG_SPACE(sizeof(grpc_core::scm_timestamping)) + - CMSG_SPACE(sizeof(sock_extended_err) + sizeof(sockaddr_in)) + - CMSG_SPACE(16 * NLA_ALIGN(NLA_HDRLEN + sizeof(uint64_t)))*/; + CMSG_SPACE(sizeof(grpc_core::scm_timestamping)) + + CMSG_SPACE(sizeof(sock_extended_err) + sizeof(sockaddr_in)) + + CMSG_SPACE(32 * NLA_ALIGN(NLA_HDRLEN + sizeof(uint64_t))); /* Allocate aligned space for cmsgs received along with timestamps */ union { char rbuf[cmsg_alloc_space]; From db34fd2a94c47c69a62355c5a512d75ba327394f Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 11 Feb 2019 19:09:11 +0100 Subject: [PATCH 211/218] update Xamarin README.md --- examples/csharp/HelloworldXamarin/README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/examples/csharp/HelloworldXamarin/README.md b/examples/csharp/HelloworldXamarin/README.md index e47855de5e1..153a4f1b4dc 100644 --- a/examples/csharp/HelloworldXamarin/README.md +++ b/examples/csharp/HelloworldXamarin/README.md @@ -4,11 +4,6 @@ gRPC C# on Xamarin EXPERIMENTAL ONLY ------------- Support of the Xamarin platform is currently experimental. -The example depends on experimental Grpc.Core nuget package that hasn't -been officially released and is only available via the [daily builds](https://packages.grpc.io/) -source. - -HINT: To download the package, please manually download the latest `.nupkg` packages from "Daily Builds" in [packages.grpc.io](https://packages.grpc.io/) into a local directory. Then add a nuget source that points to that directory (That can be [done in Visual Studio](https://docs.microsoft.com/en-us/nuget/tools/package-manager-ui#package-sources) or Visual Studio for Mac via "Configure nuget sources"). After that, nuget will also explore that directory when looking for packages. BACKGROUND ------------- From a8a6e925b88d561ca5054bc7db13bda29ff74dbb Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 12 Feb 2019 11:44:36 +0100 Subject: [PATCH 212/218] update Grpc.Core in Xamarin example --- .../Droid/HelloworldXamarin.Droid.csproj | 8 ++++---- examples/csharp/HelloworldXamarin/Droid/packages.config | 2 +- .../HelloworldXamarin/iOS/HelloworldXamarin.iOS.csproj | 8 ++++---- examples/csharp/HelloworldXamarin/iOS/packages.config | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/csharp/HelloworldXamarin/Droid/HelloworldXamarin.Droid.csproj b/examples/csharp/HelloworldXamarin/Droid/HelloworldXamarin.Droid.csproj index b5ca8490a48..991fa0c9bcc 100644 --- a/examples/csharp/HelloworldXamarin/Droid/HelloworldXamarin.Droid.csproj +++ b/examples/csharp/HelloworldXamarin/Droid/HelloworldXamarin.Droid.csproj @@ -50,12 +50,12 @@ ..\packages\System.Interactive.Async.3.1.1\lib\netstandard1.3\System.Interactive.Async.dll - - ..\packages\Grpc.Core.1.15.0-dev\lib\netstandard1.5\Grpc.Core.dll - ..\packages\Google.Protobuf.3.6.0\lib\netstandard1.0\Google.Protobuf.dll + + ..\packages\Grpc.Core.1.18.0\lib\netstandard1.5\Grpc.Core.dll + @@ -79,5 +79,5 @@ - + \ No newline at end of file diff --git a/examples/csharp/HelloworldXamarin/Droid/packages.config b/examples/csharp/HelloworldXamarin/Droid/packages.config index 3574b6782b3..29201117298 100644 --- a/examples/csharp/HelloworldXamarin/Droid/packages.config +++ b/examples/csharp/HelloworldXamarin/Droid/packages.config @@ -1,7 +1,7 @@  - + diff --git a/examples/csharp/HelloworldXamarin/iOS/HelloworldXamarin.iOS.csproj b/examples/csharp/HelloworldXamarin/iOS/HelloworldXamarin.iOS.csproj index b5c0d1d1192..9154bf33527 100644 --- a/examples/csharp/HelloworldXamarin/iOS/HelloworldXamarin.iOS.csproj +++ b/examples/csharp/HelloworldXamarin/iOS/HelloworldXamarin.iOS.csproj @@ -89,12 +89,12 @@ ..\packages\System.Interactive.Async.3.1.1\lib\netstandard1.3\System.Interactive.Async.dll - - ..\packages\Grpc.Core.1.15.0-dev\lib\netstandard1.5\Grpc.Core.dll - ..\packages\Google.Protobuf.3.6.0\lib\netstandard1.0\Google.Protobuf.dll + + ..\packages\Grpc.Core.1.18.0\lib\netstandard1.5\Grpc.Core.dll + @@ -122,5 +122,5 @@ - + \ No newline at end of file diff --git a/examples/csharp/HelloworldXamarin/iOS/packages.config b/examples/csharp/HelloworldXamarin/iOS/packages.config index ce4bceb62a8..055222ba48f 100644 --- a/examples/csharp/HelloworldXamarin/iOS/packages.config +++ b/examples/csharp/HelloworldXamarin/iOS/packages.config @@ -1,7 +1,7 @@  - + From 593852c2ba39abd4194c498695a02a2426cf357c Mon Sep 17 00:00:00 2001 From: Arjun Roy Date: Tue, 12 Feb 2019 11:58:24 -0800 Subject: [PATCH 213/218] grpc handshaker linkage fixup --- src/core/lib/security/transport/security_handshaker.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/lib/security/transport/security_handshaker.cc b/src/core/lib/security/transport/security_handshaker.cc index a6fd2481a4a..5369574b854 100644 --- a/src/core/lib/security/transport/security_handshaker.cc +++ b/src/core/lib/security/transport/security_handshaker.cc @@ -496,11 +496,6 @@ RefCountedPtr SecurityHandshakerCreate( } } -grpc_handshaker* grpc_security_handshaker_create( - tsi_handshaker* handshaker, grpc_security_connector* connector) { - return SecurityHandshakerCreate(handshaker, connector).release(); -} - void SecurityRegisterHandshakerFactories() { HandshakerRegistry::RegisterHandshakerFactory( false /* at_start */, HANDSHAKER_CLIENT, @@ -511,3 +506,8 @@ void SecurityRegisterHandshakerFactories() { } } // namespace grpc_core + +grpc_handshaker* grpc_security_handshaker_create( + tsi_handshaker* handshaker, grpc_security_connector* connector) { + return SecurityHandshakerCreate(handshaker, connector).release(); +} From c78d456e0804265bc4b101e6f86ffa22862f8361 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 11 Feb 2019 13:20:35 +0100 Subject: [PATCH 214/218] add scaffolding for HelloworldUnity --- examples/csharp/HelloworldUnity/.gitignore | 52 ++ .../HelloworldUnity/Assets/Plugins.meta | 8 + .../csharp/HelloworldUnity/Assets/Scenes.meta | 8 + .../Assets/Scenes/SampleScene.unity | 586 ++++++++++++++++ .../Assets/Scenes/SampleScene.unity.meta | 7 + .../HelloworldUnity/Assets/Scripts.meta | 8 + .../Assets/Scripts/HelloWorldScript.cs | 92 +++ .../Assets/Scripts/HelloWorldScript.cs.meta | 11 + .../Assets/Scripts/Helloworld.cs | 286 ++++++++ .../Assets/Scripts/Helloworld.cs.meta | 11 + .../Assets/Scripts/HelloworldGrpc.cs | 150 ++++ .../Assets/Scripts/HelloworldGrpc.cs.meta | 11 + .../ProjectSettings/AudioManager.asset | 17 + .../ProjectSettings/ClusterInputManager.asset | 6 + .../ProjectSettings/DynamicsManager.asset | 29 + .../ProjectSettings/EditorBuildSettings.asset | 11 + .../ProjectSettings/EditorSettings.asset | 21 + .../ProjectSettings/GraphicsSettings.asset | 60 ++ .../ProjectSettings/InputManager.asset | 295 ++++++++ .../ProjectSettings/NavMeshAreas.asset | 91 +++ .../ProjectSettings/NetworkManager.asset | 8 + .../ProjectSettings/Physics2DSettings.asset | 55 ++ .../ProjectSettings/PresetManager.asset | 13 + .../ProjectSettings/ProjectSettings.asset | 656 ++++++++++++++++++ .../ProjectSettings/ProjectVersion.txt | 1 + .../ProjectSettings/QualitySettings.asset | 191 +++++ .../ProjectSettings/TagManager.asset | 43 ++ .../ProjectSettings/TimeManager.asset | 9 + .../UnityConnectSettings.asset | 34 + .../ProjectSettings/VFXManager.asset | 11 + .../UIElementsSchema/UIElements.xsd | 6 + .../UnityEditor.Experimental.UIElements.xsd | 228 ++++++ .../UnityEditor.PackageManager.UI.xsd | 116 ++++ .../UnityEngine.Experimental.UIElements.xsd | 269 +++++++ 34 files changed, 3400 insertions(+) create mode 100644 examples/csharp/HelloworldUnity/.gitignore create mode 100644 examples/csharp/HelloworldUnity/Assets/Plugins.meta create mode 100644 examples/csharp/HelloworldUnity/Assets/Scenes.meta create mode 100644 examples/csharp/HelloworldUnity/Assets/Scenes/SampleScene.unity create mode 100644 examples/csharp/HelloworldUnity/Assets/Scenes/SampleScene.unity.meta create mode 100644 examples/csharp/HelloworldUnity/Assets/Scripts.meta create mode 100644 examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs create mode 100644 examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs.meta create mode 100644 examples/csharp/HelloworldUnity/Assets/Scripts/Helloworld.cs create mode 100644 examples/csharp/HelloworldUnity/Assets/Scripts/Helloworld.cs.meta create mode 100644 examples/csharp/HelloworldUnity/Assets/Scripts/HelloworldGrpc.cs create mode 100644 examples/csharp/HelloworldUnity/Assets/Scripts/HelloworldGrpc.cs.meta create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/AudioManager.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/ClusterInputManager.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/DynamicsManager.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/EditorBuildSettings.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/EditorSettings.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/GraphicsSettings.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/InputManager.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/NavMeshAreas.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/NetworkManager.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/Physics2DSettings.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/PresetManager.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/ProjectSettings.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/ProjectVersion.txt create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/QualitySettings.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/TagManager.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/TimeManager.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/UnityConnectSettings.asset create mode 100644 examples/csharp/HelloworldUnity/ProjectSettings/VFXManager.asset create mode 100644 examples/csharp/HelloworldUnity/UIElementsSchema/UIElements.xsd create mode 100644 examples/csharp/HelloworldUnity/UIElementsSchema/UnityEditor.Experimental.UIElements.xsd create mode 100644 examples/csharp/HelloworldUnity/UIElementsSchema/UnityEditor.PackageManager.UI.xsd create mode 100644 examples/csharp/HelloworldUnity/UIElementsSchema/UnityEngine.Experimental.UIElements.xsd diff --git a/examples/csharp/HelloworldUnity/.gitignore b/examples/csharp/HelloworldUnity/.gitignore new file mode 100644 index 00000000000..6245af922f6 --- /dev/null +++ b/examples/csharp/HelloworldUnity/.gitignore @@ -0,0 +1,52 @@ +[Ll]ibrary/ +[Tt]emp/ +[Oo]bj/ +[Bb]uild/ +[Bb]uilds/ +[Ll]ogs/ + +# Never ignore Asset meta data +![Aa]ssets/**/*.meta + +# Uncomment this line if you wish to ignore the asset store tools plugin +# [Aa]ssets/AssetStoreTools* + +# Visual Studio cache directory +.vs/ + +# Gradle cache directory +.gradle/ + +# Autogenerated VS/MD/Consulo solution and project files +ExportedObj/ +.consulo/ +*.csproj +*.unityproj +*.sln +*.suo +*.tmp +*.user +*.userprefs +*.pidb +*.booproj +*.svd +*.pdb +*.mdb +*.opendb +*.VC.db + +# Unity3D generated meta files +*.pidb.meta +*.pdb.meta +*.mdb.meta + +# Unity3D generated file on crash reports +sysinfo.txt + +# Builds +*.apk +*.unitypackage + +# Crashlytics generated file +crashlytics-build.properties + diff --git a/examples/csharp/HelloworldUnity/Assets/Plugins.meta b/examples/csharp/HelloworldUnity/Assets/Plugins.meta new file mode 100644 index 00000000000..31c915a8752 --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9e39cea189b0245c4a39113ff6459d24 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/examples/csharp/HelloworldUnity/Assets/Scenes.meta b/examples/csharp/HelloworldUnity/Assets/Scenes.meta new file mode 100644 index 00000000000..7fe8e109da3 --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 131a6b21c8605f84396be9f6751fb6e3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/examples/csharp/HelloworldUnity/Assets/Scenes/SampleScene.unity b/examples/csharp/HelloworldUnity/Assets/Scenes/SampleScene.unity new file mode 100644 index 00000000000..8c5947d0f7b --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scenes/SampleScene.unity @@ -0,0 +1,586 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_TemporalCoherenceThreshold: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &519420028 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 519420032} + - component: {fileID: 519420031} + - component: {fileID: 519420029} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &519420029 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 519420028} + m_Enabled: 1 +--- !u!20 &519420031 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 519420028} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 2 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 0 + m_HDR: 1 + m_AllowMSAA: 0 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 0 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &519420032 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 519420028} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &785253852 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 785253855} + - component: {fileID: 785253854} + - component: {fileID: 785253853} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &785253853 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 785253852} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &785253854 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 785253852} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &785253855 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 785253852} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1639505844 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1639505846} + - component: {fileID: 1639505845} + m_Layer: 0 + m_Name: UIManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1639505845 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1639505844} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d62381e23356a4203b3e54cc6c2e3a4f, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &1639505846 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1639505844} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1729899994 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1729899995} + - component: {fileID: 1729899997} + - component: {fileID: 1729899996} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1729899995 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1729899994} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2040475500} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1729899996 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1729899994} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Hello gRPC!!! +--- !u!222 &1729899997 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1729899994} + m_CullTransparentMesh: 0 +--- !u!1 &2040475499 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2040475500} + - component: {fileID: 2040475503} + - component: {fileID: 2040475502} + - component: {fileID: 2040475501} + m_Layer: 5 + m_Name: Button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2040475500 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2040475499} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1729899995} + m_Father: {fileID: 2066701619} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 500, y: 150} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2040475501 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2040475499} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 2040475502} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1639505845} + m_MethodName: RunHelloWorld + m_Mode: 2 + m_Arguments: + m_ObjectArgument: {fileID: 1729899996} + m_ObjectArgumentAssemblyTypeName: UnityEngine.UI.Text, UnityEngine.UI + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &2040475502 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2040475499} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.34157702, g: 0.6037736, b: 0.093983635, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 +--- !u!222 &2040475503 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2040475499} + m_CullTransparentMesh: 0 +--- !u!1 &2066701615 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2066701619} + - component: {fileID: 2066701618} + - component: {fileID: 2066701617} + - component: {fileID: 2066701616} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2066701616 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2066701615} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &2066701617 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2066701615} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!223 &2066701618 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2066701615} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &2066701619 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2066701615} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 2040475500} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} diff --git a/examples/csharp/HelloworldUnity/Assets/Scenes/SampleScene.unity.meta b/examples/csharp/HelloworldUnity/Assets/Scenes/SampleScene.unity.meta new file mode 100644 index 00000000000..c1e3c88e1cf --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scenes/SampleScene.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2cda990e2423bbf4892e6590ba056729 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts.meta b/examples/csharp/HelloworldUnity/Assets/Scripts.meta new file mode 100644 index 00000000000..49e35f97956 --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 55598493aa3774a6dad4b7a4974826ff +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs new file mode 100644 index 00000000000..6d318bcc348 --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs @@ -0,0 +1,92 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +using Helloworld; +using System.Threading.Tasks; + +using System; + +using UnityEngine.SceneManagement; + +using Grpc.Core; + +public class HelloWorldScript : MonoBehaviour { + const int Port = 50051; + int counter = 1; + // Use this for initialization + void Start () { + //Console.WriteLine("dfsdfadfffa dfasfa"); + + + } + + public void RunHelloWorld(Text text) + { + //Debug.Log("dfasfa"); + //var channel = new Channel("localhost:12345", ChannelCredentials.Insecure); + //SceneManager.LoadScene("RocketMouse"); + + + //var unityApplicationClass = Type.GetType("UnityEngine.Application, UnityEngine"); + // Consult value of Application.platform via reflection + // https://docs.unity3d.com/ScriptReference/Application-platform.html + // var platformProperty = unityApplicationClass.GetTypeInfo().GetProperty("platform"); + // var unityRuntimePlatform = platformProperty?.GetValue(null)?.ToString(); + //var isUnityIOS = (unityRuntimePlatform == "IPhonePlayer"); + + var t = Type.GetType("UnityEngine.Application, UnityEngine"); + var propInfo = t.GetProperty("platform"); + var reflPlatform = propInfo.GetValue(null).ToString(); + + + Debug.Log("Appl. platform:" + Application.platform); + Debug.Log("Appl. platform:" + reflPlatform); + Debug.Log("Environment.OSVersion: " + Environment.OSVersion); + + + Server server = new Server + { + Services = { Greeter.BindService(new GreeterImpl()) }, + Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } + }; + server.Start(); + + Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure); + + var client = new Greeter.GreeterClient(channel); + String user = "Unity " + counter; + + var reply = client.SayHello(new HelloRequest { Name = user }); + + + text.text = "Greeting: " + reply.Message; + + channel.ShutdownAsync().Wait(); + + server.ShutdownAsync().Wait(); + + counter ++; + + + + //Debug.Log("channel: created channel"); + + + } + + // Update is called once per frame + void Update () { + + } + + class GreeterImpl : Greeter.GreeterBase + { + // Server side handler of the SayHello RPC + public override Task SayHello(HelloRequest request, ServerCallContext context) + { + return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); + } + } +} diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs.meta b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs.meta new file mode 100644 index 00000000000..60b0ea38c08 --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d62381e23356a4203b3e54cc6c2e3a4f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/Helloworld.cs b/examples/csharp/HelloworldUnity/Assets/Scripts/Helloworld.cs new file mode 100644 index 00000000000..ecfc8e131cb --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/Helloworld.cs @@ -0,0 +1,286 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: helloworld.proto +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Helloworld { + + /// Holder for reflection information generated from helloworld.proto + public static partial class HelloworldReflection { + + #region Descriptor + /// File descriptor for helloworld.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static HelloworldReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChBoZWxsb3dvcmxkLnByb3RvEgpoZWxsb3dvcmxkIhwKDEhlbGxvUmVxdWVz", + "dBIMCgRuYW1lGAEgASgJIh0KCkhlbGxvUmVwbHkSDwoHbWVzc2FnZRgBIAEo", + "CTJJCgdHcmVldGVyEj4KCFNheUhlbGxvEhguaGVsbG93b3JsZC5IZWxsb1Jl", + "cXVlc3QaFi5oZWxsb3dvcmxkLkhlbGxvUmVwbHkiAEI2Chtpby5ncnBjLmV4", + "YW1wbGVzLmhlbGxvd29ybGRCD0hlbGxvV29ybGRQcm90b1ABogIDSExXYgZw", + "cm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloRequest), global::Helloworld.HelloRequest.Parser, new[]{ "Name" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloReply), global::Helloworld.HelloReply.Parser, new[]{ "Message" }, null, null, null) + })); + } + #endregion + + } + #region Messages + /// + /// The request message containing the user's name. + /// + public sealed partial class HelloRequest : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HelloRequest()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloRequest(HelloRequest other) : this() { + name_ = other.name_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloRequest Clone() { + return new HelloRequest(this); + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 1; + private string name_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as HelloRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(HelloRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(HelloRequest other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + Name = input.ReadString(); + break; + } + } + } + } + + } + + /// + /// The response message containing the greetings + /// + public sealed partial class HelloReply : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HelloReply()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloReply() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloReply(HelloReply other) : this() { + message_ = other.message_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloReply Clone() { + return new HelloReply(this); + } + + /// Field number for the "message" field. + public const int MessageFieldNumber = 1; + private string message_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Message { + get { return message_; } + set { + message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as HelloReply); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(HelloReply other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Message != other.Message) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Message.Length != 0) hash ^= Message.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Message.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Message); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Message.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(HelloReply other) { + if (other == null) { + return; + } + if (other.Message.Length != 0) { + Message = other.Message; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + Message = input.ReadString(); + break; + } + } + } + } + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/Helloworld.cs.meta b/examples/csharp/HelloworldUnity/Assets/Scripts/Helloworld.cs.meta new file mode 100644 index 00000000000..7a43df02a17 --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/Helloworld.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8bfcdd9a5979d4cc7b76d17be585e778 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloworldGrpc.cs b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloworldGrpc.cs new file mode 100644 index 00000000000..c808884e579 --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloworldGrpc.cs @@ -0,0 +1,150 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: helloworld.proto +// Original file comments: +// 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. +// +#pragma warning disable 1591 +#region Designer generated code + +using System; +using System.Threading; +using System.Threading.Tasks; +using grpc = global::Grpc.Core; + +namespace Helloworld { + /// + /// The greeting service definition. + /// + public static partial class Greeter + { + static readonly string __ServiceName = "helloworld.Greeter"; + + static readonly grpc::Marshaller __Marshaller_HelloRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloRequest.Parser.ParseFrom); + static readonly grpc::Marshaller __Marshaller_HelloReply = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloReply.Parser.ParseFrom); + + static readonly grpc::Method __Method_SayHello = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "SayHello", + __Marshaller_HelloRequest, + __Marshaller_HelloReply); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Helloworld.HelloworldReflection.Descriptor.Services[0]; } + } + + /// Base class for server-side implementations of Greeter + public abstract partial class GreeterBase + { + /// + /// Sends a greeting + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + public virtual global::System.Threading.Tasks.Task SayHello(global::Helloworld.HelloRequest request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for Greeter + public partial class GreeterClient : grpc::ClientBase + { + /// Creates a new client for Greeter + /// The channel to use to make remote calls. + public GreeterClient(grpc::Channel channel) : base(channel) + { + } + /// Creates a new client for Greeter that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + public GreeterClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + protected GreeterClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + protected GreeterClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// Sends a greeting + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return SayHello(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Sends a greeting + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_SayHello, null, options, request); + } + /// + /// Sends a greeting + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + public virtual grpc::AsyncUnaryCall SayHelloAsync(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return SayHelloAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Sends a greeting + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + public virtual grpc::AsyncUnaryCall SayHelloAsync(global::Helloworld.HelloRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_SayHello, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + protected override GreeterClient NewInstance(ClientBaseConfiguration configuration) + { + return new GreeterClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + public static grpc::ServerServiceDefinition BindService(GreeterBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_SayHello, serviceImpl.SayHello).Build(); + } + + } +} +#endregion diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloworldGrpc.cs.meta b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloworldGrpc.cs.meta new file mode 100644 index 00000000000..e6a26fca3dc --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloworldGrpc.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf9b820c371a143ce96df8edaebb3fe2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/AudioManager.asset b/examples/csharp/HelloworldUnity/ProjectSettings/AudioManager.asset new file mode 100644 index 00000000000..304925ebde5 --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/AudioManager.asset @@ -0,0 +1,17 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!11 &1 +AudioManager: + m_ObjectHideFlags: 0 + m_Volume: 1 + Rolloff Scale: 1 + Doppler Factor: 1 + Default Speaker Mode: 2 + m_SampleRate: 0 + m_DSPBufferSize: 1024 + m_VirtualVoiceCount: 512 + m_RealVoiceCount: 32 + m_SpatializerPlugin: + m_AmbisonicDecoderPlugin: + m_DisableAudio: 0 + m_VirtualizeEffects: 1 diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/ClusterInputManager.asset b/examples/csharp/HelloworldUnity/ProjectSettings/ClusterInputManager.asset new file mode 100644 index 00000000000..a84cf4e6fe7 --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/ClusterInputManager.asset @@ -0,0 +1,6 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!236 &1 +ClusterInputManager: + m_ObjectHideFlags: 0 + m_Inputs: [] diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/DynamicsManager.asset b/examples/csharp/HelloworldUnity/ProjectSettings/DynamicsManager.asset new file mode 100644 index 00000000000..78992f08c7a --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/DynamicsManager.asset @@ -0,0 +1,29 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!55 &1 +PhysicsManager: + m_ObjectHideFlags: 0 + serializedVersion: 7 + m_Gravity: {x: 0, y: -9.81, z: 0} + m_DefaultMaterial: {fileID: 0} + m_BounceThreshold: 2 + m_SleepThreshold: 0.005 + m_DefaultContactOffset: 0.01 + m_DefaultSolverIterations: 6 + m_DefaultSolverVelocityIterations: 1 + m_QueriesHitBackfaces: 0 + m_QueriesHitTriggers: 1 + m_EnableAdaptiveForce: 0 + m_ClothInterCollisionDistance: 0 + m_ClothInterCollisionStiffness: 0 + m_ContactsGeneration: 1 + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + m_AutoSimulation: 1 + m_AutoSyncTransforms: 1 + m_ClothInterCollisionSettingsToggle: 0 + m_ContactPairsMode: 0 + m_BroadphaseType: 0 + m_WorldBounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 250, y: 250, z: 250} + m_WorldSubdivisions: 8 diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/EditorBuildSettings.asset b/examples/csharp/HelloworldUnity/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 00000000000..62c5a75b293 --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/EditorBuildSettings.asset @@ -0,0 +1,11 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1045 &1 +EditorBuildSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Scenes: + - enabled: 1 + path: Assets/Scenes/SampleScene.unity + guid: 2cda990e2423bbf4892e6590ba056729 + m_configObjects: {} diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/EditorSettings.asset b/examples/csharp/HelloworldUnity/ProjectSettings/EditorSettings.asset new file mode 100644 index 00000000000..3376fd8b501 --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/EditorSettings.asset @@ -0,0 +1,21 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!159 &1 +EditorSettings: + m_ObjectHideFlags: 0 + serializedVersion: 7 + m_ExternalVersionControlSupport: Visible Meta Files + m_SerializationMode: 2 + m_LineEndingsForNewScripts: 2 + m_DefaultBehaviorMode: 1 + m_SpritePackerMode: 4 + m_SpritePackerPaddingPower: 1 + m_EtcTextureCompressorBehavior: 1 + m_EtcTextureFastCompressor: 1 + m_EtcTextureNormalCompressor: 2 + m_EtcTextureBestCompressor: 4 + m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd + m_ProjectGenerationRootNamespace: + m_UserGeneratedProjectSuffix: + m_CollabEditorSettings: + inProgressEnabled: 1 diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/GraphicsSettings.asset b/examples/csharp/HelloworldUnity/ProjectSettings/GraphicsSettings.asset new file mode 100644 index 00000000000..b35e28eaf0f --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/GraphicsSettings.asset @@ -0,0 +1,60 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!30 &1 +GraphicsSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_Deferred: + m_Mode: 1 + m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} + m_DeferredReflections: + m_Mode: 1 + m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} + m_ScreenSpaceShadows: + m_Mode: 1 + m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} + m_LegacyDeferred: + m_Mode: 1 + m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} + m_DepthNormals: + m_Mode: 1 + m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} + m_MotionVectors: + m_Mode: 1 + m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} + m_LightHalo: + m_Mode: 1 + m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} + m_LensFlare: + m_Mode: 1 + m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} + m_AlwaysIncludedShaders: + - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 16002, guid: 0000000000000000f000000000000000, type: 0} + m_PreloadedShaders: [] + m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, + type: 0} + m_CustomRenderPipeline: {fileID: 0} + m_TransparencySortMode: 0 + m_TransparencySortAxis: {x: 0, y: 0, z: 1} + m_DefaultRenderingPath: 1 + m_DefaultMobileRenderingPath: 1 + m_TierSettings: [] + m_LightmapStripping: 0 + m_FogStripping: 0 + m_InstancingStripping: 0 + m_LightmapKeepPlain: 1 + m_LightmapKeepDirCombined: 1 + m_LightmapKeepDynamicPlain: 1 + m_LightmapKeepDynamicDirCombined: 1 + m_LightmapKeepShadowMask: 1 + m_LightmapKeepSubtractive: 1 + m_FogKeepLinear: 1 + m_FogKeepExp: 1 + m_FogKeepExp2: 1 + m_AlbedoSwatchInfos: [] + m_LightsUseLinearIntensity: 0 + m_LightsUseColorTemperature: 0 diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/InputManager.asset b/examples/csharp/HelloworldUnity/ProjectSettings/InputManager.asset new file mode 100644 index 00000000000..25966468fff --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/InputManager.asset @@ -0,0 +1,295 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!13 &1 +InputManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Axes: + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: a + altPositiveButton: d + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: s + altPositiveButton: w + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: mouse 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: mouse 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: mouse 2 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: space + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse X + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse Y + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse ScrollWheel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 2 + joyNum: 0 + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 0 + type: 2 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 1 + type: 2 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 0 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 1 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 2 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 3 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: enter + altNegativeButton: + altPositiveButton: space + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Cancel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: escape + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/NavMeshAreas.asset b/examples/csharp/HelloworldUnity/ProjectSettings/NavMeshAreas.asset new file mode 100644 index 00000000000..c8fa1b5bd1e --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/NavMeshAreas.asset @@ -0,0 +1,91 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!126 &1 +NavMeshProjectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + areas: + - name: Walkable + cost: 1 + - name: Not Walkable + cost: 1 + - name: Jump + cost: 2 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + m_LastAgentTypeID: -887442657 + m_Settings: + - serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.75 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_SettingNames: + - Humanoid diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/NetworkManager.asset b/examples/csharp/HelloworldUnity/ProjectSettings/NetworkManager.asset new file mode 100644 index 00000000000..e9cd5781b1a --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/NetworkManager.asset @@ -0,0 +1,8 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!149 &1 +NetworkManager: + m_ObjectHideFlags: 0 + m_DebugLevel: 0 + m_Sendrate: 15 + m_AssetToPrefab: {} diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/Physics2DSettings.asset b/examples/csharp/HelloworldUnity/ProjectSettings/Physics2DSettings.asset new file mode 100644 index 00000000000..8e9e0210986 --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/Physics2DSettings.asset @@ -0,0 +1,55 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!19 &1 +Physics2DSettings: + m_ObjectHideFlags: 0 + serializedVersion: 3 + m_Gravity: {x: 0, y: -9.81} + m_DefaultMaterial: {fileID: 0} + m_VelocityIterations: 8 + m_PositionIterations: 3 + m_VelocityThreshold: 1 + m_MaxLinearCorrection: 0.2 + m_MaxAngularCorrection: 8 + m_MaxTranslationSpeed: 100 + m_MaxRotationSpeed: 360 + m_BaumgarteScale: 0.2 + m_BaumgarteTimeOfImpactScale: 0.75 + m_TimeToSleep: 0.5 + m_LinearSleepTolerance: 0.01 + m_AngularSleepTolerance: 2 + m_DefaultContactOffset: 0.01 + m_JobOptions: + serializedVersion: 2 + useMultithreading: 0 + useConsistencySorting: 0 + m_InterpolationPosesPerJob: 100 + m_NewContactsPerJob: 30 + m_CollideContactsPerJob: 100 + m_ClearFlagsPerJob: 200 + m_ClearBodyForcesPerJob: 200 + m_SyncDiscreteFixturesPerJob: 50 + m_SyncContinuousFixturesPerJob: 50 + m_FindNearestContactsPerJob: 100 + m_UpdateTriggerContactsPerJob: 100 + m_IslandSolverCostThreshold: 100 + m_IslandSolverBodyCostScale: 1 + m_IslandSolverContactCostScale: 10 + m_IslandSolverJointCostScale: 10 + m_IslandSolverBodiesPerJob: 50 + m_IslandSolverContactsPerJob: 50 + m_AutoSimulation: 1 + m_QueriesHitTriggers: 1 + m_QueriesStartInColliders: 1 + m_CallbacksOnDisable: 1 + m_AutoSyncTransforms: 1 + m_AlwaysShowColliders: 0 + m_ShowColliderSleep: 1 + m_ShowColliderContacts: 0 + m_ShowColliderAABB: 0 + m_ContactArrowScale: 0.2 + m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} + m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} + m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} + m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/PresetManager.asset b/examples/csharp/HelloworldUnity/ProjectSettings/PresetManager.asset new file mode 100644 index 00000000000..0832099de85 --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/PresetManager.asset @@ -0,0 +1,13 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1386491679 &1 +PresetManager: + m_ObjectHideFlags: 0 + m_DefaultList: + - type: + m_NativeTypeID: 20 + m_ManagedTypePPtr: {fileID: 0} + m_ManagedTypeFallback: + defaultPresets: + - m_Preset: {fileID: 2655988077585873504, guid: bfcfc320427f8224bbb7a96f3d3aebad, + type: 2} diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/ProjectSettings.asset b/examples/csharp/HelloworldUnity/ProjectSettings/ProjectSettings.asset new file mode 100644 index 00000000000..b1e2fb0a430 --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,656 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 15 + productGUID: 2ed9f077cb8c7421b9d7c7fa18f3c25d + AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + AndroidEnableSustainedPerformanceMode: 0 + defaultScreenOrientation: 4 + targetDevice: 2 + useOnDemandResources: 0 + accelerometerFrequency: 60 + companyName: com.grpc.examples + productName: HelloworldUnity + defaultCursor: {fileID: 0} + cursorHotspot: {x: 0, y: 0} + m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} + m_ShowUnitySplashScreen: 1 + m_ShowUnitySplashLogo: 1 + m_SplashScreenOverlayOpacity: 1 + m_SplashScreenAnimation: 1 + m_SplashScreenLogoStyle: 1 + m_SplashScreenDrawMode: 0 + m_SplashScreenBackgroundAnimationZoom: 1 + m_SplashScreenLogoAnimationZoom: 1 + m_SplashScreenBackgroundLandscapeAspect: 1 + m_SplashScreenBackgroundPortraitAspect: 1 + m_SplashScreenBackgroundLandscapeUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenBackgroundPortraitUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenLogos: [] + m_VirtualRealitySplashScreen: {fileID: 0} + m_HolographicTrackingLossScreen: {fileID: 0} + defaultScreenWidth: 1024 + defaultScreenHeight: 768 + defaultScreenWidthWeb: 960 + defaultScreenHeightWeb: 600 + m_StereoRenderingPath: 0 + m_ActiveColorSpace: 0 + m_MTRendering: 1 + m_StackTraceTypes: 010000000100000001000000010000000100000001000000 + iosShowActivityIndicatorOnLoading: -1 + androidShowActivityIndicatorOnLoading: -1 + iosAppInBackgroundBehavior: 0 + displayResolutionDialog: 1 + iosAllowHTTPDownload: 1 + allowedAutorotateToPortrait: 1 + allowedAutorotateToPortraitUpsideDown: 1 + allowedAutorotateToLandscapeRight: 1 + allowedAutorotateToLandscapeLeft: 1 + useOSAutorotation: 1 + use32BitDisplayBuffer: 1 + preserveFramebufferAlpha: 0 + disableDepthAndStencilBuffers: 0 + androidStartInFullscreen: 1 + androidRenderOutsideSafeArea: 0 + androidBlitType: 0 + defaultIsNativeResolution: 1 + macRetinaSupport: 1 + runInBackground: 1 + captureSingleScreen: 0 + muteOtherAudioSources: 0 + Prepare IOS For Recording: 0 + Force IOS Speakers When Recording: 0 + deferSystemGesturesMode: 0 + hideHomeButton: 0 + submitAnalytics: 1 + usePlayerLog: 1 + bakeCollisionMeshes: 0 + forceSingleInstance: 0 + resizableWindow: 0 + useMacAppStoreValidation: 0 + macAppStoreCategory: public.app-category.games + gpuSkinning: 0 + graphicsJobs: 0 + xboxPIXTextureCapture: 0 + xboxEnableAvatar: 0 + xboxEnableKinect: 0 + xboxEnableKinectAutoTracking: 0 + xboxEnableFitness: 0 + visibleInBackground: 1 + allowFullscreenSwitch: 1 + graphicsJobMode: 0 + fullscreenMode: 1 + xboxSpeechDB: 0 + xboxEnableHeadOrientation: 0 + xboxEnableGuest: 0 + xboxEnablePIXSampling: 0 + metalFramebufferOnly: 0 + xboxOneResolution: 0 + xboxOneSResolution: 0 + xboxOneXResolution: 3 + xboxOneMonoLoggingLevel: 0 + xboxOneLoggingLevel: 1 + xboxOneDisableEsram: 0 + xboxOnePresentImmediateThreshold: 0 + switchQueueCommandMemory: 0 + vulkanEnableSetSRGBWrite: 0 + m_SupportedAspectRatios: + 4:3: 1 + 5:4: 1 + 16:10: 1 + 16:9: 1 + Others: 1 + bundleVersion: 0.1 + preloadedAssets: [] + metroInputSource: 0 + wsaTransparentSwapchain: 0 + m_HolographicPauseOnTrackingLoss: 1 + xboxOneDisableKinectGpuReservation: 0 + xboxOneEnable7thCore: 0 + isWsaHolographicRemotingEnabled: 0 + vrSettings: + cardboard: + depthFormat: 0 + enableTransitionView: 0 + daydream: + depthFormat: 0 + useSustainedPerformanceMode: 0 + enableVideoLayer: 0 + useProtectedVideoMemory: 0 + minimumSupportedHeadTracking: 0 + maximumSupportedHeadTracking: 1 + hololens: + depthFormat: 1 + depthBufferSharingEnabled: 0 + oculus: + sharedDepthBuffer: 0 + dashSupport: 0 + enable360StereoCapture: 0 + protectGraphicsMemory: 0 + enableFrameTimingStats: 0 + useHDRDisplay: 0 + m_ColorGamuts: 00000000 + targetPixelDensity: 30 + resolutionScalingMode: 0 + androidSupportedAspectRatio: 1 + androidMaxAspectRatio: 2.1 + applicationIdentifier: + Android: com.grpc.examples + Standalone: com.Company.ProductName + iOS: com.jattermusch.grpc.example + buildNumber: {} + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 16 + AndroidTargetSdkVersion: 0 + AndroidPreferredInstallLocation: 1 + aotOptions: + stripEngineCode: 1 + iPhoneStrippingLevel: 0 + iPhoneScriptCallOptimization: 0 + ForceInternetPermission: 0 + ForceSDCardPermission: 0 + CreateWallpaper: 0 + APKExpansionFiles: 0 + keepLoadedShadersAlive: 0 + StripUnusedMeshComponents: 1 + VertexChannelCompressionMask: 4054 + iPhoneSdkVersion: 989 + iOSTargetOSVersionString: 9.0 + tvOSSdkVersion: 0 + tvOSRequireExtendedGameController: 0 + tvOSTargetOSVersionString: 9.0 + uIPrerenderedIcon: 0 + uIRequiresPersistentWiFi: 0 + uIRequiresFullScreen: 1 + uIStatusBarHidden: 1 + uIExitOnSuspend: 0 + uIStatusBarStyle: 0 + iPhoneSplashScreen: {fileID: 0} + iPhoneHighResSplashScreen: {fileID: 0} + iPhoneTallHighResSplashScreen: {fileID: 0} + iPhone47inSplashScreen: {fileID: 0} + iPhone55inPortraitSplashScreen: {fileID: 0} + iPhone55inLandscapeSplashScreen: {fileID: 0} + iPhone58inPortraitSplashScreen: {fileID: 0} + iPhone58inLandscapeSplashScreen: {fileID: 0} + iPadPortraitSplashScreen: {fileID: 0} + iPadHighResPortraitSplashScreen: {fileID: 0} + iPadLandscapeSplashScreen: {fileID: 0} + iPadHighResLandscapeSplashScreen: {fileID: 0} + appleTVSplashScreen: {fileID: 0} + appleTVSplashScreen2x: {fileID: 0} + tvOSSmallIconLayers: [] + tvOSSmallIconLayers2x: [] + tvOSLargeIconLayers: [] + tvOSLargeIconLayers2x: [] + tvOSTopShelfImageLayers: [] + tvOSTopShelfImageLayers2x: [] + tvOSTopShelfImageWideLayers: [] + tvOSTopShelfImageWideLayers2x: [] + iOSLaunchScreenType: 0 + iOSLaunchScreenPortrait: {fileID: 0} + iOSLaunchScreenLandscape: {fileID: 0} + iOSLaunchScreenBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreenFillPct: 100 + iOSLaunchScreenSize: 100 + iOSLaunchScreenCustomXibPath: + iOSLaunchScreeniPadType: 0 + iOSLaunchScreeniPadImage: {fileID: 0} + iOSLaunchScreeniPadBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreeniPadFillPct: 100 + iOSLaunchScreeniPadSize: 100 + iOSLaunchScreeniPadCustomXibPath: + iOSUseLaunchScreenStoryboard: 0 + iOSLaunchScreenCustomStoryboardPath: + iOSDeviceRequirements: [] + iOSURLSchemes: [] + iOSBackgroundModes: 0 + iOSMetalForceHardShadows: 0 + metalEditorSupport: 1 + metalAPIValidation: 1 + iOSRenderExtraFrameOnPause: 0 + appleDeveloperTeamID: + iOSManualSigningProvisioningProfileID: + tvOSManualSigningProvisioningProfileID: + iOSManualSigningProvisioningProfileType: 0 + tvOSManualSigningProvisioningProfileType: 0 + appleEnableAutomaticSigning: 0 + iOSRequireARKit: 0 + appleEnableProMotion: 0 + clonedFromGUID: 5f34be1353de5cf4398729fda238591b + templatePackageId: com.unity.template.2d@1.0.1 + templateDefaultScene: Assets/Scenes/SampleScene.unity + AndroidTargetArchitectures: 5 + AndroidSplashScreenScale: 0 + androidSplashScreen: {fileID: 0} + AndroidKeystoreName: + AndroidKeyaliasName: + AndroidBuildApkPerCpuArchitecture: 0 + AndroidTVCompatibility: 1 + AndroidIsGame: 1 + AndroidEnableTango: 0 + androidEnableBanner: 1 + androidUseLowAccuracyLocation: 0 + m_AndroidBanners: + - width: 320 + height: 180 + banner: {fileID: 0} + androidGamepadSupportLevel: 0 + resolutionDialogBanner: {fileID: 0} + m_BuildTargetIcons: [] + m_BuildTargetPlatformIcons: + - m_BuildTarget: Android + m_Icons: + - m_Textures: [] + m_Width: 432 + m_Height: 432 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 324 + m_Height: 324 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 216 + m_Height: 216 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 162 + m_Height: 162 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 108 + m_Height: 108 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 81 + m_Height: 81 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 1 + m_SubKind: + m_BuildTargetBatching: [] + m_BuildTargetGraphicsAPIs: [] + m_BuildTargetVRSettings: [] + m_BuildTargetEnableVuforiaSettings: [] + openGLRequireES31: 0 + openGLRequireES31AEP: 0 + m_TemplateCustomTags: {} + mobileMTRendering: + Android: 1 + iPhone: 1 + tvOS: 1 + m_BuildTargetGroupLightmapEncodingQuality: [] + m_BuildTargetGroupLightmapSettings: [] + playModeTestRunnerEnabled: 0 + runPlayModeTestAsEditModeTest: 0 + actionOnDotNetUnhandledException: 1 + enableInternalProfiler: 0 + logObjCUncaughtExceptions: 1 + enableCrashReportAPI: 0 + cameraUsageDescription: + locationUsageDescription: + microphoneUsageDescription: + switchNetLibKey: + switchSocketMemoryPoolSize: 6144 + switchSocketAllocatorPoolSize: 128 + switchSocketConcurrencyLimit: 14 + switchScreenResolutionBehavior: 2 + switchUseCPUProfiler: 0 + switchApplicationID: 0x01004b9000490000 + switchNSODependencies: + switchTitleNames_0: + switchTitleNames_1: + switchTitleNames_2: + switchTitleNames_3: + switchTitleNames_4: + switchTitleNames_5: + switchTitleNames_6: + switchTitleNames_7: + switchTitleNames_8: + switchTitleNames_9: + switchTitleNames_10: + switchTitleNames_11: + switchTitleNames_12: + switchTitleNames_13: + switchTitleNames_14: + switchPublisherNames_0: + switchPublisherNames_1: + switchPublisherNames_2: + switchPublisherNames_3: + switchPublisherNames_4: + switchPublisherNames_5: + switchPublisherNames_6: + switchPublisherNames_7: + switchPublisherNames_8: + switchPublisherNames_9: + switchPublisherNames_10: + switchPublisherNames_11: + switchPublisherNames_12: + switchPublisherNames_13: + switchPublisherNames_14: + switchIcons_0: {fileID: 0} + switchIcons_1: {fileID: 0} + switchIcons_2: {fileID: 0} + switchIcons_3: {fileID: 0} + switchIcons_4: {fileID: 0} + switchIcons_5: {fileID: 0} + switchIcons_6: {fileID: 0} + switchIcons_7: {fileID: 0} + switchIcons_8: {fileID: 0} + switchIcons_9: {fileID: 0} + switchIcons_10: {fileID: 0} + switchIcons_11: {fileID: 0} + switchIcons_12: {fileID: 0} + switchIcons_13: {fileID: 0} + switchIcons_14: {fileID: 0} + switchSmallIcons_0: {fileID: 0} + switchSmallIcons_1: {fileID: 0} + switchSmallIcons_2: {fileID: 0} + switchSmallIcons_3: {fileID: 0} + switchSmallIcons_4: {fileID: 0} + switchSmallIcons_5: {fileID: 0} + switchSmallIcons_6: {fileID: 0} + switchSmallIcons_7: {fileID: 0} + switchSmallIcons_8: {fileID: 0} + switchSmallIcons_9: {fileID: 0} + switchSmallIcons_10: {fileID: 0} + switchSmallIcons_11: {fileID: 0} + switchSmallIcons_12: {fileID: 0} + switchSmallIcons_13: {fileID: 0} + switchSmallIcons_14: {fileID: 0} + switchManualHTML: + switchAccessibleURLs: + switchLegalInformation: + switchMainThreadStackSize: 1048576 + switchPresenceGroupId: + switchLogoHandling: 0 + switchReleaseVersion: 0 + switchDisplayVersion: 1.0.0 + switchStartupUserAccount: 0 + switchTouchScreenUsage: 0 + switchSupportedLanguagesMask: 0 + switchLogoType: 0 + switchApplicationErrorCodeCategory: + switchUserAccountSaveDataSize: 0 + switchUserAccountSaveDataJournalSize: 0 + switchApplicationAttribute: 0 + switchCardSpecSize: -1 + switchCardSpecClock: -1 + switchRatingsMask: 0 + switchRatingsInt_0: 0 + switchRatingsInt_1: 0 + switchRatingsInt_2: 0 + switchRatingsInt_3: 0 + switchRatingsInt_4: 0 + switchRatingsInt_5: 0 + switchRatingsInt_6: 0 + switchRatingsInt_7: 0 + switchRatingsInt_8: 0 + switchRatingsInt_9: 0 + switchRatingsInt_10: 0 + switchRatingsInt_11: 0 + switchLocalCommunicationIds_0: + switchLocalCommunicationIds_1: + switchLocalCommunicationIds_2: + switchLocalCommunicationIds_3: + switchLocalCommunicationIds_4: + switchLocalCommunicationIds_5: + switchLocalCommunicationIds_6: + switchLocalCommunicationIds_7: + switchParentalControl: 0 + switchAllowsScreenshot: 1 + switchAllowsVideoCapturing: 1 + switchAllowsRuntimeAddOnContentInstall: 0 + switchDataLossConfirmation: 0 + switchUserAccountLockEnabled: 0 + switchSupportedNpadStyles: 3 + switchNativeFsCacheSize: 32 + switchIsHoldTypeHorizontal: 0 + switchSupportedNpadCount: 8 + switchSocketConfigEnabled: 0 + switchTcpInitialSendBufferSize: 32 + switchTcpInitialReceiveBufferSize: 64 + switchTcpAutoSendBufferSizeMax: 256 + switchTcpAutoReceiveBufferSizeMax: 256 + switchUdpSendBufferSize: 9 + switchUdpReceiveBufferSize: 42 + switchSocketBufferEfficiency: 4 + switchSocketInitializeEnabled: 1 + switchNetworkInterfaceManagerInitializeEnabled: 1 + switchPlayerConnectionEnabled: 1 + ps4NPAgeRating: 12 + ps4NPTitleSecret: + ps4NPTrophyPackPath: + ps4ParentalLevel: 11 + ps4ContentID: ED1633-NPXX51362_00-0000000000000000 + ps4Category: 0 + ps4MasterVersion: 01.00 + ps4AppVersion: 01.00 + ps4AppType: 0 + ps4ParamSfxPath: + ps4VideoOutPixelFormat: 0 + ps4VideoOutInitialWidth: 1920 + ps4VideoOutBaseModeInitialWidth: 1920 + ps4VideoOutReprojectionRate: 60 + ps4PronunciationXMLPath: + ps4PronunciationSIGPath: + ps4BackgroundImagePath: + ps4StartupImagePath: + ps4StartupImagesFolder: + ps4IconImagesFolder: + ps4SaveDataImagePath: + ps4SdkOverride: + ps4BGMPath: + ps4ShareFilePath: + ps4ShareOverlayImagePath: + ps4PrivacyGuardImagePath: + ps4NPtitleDatPath: + ps4RemotePlayKeyAssignment: -1 + ps4RemotePlayKeyMappingDir: + ps4PlayTogetherPlayerCount: 0 + ps4EnterButtonAssignment: 1 + ps4ApplicationParam1: 0 + ps4ApplicationParam2: 0 + ps4ApplicationParam3: 0 + ps4ApplicationParam4: 0 + ps4DownloadDataSize: 0 + ps4GarlicHeapSize: 2048 + ps4ProGarlicHeapSize: 2560 + ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ + ps4pnSessions: 1 + ps4pnPresence: 1 + ps4pnFriends: 1 + ps4pnGameCustomData: 1 + playerPrefsSupport: 0 + enableApplicationExit: 0 + resetTempFolder: 1 + restrictedAudioUsageRights: 0 + ps4UseResolutionFallback: 0 + ps4ReprojectionSupport: 0 + ps4UseAudio3dBackend: 0 + ps4SocialScreenEnabled: 0 + ps4ScriptOptimizationLevel: 0 + ps4Audio3dVirtualSpeakerCount: 14 + ps4attribCpuUsage: 0 + ps4PatchPkgPath: + ps4PatchLatestPkgPath: + ps4PatchChangeinfoPath: + ps4PatchDayOne: 0 + ps4attribUserManagement: 0 + ps4attribMoveSupport: 0 + ps4attrib3DSupport: 0 + ps4attribShareSupport: 0 + ps4attribExclusiveVR: 0 + ps4disableAutoHideSplash: 0 + ps4videoRecordingFeaturesUsed: 0 + ps4contentSearchFeaturesUsed: 0 + ps4attribEyeToEyeDistanceSettingVR: 0 + ps4IncludedModules: [] + monoEnv: + splashScreenBackgroundSourceLandscape: {fileID: 0} + splashScreenBackgroundSourcePortrait: {fileID: 0} + spritePackerPolicy: + webGLMemorySize: 256 + webGLExceptionSupport: 1 + webGLNameFilesAsHashes: 0 + webGLDataCaching: 1 + webGLDebugSymbols: 0 + webGLEmscriptenArgs: + webGLModulesDirectory: + webGLTemplate: APPLICATION:Default + webGLAnalyzeBuildSize: 0 + webGLUseEmbeddedResources: 0 + webGLCompressionFormat: 1 + webGLLinkerTarget: 1 + webGLThreadsSupport: 0 + scriptingDefineSymbols: {} + platformArchitecture: {} + scriptingBackend: + Android: 1 + il2cppCompilerConfiguration: {} + managedStrippingLevel: {} + incrementalIl2cppBuild: {} + allowUnsafeCode: 0 + additionalIl2CppArgs: + scriptingRuntimeVersion: 1 + apiCompatibilityLevelPerPlatform: + Android: 3 + m_RenderingPath: 1 + m_MobileRenderingPath: 1 + metroPackageName: Template_2D + metroPackageVersion: + metroCertificatePath: + metroCertificatePassword: + metroCertificateSubject: + metroCertificateIssuer: + metroCertificateNotAfter: 0000000000000000 + metroApplicationDescription: Template_2D + wsaImages: {} + metroTileShortName: + metroTileShowName: 0 + metroMediumTileShowName: 0 + metroLargeTileShowName: 0 + metroWideTileShowName: 0 + metroSupportStreamingInstall: 0 + metroLastRequiredScene: 0 + metroDefaultTileSize: 1 + metroTileForegroundText: 2 + metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} + metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, + a: 1} + metroSplashScreenUseBackgroundColor: 0 + platformCapabilities: {} + metroTargetDeviceFamilies: {} + metroFTAName: + metroFTAFileTypes: [] + metroProtocolName: + metroCompilationOverrides: 1 + XboxOneProductId: + XboxOneUpdateKey: + XboxOneSandboxId: + XboxOneContentId: + XboxOneTitleId: + XboxOneSCId: + XboxOneGameOsOverridePath: + XboxOnePackagingOverridePath: + XboxOneAppManifestOverridePath: + XboxOneVersion: 1.0.0.0 + XboxOnePackageEncryption: 0 + XboxOnePackageUpdateGranularity: 2 + XboxOneDescription: + XboxOneLanguage: + - enus + XboxOneCapability: [] + XboxOneGameRating: {} + XboxOneIsContentPackage: 0 + XboxOneEnableGPUVariability: 0 + XboxOneSockets: {} + XboxOneSplashScreen: {fileID: 0} + XboxOneAllowedProductIds: [] + XboxOnePersistentLocalStorageSize: 0 + XboxOneXTitleMemory: 8 + xboxOneScriptCompiler: 0 + XboxOneOverrideIdentityName: + vrEditorSettings: + daydream: + daydreamIconForeground: {fileID: 0} + daydreamIconBackground: {fileID: 0} + cloudServicesEnabled: + UNet: 1 + luminIcon: + m_Name: + m_ModelFolderPath: + m_PortalFolderPath: + luminCert: + m_CertPath: + m_PrivateKeyPath: + luminIsChannelApp: 0 + luminVersion: + m_VersionCode: 1 + m_VersionName: + facebookSdkVersion: 7.9.4 + facebookAppId: + facebookCookies: 1 + facebookLogging: 1 + facebookStatus: 1 + facebookXfbml: 0 + facebookFrictionlessRequests: 1 + apiCompatibilityLevel: 3 + cloudProjectId: + framebufferDepthMemorylessMode: 0 + projectName: + organizationId: + cloudEnabled: 0 + enableNativePlatformBackendsForNewInputSystem: 0 + disableOldInputManagerSupport: 0 + legacyClampBlendShapeWeights: 1 diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/ProjectVersion.txt b/examples/csharp/HelloworldUnity/ProjectSettings/ProjectVersion.txt new file mode 100644 index 00000000000..acd2ceba1e4 --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/ProjectVersion.txt @@ -0,0 +1 @@ +m_EditorVersion: 2018.3.3f1 diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/QualitySettings.asset b/examples/csharp/HelloworldUnity/ProjectSettings/QualitySettings.asset new file mode 100644 index 00000000000..b055962bcac --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/QualitySettings.asset @@ -0,0 +1,191 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!47 &1 +QualitySettings: + m_ObjectHideFlags: 0 + serializedVersion: 5 + m_CurrentQuality: 3 + m_QualitySettings: + - serializedVersion: 2 + name: Very Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 15 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 1 + textureQuality: 1 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.3 + maximumLODLevel: 0 + particleRaycastBudget: 4 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.4 + maximumLODLevel: 0 + particleRaycastBudget: 16 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Medium + pixelLightCount: 1 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 1 + lodBias: 0.7 + maximumLODLevel: 0 + particleRaycastBudget: 64 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: High + pixelLightCount: 2 + shadows: 0 + shadowResolution: 1 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 40 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 1 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 1 + lodBias: 1 + maximumLODLevel: 0 + particleRaycastBudget: 256 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Very High + pixelLightCount: 3 + shadows: 0 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 70 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 1 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 1 + lodBias: 1.5 + maximumLODLevel: 0 + particleRaycastBudget: 1024 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Ultra + pixelLightCount: 4 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 4 + shadowDistance: 150 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 1 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 1 + lodBias: 2 + maximumLODLevel: 0 + particleRaycastBudget: 4096 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + m_PerPlatformDefaultQuality: + Android: 2 + Nintendo 3DS: 5 + Nintendo Switch: 5 + PS4: 5 + PSM: 5 + PSP2: 2 + Standalone: 5 + Tizen: 2 + WebGL: 3 + WiiU: 5 + Windows Store Apps: 5 + XboxOne: 5 + iPhone: 2 + tvOS: 2 diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/TagManager.asset b/examples/csharp/HelloworldUnity/ProjectSettings/TagManager.asset new file mode 100644 index 00000000000..3281f1b528b --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/TagManager.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!78 &1 +TagManager: + serializedVersion: 2 + tags: [] + layers: + - Default + - TransparentFX + - Ignore Raycast + - + - Water + - UI + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + m_SortingLayers: + - name: Default + uniqueID: 0 + locked: 0 diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/TimeManager.asset b/examples/csharp/HelloworldUnity/ProjectSettings/TimeManager.asset new file mode 100644 index 00000000000..06bcc6d2953 --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/TimeManager.asset @@ -0,0 +1,9 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!5 &1 +TimeManager: + m_ObjectHideFlags: 0 + Fixed Timestep: 0.02 + Maximum Allowed Timestep: 0.1 + m_TimeScale: 1 + Maximum Particle Timestep: 0.03 diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/UnityConnectSettings.asset b/examples/csharp/HelloworldUnity/ProjectSettings/UnityConnectSettings.asset new file mode 100644 index 00000000000..06db74a9444 --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/UnityConnectSettings.asset @@ -0,0 +1,34 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!310 &1 +UnityConnectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 1 + m_Enabled: 1 + m_TestMode: 0 + m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events + m_EventUrl: https://cdp.cloud.unity3d.com/v1/events + m_ConfigUrl: https://config.uca.cloud.unity3d.com + m_TestInitMode: 0 + CrashReportingSettings: + m_EventUrl: https://perf-events.cloud.unity3d.com + m_Enabled: 0 + m_LogBufferSize: 10 + m_CaptureEditorExceptions: 1 + UnityPurchasingSettings: + m_Enabled: 0 + m_TestMode: 0 + UnityAnalyticsSettings: + m_Enabled: 1 + m_TestMode: 0 + m_InitializeOnStartup: 1 + UnityAdsSettings: + m_Enabled: 0 + m_InitializeOnStartup: 1 + m_TestMode: 0 + m_IosGameId: + m_AndroidGameId: + m_GameIds: {} + m_GameId: + PerformanceReportingSettings: + m_Enabled: 0 diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/VFXManager.asset b/examples/csharp/HelloworldUnity/ProjectSettings/VFXManager.asset new file mode 100644 index 00000000000..6e0eaca40d5 --- /dev/null +++ b/examples/csharp/HelloworldUnity/ProjectSettings/VFXManager.asset @@ -0,0 +1,11 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!937362698 &1 +VFXManager: + m_ObjectHideFlags: 0 + m_IndirectShader: {fileID: 0} + m_CopyBufferShader: {fileID: 0} + m_SortShader: {fileID: 0} + m_RenderPipeSettingsPath: + m_FixedTimeStep: 0.016666668 + m_MaxDeltaTime: 0.05 diff --git a/examples/csharp/HelloworldUnity/UIElementsSchema/UIElements.xsd b/examples/csharp/HelloworldUnity/UIElementsSchema/UIElements.xsd new file mode 100644 index 00000000000..1131a5105bf --- /dev/null +++ b/examples/csharp/HelloworldUnity/UIElementsSchema/UIElements.xsd @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/examples/csharp/HelloworldUnity/UIElementsSchema/UnityEditor.Experimental.UIElements.xsd b/examples/csharp/HelloworldUnity/UIElementsSchema/UnityEditor.Experimental.UIElements.xsd new file mode 100644 index 00000000000..f2374e87007 --- /dev/null +++ b/examples/csharp/HelloworldUnity/UIElementsSchema/UnityEditor.Experimental.UIElements.xsd @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/csharp/HelloworldUnity/UIElementsSchema/UnityEditor.PackageManager.UI.xsd b/examples/csharp/HelloworldUnity/UIElementsSchema/UnityEditor.PackageManager.UI.xsd new file mode 100644 index 00000000000..117194aa38a --- /dev/null +++ b/examples/csharp/HelloworldUnity/UIElementsSchema/UnityEditor.PackageManager.UI.xsd @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/csharp/HelloworldUnity/UIElementsSchema/UnityEngine.Experimental.UIElements.xsd b/examples/csharp/HelloworldUnity/UIElementsSchema/UnityEngine.Experimental.UIElements.xsd new file mode 100644 index 00000000000..0c074b23ba9 --- /dev/null +++ b/examples/csharp/HelloworldUnity/UIElementsSchema/UnityEngine.Experimental.UIElements.xsd @@ -0,0 +1,269 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From db598a6cd0ccee801d5d415630a58c1f2104f89c Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 11 Feb 2019 19:10:42 +0100 Subject: [PATCH 215/218] Add HelloworldUnity readme --- examples/csharp/HelloworldUnity/README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 examples/csharp/HelloworldUnity/README.md diff --git a/examples/csharp/HelloworldUnity/README.md b/examples/csharp/HelloworldUnity/README.md new file mode 100644 index 00000000000..ec489e94998 --- /dev/null +++ b/examples/csharp/HelloworldUnity/README.md @@ -0,0 +1,19 @@ +gRPC C# on Unity +======================== + +EXPERIMENTAL ONLY +------------- +Support of the Unity platform is currently experimental. + +PREREQUISITES +------------- + +- Unity 2018.3.5f1 + +BUILD +------- + +- Follow instructions in https://github.com/grpc/grpc/tree/master/src/csharp/experimental#unity to obtain the grpc_csharp_unity.zip + that contains gRPC C# for Unity. Unzip it under `Assets/Plugins` directory. +- Open the `HelloworldUnity.sln` in Unity Editor. +- Build using Unity Editor. From 022d71ecc5209b0b39335845df63949b808a6c1d Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 12 Feb 2019 11:20:31 +0100 Subject: [PATCH 216/218] Unity example improvements --- .../Assets/Scripts/HelloWorldScript.cs | 98 +++---------------- .../Assets/Scripts/HelloWorldTest.cs | 63 ++++++++++++ .../Assets/Scripts/HelloWorldTest.cs.meta | 11 +++ 3 files changed, 87 insertions(+), 85 deletions(-) create mode 100644 examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs create mode 100644 examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs.meta diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs index 6d318bcc348..df3ce8929e1 100644 --- a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs @@ -1,92 +1,20 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; +using UnityEngine; using UnityEngine.UI; -using Helloworld; -using System.Threading.Tasks; - -using System; - -using UnityEngine.SceneManagement; - -using Grpc.Core; - public class HelloWorldScript : MonoBehaviour { - const int Port = 50051; - int counter = 1; - // Use this for initialization - void Start () { - //Console.WriteLine("dfsdfadfffa dfasfa"); - - - } - - public void RunHelloWorld(Text text) - { - //Debug.Log("dfasfa"); - //var channel = new Channel("localhost:12345", ChannelCredentials.Insecure); - //SceneManager.LoadScene("RocketMouse"); - - - //var unityApplicationClass = Type.GetType("UnityEngine.Application, UnityEngine"); - // Consult value of Application.platform via reflection - // https://docs.unity3d.com/ScriptReference/Application-platform.html - // var platformProperty = unityApplicationClass.GetTypeInfo().GetProperty("platform"); - // var unityRuntimePlatform = platformProperty?.GetValue(null)?.ToString(); - //var isUnityIOS = (unityRuntimePlatform == "IPhonePlayer"); - - var t = Type.GetType("UnityEngine.Application, UnityEngine"); - var propInfo = t.GetProperty("platform"); - var reflPlatform = propInfo.GetValue(null).ToString(); - - - Debug.Log("Appl. platform:" + Application.platform); - Debug.Log("Appl. platform:" + reflPlatform); - Debug.Log("Environment.OSVersion: " + Environment.OSVersion); - - - Server server = new Server - { - Services = { Greeter.BindService(new GreeterImpl()) }, - Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } - }; - server.Start(); - - Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure); - - var client = new Greeter.GreeterClient(channel); - String user = "Unity " + counter; - - var reply = client.SayHello(new HelloRequest { Name = user }); - - - text.text = "Greeting: " + reply.Message; - - channel.ShutdownAsync().Wait(); - - server.ShutdownAsync().Wait(); - - counter ++; - - - - //Debug.Log("channel: created channel"); + int counter = 1; + // Use this for initialization + void Start () {} - } - - // Update is called once per frame - void Update () { - - } + // Update is called once per frame + void Update() {} - class GreeterImpl : Greeter.GreeterBase - { - // Server side handler of the SayHello RPC - public override Task SayHello(HelloRequest request, ServerCallContext context) - { - return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); - } - } + // Ran when button is clicked + public void RunHelloWorld(Text text) + { + var reply = HelloWorldTest.Greet("Unity " + counter); + text.text = "Greeting: " + reply.Message; + counter++; + } } diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs new file mode 100644 index 00000000000..7138da751b5 --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs @@ -0,0 +1,63 @@ +using UnityEngine; +using System.Threading.Tasks; +using System; +using Grpc.Core; +using Helloworld; + +class HelloWorldTest +{ + // Can be run from commandline. + // Example command: + // "/Applications/Unity/Unity.app/Contents/MacOS/Unity -quit -batchmode -nographics -executeMethod HelloWorldTest.RunHelloWorld -logfile" + public static void RunHelloWorld() + { + Application.SetStackTraceLogType(LogType.Log, StackTraceLogType.None); + + Debug.Log("=============================================================="); + Debug.Log("Starting tests"); + Debug.Log("=============================================================="); + + Debug.Log("Application.platform: " + Application.platform); + Debug.Log("Environment.OSVersion: " + Environment.OSVersion); + + var reply = Greet("Unity"); + Debug.Log("Greeting: " + reply.Message); + + Debug.Log("=============================================================="); + Debug.Log("Tests finished successfully."); + Debug.Log("=============================================================="); + } + + public static HelloReply Greet(string greeting) + { + const int Port = 50051; + + Server server = new Server + { + Services = { Greeter.BindService(new GreeterImpl()) }, + Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } + }; + server.Start(); + + Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure); + + var client = new Greeter.GreeterClient(channel); + + var reply = client.SayHello(new HelloRequest { Name = greeting }); + + channel.ShutdownAsync().Wait(); + + server.ShutdownAsync().Wait(); + + return reply; + } + + class GreeterImpl : Greeter.GreeterBase + { + // Server side handler of the SayHello RPC + public override Task SayHello(HelloRequest request, ServerCallContext context) + { + return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); + } + } +} diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs.meta b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs.meta new file mode 100644 index 00000000000..f511815254a --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8c088e5dee11c45fc95e41b9281d55e2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From bf175db9ad0b0962a3a03f010b4a93e8ba5ead55 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 12 Feb 2019 11:27:51 +0100 Subject: [PATCH 217/218] upgrade ProjectVersion --- .../csharp/HelloworldUnity/ProjectSettings/ProjectVersion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/csharp/HelloworldUnity/ProjectSettings/ProjectVersion.txt b/examples/csharp/HelloworldUnity/ProjectSettings/ProjectVersion.txt index acd2ceba1e4..6128d74131b 100644 --- a/examples/csharp/HelloworldUnity/ProjectSettings/ProjectVersion.txt +++ b/examples/csharp/HelloworldUnity/ProjectSettings/ProjectVersion.txt @@ -1 +1 @@ -m_EditorVersion: 2018.3.3f1 +m_EditorVersion: 2018.3.5f1 From 623702da6e509b802e26eaa10f96f1d6380c2649 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 12 Feb 2019 16:56:43 +0100 Subject: [PATCH 218/218] add copyright headers --- .../Assets/Scripts/HelloWorldScript.cs | 58 ++++--- .../Assets/Scripts/HelloWorldTest.cs | 144 ++++++++++-------- 2 files changed, 119 insertions(+), 83 deletions(-) diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs index df3ce8929e1..0dad0f6a5ad 100644 --- a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs @@ -1,20 +1,38 @@ -using UnityEngine; -using UnityEngine.UI; - -public class HelloWorldScript : MonoBehaviour { - int counter = 1; - - // Use this for initialization - void Start () {} - - // Update is called once per frame - void Update() {} - - // Ran when button is clicked - public void RunHelloWorld(Text text) - { - var reply = HelloWorldTest.Greet("Unity " + counter); - text.text = "Greeting: " + reply.Message; - counter++; - } -} +#region Copyright notice and license + +// Copyright 2019 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. + +#endregion + +using UnityEngine; +using UnityEngine.UI; + +public class HelloWorldScript : MonoBehaviour { + int counter = 1; + + // Use this for initialization + void Start () {} + + // Update is called once per frame + void Update() {} + + // Ran when button is clicked + public void RunHelloWorld(Text text) + { + var reply = HelloWorldTest.Greet("Unity " + counter); + text.text = "Greeting: " + reply.Message; + counter++; + } +} diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs index 7138da751b5..2c10f10a144 100644 --- a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs @@ -1,63 +1,81 @@ -using UnityEngine; -using System.Threading.Tasks; -using System; -using Grpc.Core; -using Helloworld; - -class HelloWorldTest -{ - // Can be run from commandline. - // Example command: - // "/Applications/Unity/Unity.app/Contents/MacOS/Unity -quit -batchmode -nographics -executeMethod HelloWorldTest.RunHelloWorld -logfile" - public static void RunHelloWorld() - { - Application.SetStackTraceLogType(LogType.Log, StackTraceLogType.None); - - Debug.Log("=============================================================="); - Debug.Log("Starting tests"); - Debug.Log("=============================================================="); - - Debug.Log("Application.platform: " + Application.platform); - Debug.Log("Environment.OSVersion: " + Environment.OSVersion); - - var reply = Greet("Unity"); - Debug.Log("Greeting: " + reply.Message); - - Debug.Log("=============================================================="); - Debug.Log("Tests finished successfully."); - Debug.Log("=============================================================="); - } - - public static HelloReply Greet(string greeting) - { - const int Port = 50051; - - Server server = new Server - { - Services = { Greeter.BindService(new GreeterImpl()) }, - Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } - }; - server.Start(); - - Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure); - - var client = new Greeter.GreeterClient(channel); - - var reply = client.SayHello(new HelloRequest { Name = greeting }); - - channel.ShutdownAsync().Wait(); - - server.ShutdownAsync().Wait(); - - return reply; - } - - class GreeterImpl : Greeter.GreeterBase - { - // Server side handler of the SayHello RPC - public override Task SayHello(HelloRequest request, ServerCallContext context) - { - return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); - } - } -} +#region Copyright notice and license + +// Copyright 2019 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. + +#endregion + +using UnityEngine; +using System.Threading.Tasks; +using System; +using Grpc.Core; +using Helloworld; + +class HelloWorldTest +{ + // Can be run from commandline. + // Example command: + // "/Applications/Unity/Unity.app/Contents/MacOS/Unity -quit -batchmode -nographics -executeMethod HelloWorldTest.RunHelloWorld -logfile" + public static void RunHelloWorld() + { + Application.SetStackTraceLogType(LogType.Log, StackTraceLogType.None); + + Debug.Log("=============================================================="); + Debug.Log("Starting tests"); + Debug.Log("=============================================================="); + + Debug.Log("Application.platform: " + Application.platform); + Debug.Log("Environment.OSVersion: " + Environment.OSVersion); + + var reply = Greet("Unity"); + Debug.Log("Greeting: " + reply.Message); + + Debug.Log("=============================================================="); + Debug.Log("Tests finished successfully."); + Debug.Log("=============================================================="); + } + + public static HelloReply Greet(string greeting) + { + const int Port = 50051; + + Server server = new Server + { + Services = { Greeter.BindService(new GreeterImpl()) }, + Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } + }; + server.Start(); + + Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure); + + var client = new Greeter.GreeterClient(channel); + + var reply = client.SayHello(new HelloRequest { Name = greeting }); + + channel.ShutdownAsync().Wait(); + + server.ShutdownAsync().Wait(); + + return reply; + } + + class GreeterImpl : Greeter.GreeterBase + { + // Server side handler of the SayHello RPC + public override Task SayHello(HelloRequest request, ServerCallContext context) + { + return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); + } + } +}