aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/cpp_generator.cc4
-rw-r--r--src/core/ext/census/grpc_filter.c4
-rw-r--r--src/core/ext/client_channel/client_channel.c828
-rw-r--r--src/core/ext/client_channel/client_channel_plugin.c4
-rw-r--r--src/core/ext/client_channel/http_proxy.c61
-rw-r--r--src/core/ext/client_channel/http_proxy.h4
-rw-r--r--src/core/ext/client_channel/lb_policy.c91
-rw-r--r--src/core/ext/client_channel/lb_policy.h85
-rw-r--r--src/core/ext/client_channel/lb_policy_factory.h1
-rw-r--r--src/core/ext/client_channel/parse_address.c38
-rw-r--r--src/core/ext/client_channel/proxy_mapper.c25
-rw-r--r--src/core/ext/client_channel/proxy_mapper.h36
-rw-r--r--src/core/ext/client_channel/proxy_mapper_registry.c52
-rw-r--r--src/core/ext/client_channel/proxy_mapper_registry.h16
-rw-r--r--src/core/ext/client_channel/resolver.c25
-rw-r--r--src/core/ext/client_channel/resolver.h35
-rw-r--r--src/core/ext/client_channel/resolver_factory.h1
-rw-r--r--src/core/ext/client_channel/resolver_registry.c26
-rw-r--r--src/core/ext/client_channel/resolver_registry.h8
-rw-r--r--src/core/ext/client_channel/subchannel.c26
-rw-r--r--src/core/ext/client_channel/subchannel.h3
-rw-r--r--src/core/ext/client_channel/uri_parser.c40
-rw-r--r--src/core/ext/client_channel/uri_parser.h4
-rw-r--r--src/core/ext/lb_policy/grpclb/grpclb.c192
-rw-r--r--src/core/ext/lb_policy/grpclb/load_balancer_api.c9
-rw-r--r--src/core/ext/lb_policy/pick_first/pick_first.c187
-rw-r--r--src/core/ext/lb_policy/round_robin/round_robin.c112
-rw-r--r--src/core/ext/load_reporting/load_reporting.c20
-rw-r--r--src/core/ext/load_reporting/load_reporting.h17
-rw-r--r--src/core/ext/load_reporting/load_reporting_filter.c24
-rw-r--r--src/core/ext/resolver/dns/native/dns_resolver.c64
-rw-r--r--src/core/ext/resolver/sockaddr/sockaddr_resolver.c47
-rw-r--r--src/core/ext/transport/chttp2/client/chttp2_connector.c5
-rw-r--r--src/core/ext/transport/chttp2/client/insecure/channel_create.c7
-rw-r--r--src/core/ext/transport/chttp2/client/secure/secure_channel_create.c11
-rw-r--r--src/core/ext/transport/chttp2/server/chttp2_server.c60
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.c214
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_ping.c2
-rw-r--r--src/core/ext/transport/chttp2/transport/frame_settings.h2
-rw-r--r--src/core/ext/transport/chttp2/transport/hpack_encoder.c1
-rw-r--r--src/core/ext/transport/chttp2/transport/internal.h83
-rw-r--r--src/core/ext/transport/chttp2/transport/parsing.c62
-rw-r--r--src/core/ext/transport/chttp2/transport/writing.c18
-rw-r--r--src/core/ext/transport/cronet/client/secure/cronet_channel_create.c13
-rw-r--r--src/core/ext/transport/cronet/transport/cronet_api_dummy.c12
-rw-r--r--src/core/ext/transport/cronet/transport/cronet_transport.c366
-rw-r--r--src/core/ext/transport/cronet/transport/cronet_transport.h43
-rw-r--r--src/core/lib/channel/channel_stack.c15
-rw-r--r--src/core/lib/channel/channel_stack.h8
-rw-r--r--src/core/lib/channel/channel_stack_builder.c5
-rw-r--r--src/core/lib/channel/compress_filter.c12
-rw-r--r--src/core/lib/channel/connected_channel.c2
-rw-r--r--src/core/lib/channel/context.h3
-rw-r--r--src/core/lib/channel/deadline_filter.c107
-rw-r--r--src/core/lib/channel/deadline_filter.h13
-rw-r--r--src/core/lib/channel/handshaker.c40
-rw-r--r--src/core/lib/channel/handshaker.h16
-rw-r--r--src/core/lib/channel/http_client_filter.c2
-rw-r--r--src/core/lib/channel/http_server_filter.c26
-rw-r--r--src/core/lib/channel/message_size_filter.c3
-rw-r--r--src/core/lib/http/httpcli.c5
-rw-r--r--src/core/lib/http/httpcli.h3
-rw-r--r--src/core/lib/http/httpcli_security_connector.c3
-rw-r--r--src/core/lib/http/parser.c4
-rw-r--r--src/core/lib/iomgr/combiner.c28
-rw-r--r--src/core/lib/iomgr/combiner.h23
-rw-r--r--src/core/lib/iomgr/error.c422
-rw-r--r--src/core/lib/iomgr/error.h15
-rw-r--r--src/core/lib/iomgr/error_internal.h24
-rw-r--r--src/core/lib/iomgr/ev_epoll_linux.c356
-rw-r--r--src/core/lib/iomgr/ev_poll_posix.c73
-rw-r--r--src/core/lib/iomgr/ev_posix.c9
-rw-r--r--src/core/lib/iomgr/ev_posix.h4
-rw-r--r--src/core/lib/iomgr/network_status_tracker.c87
-rw-r--r--src/core/lib/iomgr/pollset.h4
-rw-r--r--src/core/lib/iomgr/pollset_set.h3
-rw-r--r--src/core/lib/iomgr/pollset_set_uv.c3
-rw-r--r--src/core/lib/iomgr/pollset_set_windows.c3
-rw-r--r--src/core/lib/iomgr/pollset_uv.c36
-rw-r--r--src/core/lib/iomgr/pollset_windows.c11
-rw-r--r--src/core/lib/iomgr/resolve_address_uv.c57
-rw-r--r--src/core/lib/iomgr/resource_quota.c2
-rw-r--r--src/core/lib/iomgr/sockaddr_utils.c12
-rw-r--r--src/core/lib/iomgr/socket_utils_windows.c4
-rw-r--r--src/core/lib/iomgr/tcp_client_uv.c16
-rw-r--r--src/core/lib/iomgr/tcp_server_posix.c350
-rw-r--r--src/core/lib/iomgr/tcp_uv.c10
-rw-r--r--src/core/lib/iomgr/timer_generic.c37
-rw-r--r--src/core/lib/iomgr/timer_generic.h2
-rw-r--r--src/core/lib/iomgr/timer_uv.c12
-rw-r--r--src/core/lib/iomgr/timer_uv.h2
-rw-r--r--src/core/lib/iomgr/udp_server.c6
-rw-r--r--src/core/lib/iomgr/wakeup_fd_posix.h2
-rw-r--r--src/core/lib/json/json.c3
-rw-r--r--src/core/lib/security/context/security_context.c13
-rw-r--r--src/core/lib/security/credentials/composite/composite_credentials.c12
-rw-r--r--src/core/lib/security/credentials/credentials.c3
-rw-r--r--src/core/lib/security/credentials/credentials_metadata.c3
-rw-r--r--src/core/lib/security/credentials/fake/fake_credentials.c6
-rw-r--r--src/core/lib/security/credentials/google_default/google_default_credentials.c4
-rw-r--r--src/core/lib/security/credentials/iam/iam_credentials.c3
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_credentials.c3
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_verifier.c13
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_verifier.h3
-rw-r--r--src/core/lib/security/credentials/oauth2/oauth2_credentials.c8
-rw-r--r--src/core/lib/security/credentials/plugin/plugin_credentials.c6
-rw-r--r--src/core/lib/security/credentials/ssl/ssl_credentials.c6
-rw-r--r--src/core/lib/security/transport/client_auth_filter.c2
-rw-r--r--src/core/lib/security/transport/security_connector.c12
-rw-r--r--src/core/lib/security/transport/security_handshaker.c3
-rw-r--r--src/core/lib/security/transport/server_auth_filter.c2
-rw-r--r--src/core/lib/slice/slice_hash_table.c6
-rw-r--r--src/core/lib/slice/slice_intern.c6
-rw-r--r--src/core/lib/support/alloc.c27
-rw-r--r--src/core/lib/support/cmdline.c6
-rw-r--r--src/core/lib/support/cpu_posix.c9
-rw-r--r--src/core/lib/support/histogram.c3
-rw-r--r--src/core/lib/support/spinlock.h52
-rw-r--r--src/core/lib/support/subprocess_posix.c3
-rw-r--r--src/core/lib/support/sync.c12
-rw-r--r--src/core/lib/support/sync_posix.c10
-rw-r--r--src/core/lib/surface/call.c180
-rw-r--r--src/core/lib/surface/call.h1
-rw-r--r--src/core/lib/surface/channel.c6
-rw-r--r--src/core/lib/surface/completion_queue.c46
-rw-r--r--src/core/lib/surface/completion_queue.h3
-rw-r--r--src/core/lib/surface/init.c2
-rw-r--r--src/core/lib/surface/lame_client.c2
-rw-r--r--src/core/lib/surface/server.c19
-rw-r--r--src/core/lib/transport/connectivity_state.c45
-rw-r--r--src/core/lib/transport/connectivity_state.h20
-rw-r--r--src/core/lib/transport/error_utils.c22
-rw-r--r--src/core/lib/transport/metadata.c6
-rw-r--r--src/core/lib/transport/static_metadata.c763
-rw-r--r--src/core/lib/transport/static_metadata.h221
-rw-r--r--src/core/lib/transport/transport.c35
-rw-r--r--src/core/lib/transport/transport.h11
-rw-r--r--src/core/lib/tsi/fake_transport_security.c6
-rw-r--r--src/core/lib/tsi/ssl_transport_security.c23
-rw-r--r--src/core/lib/tsi/test_creds/BUILD36
-rw-r--r--src/core/lib/tsi/transport_security.c6
-rw-r--r--src/core/plugin_registry/grpc_cronet_plugin_registry.c4
-rw-r--r--src/cpp/common/channel_filter.h4
-rw-r--r--src/cpp/common/version_cc.cc2
-rw-r--r--src/cpp/server/channel_argument_option.cc78
-rw-r--r--src/cpp/server/health/default_health_check_service.cc168
-rw-r--r--src/cpp/server/health/default_health_check_service.h78
-rw-r--r--src/cpp/server/health/health.pb.c24
-rw-r--r--src/cpp/server/health/health.pb.h72
-rw-r--r--src/cpp/server/health/health_check_service.cc (renamed from src/cpp/test/server_context_test_spouse.cc)24
-rw-r--r--src/cpp/server/health/health_check_service_server_builder_option.cc50
-rw-r--r--src/cpp/server/server_builder.cc8
-rw-r--r--src/cpp/server/server_cc.cc43
-rw-r--r--src/cpp/server/server_context.cc29
-rw-r--r--src/csharp/Grpc.Auth/Grpc.Auth.csproj26
-rw-r--r--src/csharp/Grpc.Auth/packages.config10
-rw-r--r--src/csharp/Grpc.Auth/project.json6
-rw-r--r--src/csharp/Grpc.Core.Testing/project.json4
-rw-r--r--src/csharp/Grpc.Core.Tests/AuthContextTest.cs86
-rw-r--r--src/csharp/Grpc.Core.Tests/AuthPropertyTest.cs82
-rw-r--r--src/csharp/Grpc.Core.Tests/ClientServerTest.cs12
-rw-r--r--src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj19
-rw-r--r--src/csharp/Grpc.Core.Tests/TestResult.xml41
-rw-r--r--src/csharp/Grpc.Core.Tests/packages.config7
-rw-r--r--src/csharp/Grpc.Core.Tests/project.json16
-rw-r--r--src/csharp/Grpc.Core/AuthContext.cs128
-rw-r--r--src/csharp/Grpc.Core/AuthProperty.cs126
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.csproj4
-rw-r--r--src/csharp/Grpc.Core/Internal/AuthContextSafeHandle.cs119
-rw-r--r--src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs10
-rw-r--r--src/csharp/Grpc.Core/Internal/CallSafeHandle.cs8
-rw-r--r--src/csharp/Grpc.Core/Internal/MarshalUtils.cs90
-rw-r--r--src/csharp/Grpc.Core/Internal/NativeMethods.cs18
-rw-r--r--src/csharp/Grpc.Core/Metadata.cs13
-rw-r--r--src/csharp/Grpc.Core/NativeDeps.Windows.targets2
-rw-r--r--src/csharp/Grpc.Core/ServerCallContext.cs23
-rw-r--r--src/csharp/Grpc.Core/VersionInfo.cs4
-rw-r--r--src/csharp/Grpc.Core/project.json2
-rw-r--r--src/csharp/Grpc.Examples.MathClient/project.json8
-rw-r--r--src/csharp/Grpc.Examples.MathServer/project.json8
-rw-r--r--src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj12
-rw-r--r--src/csharp/Grpc.Examples.Tests/packages.config6
-rw-r--r--src/csharp/Grpc.Examples.Tests/project.json12
-rw-r--r--src/csharp/Grpc.Examples/Grpc.Examples.csproj14
-rw-r--r--src/csharp/Grpc.Examples/packages.config4
-rw-r--r--src/csharp/Grpc.Examples/project.json9
-rw-r--r--src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj10
-rw-r--r--src/csharp/Grpc.HealthCheck.Tests/packages.config6
-rw-r--r--src/csharp/Grpc.HealthCheck.Tests/project.json12
-rw-r--r--src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj6
-rw-r--r--src/csharp/Grpc.HealthCheck/packages.config2
-rw-r--r--src/csharp/Grpc.HealthCheck/project.json13
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj28
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Client/packages.config10
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Client/project.json8
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/packages.config3
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json8
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj28
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Server/packages.config10
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Server/project.json8
-rw-r--r--src/csharp/Grpc.IntegrationTesting.StressClient/packages.config3
-rw-r--r--src/csharp/Grpc.IntegrationTesting.StressClient/project.json8
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Control.cs497
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Empty.cs12
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj52
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropClient.cs4
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropServer.cs2
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Messages.cs128
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Metrics.cs4
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Payloads.cs4
-rw-r--r--src/csharp/Grpc.IntegrationTesting/QpsWorker.cs2
-rw-r--r--src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs38
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Stats.cs26
-rw-r--r--src/csharp/Grpc.IntegrationTesting/StressTestClient.cs1
-rw-r--r--src/csharp/Grpc.IntegrationTesting/packages.config22
-rw-r--r--src/csharp/Grpc.IntegrationTesting/project.json23
-rw-r--r--src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj16
-rw-r--r--src/csharp/Grpc.Reflection.Tests/packages.config6
-rw-r--r--src/csharp/Grpc.Reflection.Tests/project.json12
-rw-r--r--src/csharp/Grpc.Reflection/Grpc.Reflection.csproj6
-rw-r--r--src/csharp/Grpc.Reflection/Reflection.cs98
-rw-r--r--src/csharp/Grpc.Reflection/packages.config2
-rw-r--r--src/csharp/Grpc.Reflection/project.json13
-rw-r--r--src/csharp/README.md47
-rwxr-xr-xsrc/csharp/build_packages_dotnetcli.bat2
-rwxr-xr-xsrc/csharp/build_packages_dotnetcli.sh4
-rw-r--r--src/csharp/buildall.bat59
-rw-r--r--src/csharp/ext/grpc_csharp_ext.c25
-rw-r--r--src/csharp/global.json5
-rw-r--r--src/csharp/tests.json3
-rw-r--r--src/node/ext/completion_queue_threadpool.cc43
-rw-r--r--src/node/ext/server.cc67
-rw-r--r--src/node/ext/server.h1
-rw-r--r--src/node/ext/server_generic.cc73
-rw-r--r--src/node/ext/server_uv.cc131
-rw-r--r--src/node/health_check/package.json4
-rw-r--r--src/node/src/client.js9
-rw-r--r--src/node/src/server.js32
-rw-r--r--src/node/test/surface_test.js107
-rw-r--r--src/node/tools/package.json2
-rw-r--r--src/objective-c/!ProtoCompiler-gRPCPlugin.podspec2
-rw-r--r--src/objective-c/GRPCClient/private/version.h2
-rw-r--r--src/objective-c/tests/CronetUnitTests/CronetUnitTests.m335
-rw-r--r--src/objective-c/tests/InteropTests.m6
-rw-r--r--src/objective-c/tests/InteropTestsLocalCleartext.m6
-rw-r--r--src/objective-c/tests/InteropTestsLocalSSL.m6
-rw-r--r--src/objective-c/tests/InteropTestsRemote.m6
-rw-r--r--src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m8
-rw-r--r--src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme19
-rwxr-xr-xsrc/objective-c/tests/run_tests.sh8
-rw-r--r--src/php/README.md24
-rw-r--r--src/php/composer.json4
-rw-r--r--src/php/ext/grpc/call.c52
-rw-r--r--src/php/ext/grpc/call_credentials.c13
-rw-r--r--src/php/ext/grpc/channel.c35
-rw-r--r--src/php/ext/grpc/channel_credentials.c31
-rw-r--r--src/php/ext/grpc/server.c36
-rw-r--r--src/php/ext/grpc/server_credentials.c8
-rw-r--r--src/php/ext/grpc/timeval.c68
-rw-r--r--src/php/tests/qps/client.php166
-rw-r--r--src/php/tests/qps/composer.json11
-rw-r--r--src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Control.php127
-rw-r--r--src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Messages.php69
-rw-r--r--src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Payloads.php37
-rw-r--r--src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/ProxyService.php34
-rw-r--r--src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Services.php45
-rw-r--r--src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Stats.php44
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/BenchmarkServiceClient.php78
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/BoolValue.php62
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ByteBufferParams.php65
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ChannelArg.php84
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ClientArgs.php63
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ClientConfig.php407
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ClientStats.php164
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ClientStatus.php44
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ClientType.php34
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ClosedLoopParams.php28
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ComplexProtoParams.php28
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/CoreRequest.php23
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/CoreResponse.php56
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/EchoStatus.php70
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/HistogramData.php153
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/HistogramParams.php93
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/LoadParams.php63
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/Mark.php60
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/Payload.php96
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/PayloadConfig.php80
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/PayloadType.php26
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/PoissonParams.php61
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ProxyClientServiceClient.php72
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ProxyStat.php44
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ReconnectInfo.php71
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ReconnectParams.php49
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/RequestResultCount.php65
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ResponseParameters.php138
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/RpcType.php21
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/Scenario.php291
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResult.php312
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResultSummary.php430
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/Scenarios.php48
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/SecurityParams.php69
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ServerArgs.php63
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ServerConfig.php305
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ServerStats.php191
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ServerStatus.php110
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/ServerType.php33
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/SimpleProtoParams.php65
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/SimpleRequest.php306
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/SimpleResponse.php129
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallRequest.php102
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallResponse.php60
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallRequest.php171
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallResponse.php60
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/Void.php23
-rw-r--r--src/php/tests/qps/generated_code/Grpc/Testing/WorkerServiceClient.php111
-rw-r--r--src/proto/grpc/health/v1/health.options1
-rw-r--r--src/proto/grpc/reflection/v1alpha/BUILD39
-rw-r--r--src/proto/grpc/testing/control.proto5
-rw-r--r--src/proto/grpc/testing/echo_messages.proto1
-rw-r--r--src/proto/grpc/testing/proxy-service.proto (renamed from src/csharp/Grpc.Core.Tests/NUnitVersionTest.cs)55
-rw-r--r--src/python/grpcio/grpc/__init__.py26
-rw-r--r--src/python/grpcio/grpc/_auth.py31
-rw-r--r--src/python/grpcio/grpc/_channel.py68
-rw-r--r--src/python/grpcio/grpc/_common.py61
-rw-r--r--src/python/grpcio/grpc/_plugin_wrapping.py6
-rw-r--r--src/python/grpcio/grpc/_server.py41
-rw-r--r--src/python/grpcio/grpc/beta/_client_adaptations.py7
-rw-r--r--src/python/grpcio/grpc/beta/_connectivity_channel.py159
-rw-r--r--src/python/grpcio/grpc/beta/_server_adaptations.py22
-rw-r--r--src/python/grpcio/grpc/beta/implementations.py11
-rw-r--r--src/python/grpcio/grpc/framework/foundation/logging_pool.py2
-rw-r--r--src/python/grpcio/grpc/framework/interfaces/base/base.py25
-rw-r--r--src/python/grpcio/grpc/framework/interfaces/face/face.py2
-rw-r--r--src/python/grpcio/grpc_version.py2
-rw-r--r--src/python/grpcio_health_checking/grpc_version.py2
-rw-r--r--src/python/grpcio_health_checking/setup.py2
-rw-r--r--src/python/grpcio_reflection/grpc_version.py2
-rw-r--r--src/python/grpcio_reflection/setup.py2
-rw-r--r--src/python/grpcio_tests/grpc_version.py2
-rw-r--r--src/python/grpcio_tests/setup.py2
-rw-r--r--src/python/grpcio_tests/tests/http2/negative_http2_client.py2
-rw-r--r--src/python/grpcio_tests/tests/interop/client.py2
-rw-r--r--src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py44
-rw-r--r--src/python/grpcio_tests/tests/unit/_invocation_defects_test.py4
-rw-r--r--src/python/grpcio_tests/tests/unit/_metadata_test.py6
-rw-r--r--src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py4
-rw-r--r--src/ruby/ext/grpc/extconf.rb6
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.c6
-rw-r--r--src/ruby/ext/grpc/rb_grpc_imports.generated.h9
-rw-r--r--src/ruby/lib/grpc/generic/client_stub.rb2
-rw-r--r--src/ruby/lib/grpc/version.rb2
-rwxr-xr-xsrc/ruby/qps/proxy-worker.rb160
-rw-r--r--src/ruby/qps/src/proto/grpc/testing/proxy-service_pb.rb17
-rw-r--r--src/ruby/qps/src/proto/grpc/testing/proxy-service_services_pb.rb55
-rw-r--r--src/ruby/tools/version.rb2
355 files changed, 13108 insertions, 3986 deletions
diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc
index e481aaf811..2908b639f3 100644
--- a/src/compiler/cpp_generator.cc
+++ b/src/compiler/cpp_generator.cc
@@ -102,7 +102,7 @@ grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) {
vars["filename_base"] = file->filename_without_ext();
vars["message_header_ext"] = file->message_header_ext();
- printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n");
+ printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
printer->Print(vars,
"// If you make any local change, they will be lost.\n");
printer->Print(vars, "// source: $filename$\n");
@@ -1010,7 +1010,7 @@ grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) {
vars["message_header_ext"] = file->message_header_ext();
vars["service_header_ext"] = file->service_header_ext();
- printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n");
+ printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
printer->Print(vars,
"// If you make any local change, they will be lost.\n");
printer->Print(vars, "// source: $filename$\n\n");
diff --git a/src/core/ext/census/grpc_filter.c b/src/core/ext/census/grpc_filter.c
index 65cfe1fa90..b80d831557 100644
--- a/src/core/ext/census/grpc_filter.c
+++ b/src/core/ext/census/grpc_filter.c
@@ -127,7 +127,7 @@ static void server_start_transport_op(grpc_exec_ctx *exec_ctx,
static grpc_error *client_init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- grpc_call_element_args *args) {
+ const grpc_call_element_args *args) {
call_data *d = elem->call_data;
GPR_ASSERT(d != NULL);
memset(d, 0, sizeof(*d));
@@ -146,7 +146,7 @@ static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
static grpc_error *server_init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- grpc_call_element_args *args) {
+ const grpc_call_element_args *args) {
call_data *d = elem->call_data;
GPR_ASSERT(d != NULL);
memset(d, 0, sizeof(*d));
diff --git a/src/core/ext/client_channel/client_channel.c b/src/core/ext/client_channel/client_channel.c
index 4ab467329a..bf64f84772 100644
--- a/src/core/ext/client_channel/client_channel.c
+++ b/src/core/ext/client_channel/client_channel.c
@@ -44,13 +44,14 @@
#include <grpc/support/useful.h>
#include "src/core/ext/client_channel/http_connect_handshaker.h"
-#include "src/core/ext/client_channel/http_proxy.h"
#include "src/core/ext/client_channel/lb_policy_registry.h"
+#include "src/core/ext/client_channel/proxy_mapper_registry.h"
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/ext/client_channel/subchannel.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/connected_channel.h"
#include "src/core/lib/channel/deadline_filter.h"
+#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/profiling/timers.h"
@@ -75,24 +76,82 @@ typedef enum {
WAIT_FOR_READY_TRUE
} wait_for_ready_value;
-typedef struct method_parameters {
+typedef struct {
+ gpr_refcount refs;
gpr_timespec timeout;
wait_for_ready_value wait_for_ready;
} method_parameters;
+static method_parameters *method_parameters_ref(
+ method_parameters *method_params) {
+ gpr_ref(&method_params->refs);
+ return method_params;
+}
+
+static void method_parameters_unref(method_parameters *method_params) {
+ if (gpr_unref(&method_params->refs)) {
+ gpr_free(method_params);
+ }
+}
+
static void *method_parameters_copy(void *value) {
- void *new_value = gpr_malloc(sizeof(method_parameters));
- memcpy(new_value, value, sizeof(method_parameters));
- return new_value;
+ return method_parameters_ref(value);
}
-static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *p) {
- gpr_free(p);
+static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *value) {
+ method_parameters_unref(value);
}
static const grpc_slice_hash_table_vtable method_parameters_vtable = {
method_parameters_free, method_parameters_copy};
+static bool parse_wait_for_ready(grpc_json *field,
+ wait_for_ready_value *wait_for_ready) {
+ if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
+ return false;
+ }
+ *wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
+ : WAIT_FOR_READY_FALSE;
+ return true;
+}
+
+static bool parse_timeout(grpc_json *field, gpr_timespec *timeout) {
+ if (field->type != GRPC_JSON_STRING) return false;
+ size_t len = strlen(field->value);
+ if (field->value[len - 1] != 's') return false;
+ char *buf = gpr_strdup(field->value);
+ buf[len - 1] = '\0'; // Remove trailing 's'.
+ char *decimal_point = strchr(buf, '.');
+ if (decimal_point != NULL) {
+ *decimal_point = '\0';
+ timeout->tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
+ if (timeout->tv_nsec == -1) {
+ gpr_free(buf);
+ return false;
+ }
+ // There should always be exactly 3, 6, or 9 fractional digits.
+ int multiplier = 1;
+ switch (strlen(decimal_point + 1)) {
+ case 9:
+ break;
+ case 6:
+ multiplier *= 1000;
+ break;
+ case 3:
+ multiplier *= 1000000;
+ break;
+ default: // Unsupported number of digits.
+ gpr_free(buf);
+ return false;
+ }
+ timeout->tv_nsec *= multiplier;
+ }
+ timeout->tv_sec = gpr_parse_nonnegative_int(buf);
+ gpr_free(buf);
+ if (timeout->tv_sec == -1) return false;
+ return true;
+}
+
static void *method_parameters_create_from_json(const grpc_json *json) {
wait_for_ready_value wait_for_ready = WAIT_FOR_READY_UNSET;
gpr_timespec timeout = {0, 0, GPR_TIMESPAN};
@@ -100,49 +159,14 @@ static void *method_parameters_create_from_json(const grpc_json *json) {
if (field->key == NULL) continue;
if (strcmp(field->key, "waitForReady") == 0) {
if (wait_for_ready != WAIT_FOR_READY_UNSET) return NULL; // Duplicate.
- if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
- return NULL;
- }
- wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
- : WAIT_FOR_READY_FALSE;
+ if (!parse_wait_for_ready(field, &wait_for_ready)) return NULL;
} else if (strcmp(field->key, "timeout") == 0) {
if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) return NULL; // Duplicate.
- if (field->type != GRPC_JSON_STRING) return NULL;
- size_t len = strlen(field->value);
- if (field->value[len - 1] != 's') return NULL;
- char *buf = gpr_strdup(field->value);
- buf[len - 1] = '\0'; // Remove trailing 's'.
- char *decimal_point = strchr(buf, '.');
- if (decimal_point != NULL) {
- *decimal_point = '\0';
- timeout.tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
- if (timeout.tv_nsec == -1) {
- gpr_free(buf);
- return NULL;
- }
- // There should always be exactly 3, 6, or 9 fractional digits.
- int multiplier = 1;
- switch (strlen(decimal_point + 1)) {
- case 9:
- break;
- case 6:
- multiplier *= 1000;
- break;
- case 3:
- multiplier *= 1000000;
- break;
- default: // Unsupported number of digits.
- gpr_free(buf);
- return NULL;
- }
- timeout.tv_nsec *= multiplier;
- }
- timeout.tv_sec = gpr_parse_nonnegative_int(buf);
- if (timeout.tv_sec == -1) return NULL;
- gpr_free(buf);
+ if (!parse_timeout(field, &timeout)) return NULL;
}
}
method_parameters *value = gpr_malloc(sizeof(method_parameters));
+ gpr_ref_init(&value->refs, 1);
value->timeout = timeout;
value->wait_for_ready = wait_for_ready;
return value;
@@ -153,10 +177,6 @@ static void *method_parameters_create_from_json(const grpc_json *json) {
*/
typedef struct client_channel_channel_data {
- /** server name */
- char *server_name;
- /** HTTP CONNECT proxy to use, if any */
- char *proxy_name;
/** resolver for this channel */
grpc_resolver *resolver;
/** have we started resolving this channel */
@@ -164,13 +184,10 @@ typedef struct client_channel_channel_data {
/** client channel factory */
grpc_client_channel_factory *client_channel_factory;
- /** mutex protecting all variables below in this data structure */
- gpr_mu mu;
+ /** combiner protecting all variables below in this data structure */
+ grpc_combiner *combiner;
/** currently active load balancer */
- char *lb_policy_name;
grpc_lb_policy *lb_policy;
- /** service config in JSON form */
- char *service_config_json;
/** maps method names to method_parameters structs */
grpc_slice_hash_table *method_params_table;
/** incoming resolver result - set by resolver.next() */
@@ -187,6 +204,13 @@ typedef struct client_channel_channel_data {
grpc_channel_stack *owning_stack;
/** interested parties (owned) */
grpc_pollset_set *interested_parties;
+
+ /* the following properties are guarded by a mutex since API's require them
+ to be instantaneously available */
+ gpr_mu info_mu;
+ char *info_lb_policy_name;
+ /** service config in JSON form */
+ char *info_service_config_json;
} channel_data;
/** We create one watcher for each new lb_policy that is returned from a
@@ -199,9 +223,9 @@ typedef struct {
grpc_lb_policy *lb_policy;
} lb_policy_connectivity_watcher;
-static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
- grpc_lb_policy *lb_policy,
- grpc_connectivity_state current_state);
+static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
+ grpc_lb_policy *lb_policy,
+ grpc_connectivity_state current_state);
static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
channel_data *chand,
@@ -212,7 +236,7 @@ static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
state == GRPC_CHANNEL_SHUTDOWN) &&
chand->lb_policy != NULL) {
/* cancel picks with wait_for_ready=false */
- grpc_lb_policy_cancel_picks(
+ grpc_lb_policy_cancel_picks_locked(
exec_ctx, chand->lb_policy,
/* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
/* check= */ 0, GRPC_ERROR_REF(error));
@@ -222,54 +246,45 @@ static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
}
static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
- lb_policy_connectivity_watcher *w,
- grpc_error *error) {
+ void *arg, grpc_error *error) {
+ lb_policy_connectivity_watcher *w = arg;
grpc_connectivity_state publish_state = w->state;
- /* check if the notification is for a stale policy */
- if (w->lb_policy != w->chand->lb_policy) return;
-
- if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
- publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
- grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
- GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
- w->chand->lb_policy = NULL;
- }
- set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
- GRPC_ERROR_REF(error), "lb_changed");
- if (w->state != GRPC_CHANNEL_SHUTDOWN) {
- watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
+ /* check if the notification is for the latest policy */
+ if (w->lb_policy == w->chand->lb_policy) {
+ if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
+ publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
+ grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
+ GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
+ w->chand->lb_policy = NULL;
+ }
+ set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
+ GRPC_ERROR_REF(error), "lb_changed");
+ if (w->state != GRPC_CHANNEL_SHUTDOWN) {
+ watch_lb_policy_locked(exec_ctx, w->chand, w->lb_policy, w->state);
+ }
}
-}
-
-static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
- lb_policy_connectivity_watcher *w = arg;
-
- gpr_mu_lock(&w->chand->mu);
- on_lb_policy_state_changed_locked(exec_ctx, w, error);
- gpr_mu_unlock(&w->chand->mu);
GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
gpr_free(w);
}
-static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
- grpc_lb_policy *lb_policy,
- grpc_connectivity_state current_state) {
+static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
+ grpc_lb_policy *lb_policy,
+ grpc_connectivity_state current_state) {
lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
w->chand = chand;
- grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w,
- grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w,
+ grpc_combiner_scheduler(chand->combiner, false));
w->state = current_state;
w->lb_policy = lb_policy;
- grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
- &w->on_changed);
+ grpc_lb_policy_notify_on_state_change_locked(exec_ctx, lb_policy, &w->state,
+ &w->on_changed);
}
-static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
+ void *arg, grpc_error *error) {
channel_data *chand = arg;
char *lb_policy_name = NULL;
grpc_lb_policy *lb_policy = NULL;
@@ -317,28 +332,18 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
// Use pick_first if nothing was specified and we didn't select grpclb
// above.
if (lb_policy_name == NULL) lb_policy_name = "pick_first";
- // If using a proxy, add channel arg for server in HTTP CONNECT request.
- if (chand->proxy_name != NULL) {
- grpc_arg new_arg;
- new_arg.key = GRPC_ARG_HTTP_CONNECT_SERVER;
- new_arg.type = GRPC_ARG_STRING;
- new_arg.value.string = chand->server_name;
- grpc_channel_args *tmp_args = chand->resolver_result;
- chand->resolver_result =
- grpc_channel_args_copy_and_add(chand->resolver_result, &new_arg, 1);
- grpc_channel_args_destroy(exec_ctx, tmp_args);
- }
// Instantiate LB policy.
grpc_lb_policy_args lb_policy_args;
lb_policy_args.args = chand->resolver_result;
lb_policy_args.client_channel_factory = chand->client_channel_factory;
+ lb_policy_args.combiner = chand->combiner;
lb_policy =
grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
if (lb_policy != NULL) {
GRPC_LB_POLICY_REF(lb_policy, "config_change");
GRPC_ERROR_UNREF(state_error);
- state =
- grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
+ state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
+ &state_error);
}
// Find service config.
channel_arg =
@@ -368,17 +373,18 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
chand->interested_parties);
}
- gpr_mu_lock(&chand->mu);
+ gpr_mu_lock(&chand->info_mu);
if (lb_policy_name != NULL) {
- gpr_free(chand->lb_policy_name);
- chand->lb_policy_name = lb_policy_name;
+ gpr_free(chand->info_lb_policy_name);
+ chand->info_lb_policy_name = lb_policy_name;
}
old_lb_policy = chand->lb_policy;
chand->lb_policy = lb_policy;
if (service_config_json != NULL) {
- gpr_free(chand->service_config_json);
- chand->service_config_json = service_config_json;
+ gpr_free(chand->info_service_config_json);
+ chand->info_service_config_json = service_config_json;
}
+ gpr_mu_unlock(&chand->info_mu);
if (chand->method_params_table != NULL) {
grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
}
@@ -401,15 +407,15 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
set_channel_connectivity_state_locked(
exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
if (lb_policy != NULL) {
- watch_lb_policy(exec_ctx, chand, lb_policy, state);
+ watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
}
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
- grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
- &chand->on_resolver_result_changed);
- gpr_mu_unlock(&chand->mu);
+ grpc_resolver_next_locked(exec_ctx, chand->resolver,
+ &chand->resolver_result,
+ &chand->on_resolver_result_changed);
} else {
if (chand->resolver != NULL) {
- grpc_resolver_shutdown(exec_ctx, chand->resolver);
+ grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL;
}
@@ -419,11 +425,10 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
GPR_ARRAY_SIZE(refs)),
"resolver_gone");
- gpr_mu_unlock(&chand->mu);
}
if (exit_idle) {
- grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
+ grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
}
@@ -441,20 +446,12 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_ERROR_UNREF(state_error);
}
-static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
- grpc_channel_element *elem,
- grpc_transport_op *op) {
+static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error_ignored) {
+ grpc_transport_op *op = arg;
+ grpc_channel_element *elem = op->transport_private.args[0];
channel_data *chand = elem->channel_data;
- grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
-
- GPR_ASSERT(op->set_accept_stream == false);
- if (op->bind_pollset != NULL) {
- grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
- op->bind_pollset);
- }
-
- gpr_mu_lock(&chand->mu);
if (op->on_connectivity_state_change != NULL) {
grpc_connectivity_state_notify_on_state_change(
exec_ctx, &chand->state_tracker, op->connectivity_state,
@@ -468,7 +465,7 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_closure_sched(exec_ctx, op->send_ping,
GRPC_ERROR_CREATE("Ping with no load balancing"));
} else {
- grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
+ grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping);
op->bind_pollset = NULL;
}
op->send_ping = NULL;
@@ -479,7 +476,7 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
set_channel_connectivity_state_locked(
exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
- grpc_resolver_shutdown(exec_ctx, chand->resolver);
+ grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL;
if (!chand->started_resolving) {
@@ -497,25 +494,48 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
}
GRPC_ERROR_UNREF(op->disconnect_with_error);
}
- gpr_mu_unlock(&chand->mu);
+ GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
+
+ grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
+}
+
+static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem,
+ grpc_transport_op *op) {
+ channel_data *chand = elem->channel_data;
+
+ GPR_ASSERT(op->set_accept_stream == false);
+ if (op->bind_pollset != NULL) {
+ grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
+ op->bind_pollset);
+ }
+
+ op->transport_private.args[0] = elem;
+ GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
+ grpc_closure_sched(
+ exec_ctx, grpc_closure_init(
+ &op->transport_private.closure, start_transport_op_locked,
+ op, grpc_combiner_scheduler(chand->combiner, false)),
+ GRPC_ERROR_NONE);
}
static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
const grpc_channel_info *info) {
channel_data *chand = elem->channel_data;
- gpr_mu_lock(&chand->mu);
+ gpr_mu_lock(&chand->info_mu);
if (info->lb_policy_name != NULL) {
- *info->lb_policy_name = chand->lb_policy_name == NULL
+ *info->lb_policy_name = chand->info_lb_policy_name == NULL
? NULL
- : gpr_strdup(chand->lb_policy_name);
+ : gpr_strdup(chand->info_lb_policy_name);
}
if (info->service_config_json != NULL) {
- *info->service_config_json = chand->service_config_json == NULL
- ? NULL
- : gpr_strdup(chand->service_config_json);
+ *info->service_config_json =
+ chand->info_service_config_json == NULL
+ ? NULL
+ : gpr_strdup(chand->info_service_config_json);
}
- gpr_mu_unlock(&chand->mu);
+ gpr_mu_unlock(&chand->info_mu);
}
/* Constructor for channel_data */
@@ -523,15 +543,15 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
grpc_channel_element_args *args) {
channel_data *chand = elem->channel_data;
- memset(chand, 0, sizeof(*chand));
GPR_ASSERT(args->is_last);
GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
// Initialize data members.
- gpr_mu_init(&chand->mu);
+ chand->combiner = grpc_combiner_create(NULL);
+ gpr_mu_init(&chand->info_mu);
chand->owning_stack = args->channel_stack;
grpc_closure_init(&chand->on_resolver_result_changed,
- on_resolver_result_changed, chand,
- grpc_schedule_on_exec_ctx);
+ on_resolver_result_changed_locked, chand,
+ grpc_combiner_scheduler(chand->combiner, false));
chand->interested_parties = grpc_pollset_set_create();
grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
"client_channel");
@@ -542,39 +562,44 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
grpc_client_channel_factory_ref(arg->value.pointer.p);
chand->client_channel_factory = arg->value.pointer.p;
- // Instantiate resolver.
+ // Get server name to resolve, using proxy mapper if needed.
arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
GPR_ASSERT(arg != NULL);
GPR_ASSERT(arg->type == GRPC_ARG_STRING);
- grpc_uri *uri = grpc_uri_parse(arg->value.string, true);
- if (uri == NULL) return GRPC_ERROR_CREATE("cannot parse server URI");
- if (uri->path[0] == '\0') {
- grpc_uri_destroy(uri);
- return GRPC_ERROR_CREATE("server URI is missing path");
- }
- chand->server_name =
- gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path);
- grpc_uri_destroy(uri);
- chand->proxy_name = grpc_get_http_proxy_server();
- char *name_to_resolve =
- chand->proxy_name == NULL ? arg->value.string : chand->proxy_name;
+ char *proxy_name = NULL;
+ grpc_channel_args *new_args = NULL;
+ grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
+ &proxy_name, &new_args);
+ // Instantiate resolver.
chand->resolver = grpc_resolver_create(
- exec_ctx, name_to_resolve, args->channel_args, chand->interested_parties);
+ exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
+ new_args != NULL ? new_args : args->channel_args,
+ chand->interested_parties, chand->combiner);
+ if (proxy_name != NULL) gpr_free(proxy_name);
+ if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
if (chand->resolver == NULL) {
return GRPC_ERROR_CREATE("resolver creation failed");
}
return GRPC_ERROR_NONE;
}
+static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ grpc_resolver *resolver = arg;
+ grpc_resolver_shutdown_locked(exec_ctx, resolver);
+ GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
+}
+
/* Destructor for channel_data */
static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) {
channel_data *chand = elem->channel_data;
- gpr_free(chand->server_name);
- gpr_free(chand->proxy_name);
if (chand->resolver != NULL) {
- grpc_resolver_shutdown(exec_ctx, chand->resolver);
- GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
+ grpc_closure_sched(
+ exec_ctx,
+ grpc_closure_create(shutdown_resolver_locked, chand->resolver,
+ grpc_combiner_scheduler(chand->combiner, false)),
+ GRPC_ERROR_NONE);
}
if (chand->client_channel_factory != NULL) {
grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
@@ -585,14 +610,15 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
chand->interested_parties);
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
}
- gpr_free(chand->lb_policy_name);
- gpr_free(chand->service_config_json);
+ gpr_free(chand->info_lb_policy_name);
+ gpr_free(chand->info_service_config_json);
if (chand->method_params_table != NULL) {
grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
}
grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
- grpc_pollset_set_destroy(chand->interested_parties);
- gpr_mu_destroy(&chand->mu);
+ grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
+ GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
+ gpr_mu_destroy(&chand->info_mu);
}
/*************************************************************************
@@ -626,7 +652,7 @@ typedef struct client_channel_call_data {
grpc_slice path; // Request path.
gpr_timespec call_start_time;
gpr_timespec deadline;
- wait_for_ready_value wait_for_ready_from_service_config;
+ method_parameters *method_params;
grpc_closure read_service_config;
grpc_error *cancel_error;
@@ -635,8 +661,6 @@ typedef struct client_channel_call_data {
grpc_subchannel_call */
gpr_atm subchannel_call;
- gpr_mu mu;
-
subchannel_creation_phase creation_phase;
grpc_connected_subchannel *connected_subchannel;
grpc_polling_entity *pollent;
@@ -681,52 +705,32 @@ static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
GRPC_ERROR_UNREF(error);
}
-typedef struct {
- grpc_transport_stream_op **ops;
- size_t nops;
- grpc_subchannel_call *call;
-} retry_ops_args;
-
-static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) {
- retry_ops_args *a = args;
- size_t i;
- for (i = 0; i < a->nops; i++) {
- grpc_subchannel_call_process_op(exec_ctx, a->call, a->ops[i]);
- }
- GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, a->call, "retry_ops");
- gpr_free(a->ops);
- gpr_free(a);
-}
-
static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
if (calld->waiting_ops_count == 0) {
return;
}
- retry_ops_args *a = gpr_malloc(sizeof(*a));
- a->ops = calld->waiting_ops;
- a->nops = calld->waiting_ops_count;
- a->call = GET_CALL(calld);
- if (a->call == CANCELLED_CALL) {
- gpr_free(a);
+ grpc_subchannel_call *call = GET_CALL(calld);
+ grpc_transport_stream_op **ops = calld->waiting_ops;
+ size_t nops = calld->waiting_ops_count;
+ if (call == CANCELLED_CALL) {
fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
return;
}
calld->waiting_ops = NULL;
calld->waiting_ops_count = 0;
calld->waiting_ops_capacity = 0;
- GRPC_SUBCHANNEL_CALL_REF(a->call, "retry_ops");
- grpc_closure_sched(
- exec_ctx, grpc_closure_create(retry_ops, a, grpc_schedule_on_exec_ctx),
- GRPC_ERROR_NONE);
+ for (size_t i = 0; i < nops; i++) {
+ grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
+ }
+ gpr_free(ops);
}
-static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
grpc_call_element *elem = arg;
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
- gpr_mu_lock(&calld->mu);
GPR_ASSERT(calld->creation_phase ==
GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
@@ -762,7 +766,6 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg,
(gpr_atm)(uintptr_t)subchannel_call);
retry_waiting_locked(exec_ctx, calld);
}
- gpr_mu_unlock(&calld->mu);
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
}
@@ -788,37 +791,35 @@ typedef struct {
/** Return true if subchannel is available immediately (in which case on_ready
should not be called), or false otherwise (in which case on_ready should be
called when the subchannel is available). */
-static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- grpc_metadata_batch *initial_metadata,
- uint32_t initial_metadata_flags,
- grpc_connected_subchannel **connected_subchannel,
- grpc_closure *on_ready, grpc_error *error);
-
-static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static bool pick_subchannel_locked(
+ grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+ grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
+ grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
+ grpc_error *error);
+
+static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
continue_picking_args *cpa = arg;
if (cpa->connected_subchannel == NULL) {
/* cancelled, do nothing */
} else if (error != GRPC_ERROR_NONE) {
grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
} else {
- call_data *calld = cpa->elem->call_data;
- gpr_mu_lock(&calld->mu);
- if (pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
- cpa->initial_metadata_flags, cpa->connected_subchannel,
- cpa->on_ready, GRPC_ERROR_NONE)) {
+ if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
+ cpa->initial_metadata_flags,
+ cpa->connected_subchannel, cpa->on_ready,
+ GRPC_ERROR_NONE)) {
grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
}
- gpr_mu_unlock(&calld->mu);
}
gpr_free(cpa);
}
-static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
- grpc_metadata_batch *initial_metadata,
- uint32_t initial_metadata_flags,
- grpc_connected_subchannel **connected_subchannel,
- grpc_closure *on_ready, grpc_error *error) {
+static bool pick_subchannel_locked(
+ grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+ grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
+ grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
+ grpc_error *error) {
GPR_TIMER_BEGIN("pick_subchannel", 0);
channel_data *chand = elem->channel_data;
@@ -828,11 +829,11 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
GPR_ASSERT(connected_subchannel);
- gpr_mu_lock(&chand->mu);
if (initial_metadata == NULL) {
if (chand->lb_policy != NULL) {
- grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
- connected_subchannel, GRPC_ERROR_REF(error));
+ grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
+ connected_subchannel,
+ GRPC_ERROR_REF(error));
}
for (closure = chand->waiting_for_config_closures.head; closure != NULL;
closure = closure->next_data.next) {
@@ -844,7 +845,6 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1));
}
}
- gpr_mu_unlock(&chand->mu);
GPR_TIMER_END("pick_subchannel", 0);
GRPC_ERROR_UNREF(error);
return true;
@@ -853,7 +853,6 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
if (chand->lb_policy != NULL) {
grpc_lb_policy *lb_policy = chand->lb_policy;
GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
- gpr_mu_unlock(&chand->mu);
// If the application explicitly set wait_for_ready, use that.
// Otherwise, if the service config specified a value for this
// method, use that.
@@ -861,10 +860,11 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
initial_metadata_flags &
GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
const bool wait_for_ready_set_from_service_config =
- calld->wait_for_ready_from_service_config != WAIT_FOR_READY_UNSET;
+ calld->method_params != NULL &&
+ calld->method_params->wait_for_ready != WAIT_FOR_READY_UNSET;
if (!wait_for_ready_set_from_api &&
wait_for_ready_set_from_service_config) {
- if (calld->wait_for_ready_from_service_config == WAIT_FOR_READY_TRUE) {
+ if (calld->method_params->wait_for_ready == WAIT_FOR_READY_TRUE) {
initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
} else {
initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
@@ -873,7 +873,7 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_lb_policy_pick_args inputs = {
initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
gpr_inf_future(GPR_CLOCK_MONOTONIC)};
- const bool result = grpc_lb_policy_pick(
+ const bool result = grpc_lb_policy_pick_locked(
exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
GPR_TIMER_END("pick_subchannel", 0);
@@ -882,8 +882,9 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
if (chand->resolver != NULL && !chand->started_resolving) {
chand->started_resolving = true;
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
- grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
- &chand->on_resolver_result_changed);
+ grpc_resolver_next_locked(exec_ctx, chand->resolver,
+ &chand->resolver_result,
+ &chand->on_resolver_result_changed);
}
if (chand->resolver != NULL) {
cpa = gpr_malloc(sizeof(*cpa));
@@ -892,88 +893,66 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
cpa->connected_subchannel = connected_subchannel;
cpa->on_ready = on_ready;
cpa->elem = elem;
- grpc_closure_init(&cpa->closure, continue_picking, cpa,
- grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
+ grpc_combiner_scheduler(chand->combiner, true));
grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
GRPC_ERROR_NONE);
} else {
grpc_closure_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"));
}
- gpr_mu_unlock(&chand->mu);
GPR_TIMER_END("pick_subchannel", 0);
return false;
}
-// The logic here is fairly complicated, due to (a) the fact that we
-// need to handle the case where we receive the send op before the
-// initial metadata op, and (b) the need for efficiency, especially in
-// the streaming case.
-// TODO(ctiller): Explain this more thoroughly.
-static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
- grpc_call_element *elem,
- grpc_transport_stream_op *op) {
- call_data *calld = elem->call_data;
+static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
+ grpc_transport_stream_op *op,
+ grpc_call_element *elem) {
channel_data *chand = elem->channel_data;
- GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
- grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
- /* try to (atomically) get the call */
- grpc_subchannel_call *call = GET_CALL(calld);
- GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
- if (call == CANCELLED_CALL) {
- grpc_transport_stream_op_finish_with_failure(
- exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
- GPR_TIMER_END("cc_start_transport_stream_op", 0);
- return;
- }
- if (call != NULL) {
- grpc_subchannel_call_process_op(exec_ctx, call, op);
- GPR_TIMER_END("cc_start_transport_stream_op", 0);
- return;
- }
- /* we failed; lock and figure out what to do */
- gpr_mu_lock(&calld->mu);
-retry:
+ call_data *calld = elem->call_data;
+ grpc_subchannel_call *call;
+
/* need to recheck that another thread hasn't set the call */
call = GET_CALL(calld);
if (call == CANCELLED_CALL) {
- gpr_mu_unlock(&calld->mu);
grpc_transport_stream_op_finish_with_failure(
exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
- GPR_TIMER_END("cc_start_transport_stream_op", 0);
+ /* early out */
return;
}
if (call != NULL) {
- gpr_mu_unlock(&calld->mu);
grpc_subchannel_call_process_op(exec_ctx, call, op);
- GPR_TIMER_END("cc_start_transport_stream_op", 0);
+ /* early out */
return;
}
/* if this is a cancellation, then we can raise our cancelled flag */
if (op->cancel_error != GRPC_ERROR_NONE) {
if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
(gpr_atm)(uintptr_t)CANCELLED_CALL)) {
- goto retry;
+ /* recurse to retry */
+ start_transport_stream_op_locked_inner(exec_ctx, op, elem);
+ /* early out */
+ return;
} else {
- // Stash a copy of cancel_error in our call data, so that we can use
- // it for subsequent operations. This ensures that if the call is
- // cancelled before any ops are passed down (e.g., if the deadline
- // is in the past when the call starts), we can return the right
- // error to the caller when the first op does get passed down.
+ /* Stash a copy of cancel_error in our call data, so that we can use
+ it for subsequent operations. This ensures that if the call is
+ cancelled before any ops are passed down (e.g., if the deadline
+ is in the past when the call starts), we can return the right
+ error to the caller when the first op does get passed down. */
calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
switch (calld->creation_phase) {
case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
break;
case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
- pick_subchannel(exec_ctx, elem, NULL, 0, &calld->connected_subchannel,
- NULL, GRPC_ERROR_REF(op->cancel_error));
+ pick_subchannel_locked(exec_ctx, elem, NULL, 0,
+ &calld->connected_subchannel, NULL,
+ GRPC_ERROR_REF(op->cancel_error));
break;
}
- gpr_mu_unlock(&calld->mu);
grpc_transport_stream_op_finish_with_failure(
exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
- GPR_TIMER_END("cc_start_transport_stream_op", 0);
+ /* early out */
return;
}
}
@@ -982,16 +961,16 @@ retry:
calld->connected_subchannel == NULL &&
op->send_initial_metadata != NULL) {
calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
- grpc_closure_init(&calld->next_step, subchannel_ready, elem,
- grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
+ grpc_combiner_scheduler(chand->combiner, true));
GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
/* If a subchannel is not available immediately, the polling entity from
call_data should be provided to channel_data's interested_parties, so
that IO of the lb_policy and resolver could be done under it. */
- if (pick_subchannel(exec_ctx, elem, op->send_initial_metadata,
- op->send_initial_metadata_flags,
- &calld->connected_subchannel, &calld->next_step,
- GRPC_ERROR_NONE)) {
+ if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
+ op->send_initial_metadata_flags,
+ &calld->connected_subchannel, &calld->next_step,
+ GRPC_ERROR_NONE)) {
calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
} else {
@@ -1014,131 +993,181 @@ retry:
gpr_atm_rel_store(&calld->subchannel_call,
(gpr_atm)(uintptr_t)subchannel_call);
retry_waiting_locked(exec_ctx, calld);
- goto retry;
+ /* recurse to retry */
+ start_transport_stream_op_locked_inner(exec_ctx, op, elem);
+ /* early out */
+ return;
}
/* nothing to be done but wait */
add_waiting_locked(calld, op);
- gpr_mu_unlock(&calld->mu);
+}
+
+static void start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error_ignored) {
+ GPR_TIMER_BEGIN("start_transport_stream_op_locked", 0);
+
+ grpc_transport_stream_op *op = arg;
+ grpc_call_element *elem = op->handler_private.args[0];
+ call_data *calld = elem->call_data;
+
+ start_transport_stream_op_locked_inner(exec_ctx, op, elem);
+
+ GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
+ "start_transport_stream_op");
+ GPR_TIMER_END("start_transport_stream_op_locked", 0);
+}
+
+/* The logic here is fairly complicated, due to (a) the fact that we
+ need to handle the case where we receive the send op before the
+ initial metadata op, and (b) the need for efficiency, especially in
+ the streaming case.
+
+ We use double-checked locking to initially see if initialization has been
+ performed. If it has not, we acquire the combiner and perform initialization.
+ If it has, we proceed on the fast path. */
+static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_transport_stream_op *op) {
+ call_data *calld = elem->call_data;
+ channel_data *chand = elem->channel_data;
+ GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
+ grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
+ /* try to (atomically) get the call */
+ grpc_subchannel_call *call = GET_CALL(calld);
+ GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
+ if (call == CANCELLED_CALL) {
+ grpc_transport_stream_op_finish_with_failure(
+ exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
+ GPR_TIMER_END("cc_start_transport_stream_op", 0);
+ /* early out */
+ return;
+ }
+ if (call != NULL) {
+ grpc_subchannel_call_process_op(exec_ctx, call, op);
+ GPR_TIMER_END("cc_start_transport_stream_op", 0);
+ /* early out */
+ return;
+ }
+ /* we failed; lock and figure out what to do */
+ GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
+ op->handler_private.args[0] = elem;
+ grpc_closure_sched(
+ exec_ctx,
+ grpc_closure_init(&op->handler_private.closure,
+ start_transport_stream_op_locked, op,
+ grpc_combiner_scheduler(chand->combiner, false)),
+ GRPC_ERROR_NONE);
GPR_TIMER_END("cc_start_transport_stream_op", 0);
}
+// Sets calld->method_params.
+// If the method params specify a timeout, populates
+// *per_method_deadline and returns true.
+static bool set_call_method_params_from_service_config_locked(
+ grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
+ gpr_timespec *per_method_deadline) {
+ channel_data *chand = elem->channel_data;
+ call_data *calld = elem->call_data;
+ if (chand->method_params_table != NULL) {
+ calld->method_params = grpc_method_config_table_get(
+ exec_ctx, chand->method_params_table, calld->path);
+ if (calld->method_params != NULL) {
+ method_parameters_ref(calld->method_params);
+ if (gpr_time_cmp(calld->method_params->timeout,
+ gpr_time_0(GPR_TIMESPAN)) != 0) {
+ *per_method_deadline =
+ gpr_time_add(calld->call_start_time, calld->method_params->timeout);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
// Gets data from the service config. Invoked when the resolver returns
// its initial result.
-static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static void read_service_config_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
grpc_call_element *elem = arg;
- channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data;
// If this is an error, there's no point in looking at the service config.
if (error == GRPC_ERROR_NONE) {
- // Get the method config table from channel data.
- gpr_mu_lock(&chand->mu);
- grpc_slice_hash_table *method_params_table = NULL;
- if (chand->method_params_table != NULL) {
- method_params_table =
- grpc_slice_hash_table_ref(chand->method_params_table);
- }
- gpr_mu_unlock(&chand->mu);
- // If the method config table was present, use it.
- if (method_params_table != NULL) {
- const method_parameters *method_params = grpc_method_config_table_get(
- exec_ctx, method_params_table, calld->path);
- if (method_params != NULL) {
- const bool have_method_timeout =
- gpr_time_cmp(method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0;
- if (have_method_timeout ||
- method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
- gpr_mu_lock(&calld->mu);
- if (have_method_timeout) {
- const gpr_timespec per_method_deadline =
- gpr_time_add(calld->call_start_time, method_params->timeout);
- if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
- calld->deadline = per_method_deadline;
- // Reset deadline timer.
- grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
- }
- }
- if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
- calld->wait_for_ready_from_service_config =
- method_params->wait_for_ready;
- }
- gpr_mu_unlock(&calld->mu);
- }
+ gpr_timespec per_method_deadline;
+ if (set_call_method_params_from_service_config_locked(
+ exec_ctx, elem, &per_method_deadline)) {
+ // If the deadline from the service config is shorter than the one
+ // from the client API, reset the deadline timer.
+ if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
+ calld->deadline = per_method_deadline;
+ grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
}
- grpc_slice_hash_table_unref(exec_ctx, method_params_table);
}
}
GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
}
-/* Constructor for call_data */
-static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
- grpc_call_element *elem,
- grpc_call_element_args *args) {
+static void initial_read_service_config_locked(grpc_exec_ctx *exec_ctx,
+ void *arg,
+ grpc_error *error_ignored) {
+ grpc_call_element *elem = arg;
channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data;
- // Initialize data members.
- grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
- calld->path = grpc_slice_ref_internal(args->path);
- calld->call_start_time = args->start_time;
- calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
- calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET;
- calld->cancel_error = GRPC_ERROR_NONE;
- gpr_atm_rel_store(&calld->subchannel_call, 0);
- gpr_mu_init(&calld->mu);
- calld->connected_subchannel = NULL;
- calld->waiting_ops = NULL;
- calld->waiting_ops_count = 0;
- calld->waiting_ops_capacity = 0;
- calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
- calld->owning_call = args->call_stack;
- calld->pollent = NULL;
// If the resolver has already returned results, then we can access
// the service config parameters immediately. Otherwise, we need to
// defer that work until the resolver returns an initial result.
- // TODO(roth): This code is almost but not quite identical to the code
- // in read_service_config() above. It would be nice to find a way to
- // combine them, to avoid having to maintain it twice.
- gpr_mu_lock(&chand->mu);
if (chand->lb_policy != NULL) {
// We already have a resolver result, so check for service config.
- if (chand->method_params_table != NULL) {
- grpc_slice_hash_table *method_params_table =
- grpc_slice_hash_table_ref(chand->method_params_table);
- gpr_mu_unlock(&chand->mu);
- method_parameters *method_params = grpc_method_config_table_get(
- exec_ctx, method_params_table, args->path);
- if (method_params != NULL) {
- if (gpr_time_cmp(method_params->timeout,
- gpr_time_0(GPR_CLOCK_MONOTONIC)) != 0) {
- gpr_timespec per_method_deadline =
- gpr_time_add(calld->call_start_time, method_params->timeout);
- calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
- }
- if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
- calld->wait_for_ready_from_service_config =
- method_params->wait_for_ready;
- }
- }
- grpc_slice_hash_table_unref(exec_ctx, method_params_table);
- } else {
- gpr_mu_unlock(&chand->mu);
+ gpr_timespec per_method_deadline;
+ if (set_call_method_params_from_service_config_locked(
+ exec_ctx, elem, &per_method_deadline)) {
+ calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
}
} else {
// We don't yet have a resolver result, so register a callback to
// get the service config data once the resolver returns.
// Take a reference to the call stack to be owned by the callback.
GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config");
- grpc_closure_init(&calld->read_service_config, read_service_config, elem,
- grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&calld->read_service_config, read_service_config_locked,
+ elem, grpc_combiner_scheduler(chand->combiner, false));
grpc_closure_list_append(&chand->waiting_for_config_closures,
&calld->read_service_config, GRPC_ERROR_NONE);
- gpr_mu_unlock(&chand->mu);
}
// Start the deadline timer with the current deadline value. If we
// do not yet have service config data, then the timer may be reset
// later.
grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
+ GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
+ "initial_read_service_config");
+}
+
+/* Constructor for call_data */
+static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ const grpc_call_element_args *args) {
+ channel_data *chand = elem->channel_data;
+ call_data *calld = elem->call_data;
+ // Initialize data members.
+ grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
+ calld->path = grpc_slice_ref_internal(args->path);
+ calld->call_start_time = args->start_time;
+ calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
+ calld->method_params = NULL;
+ calld->cancel_error = GRPC_ERROR_NONE;
+ gpr_atm_rel_store(&calld->subchannel_call, 0);
+ calld->connected_subchannel = NULL;
+ calld->waiting_ops = NULL;
+ calld->waiting_ops_count = 0;
+ calld->waiting_ops_capacity = 0;
+ calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
+ calld->owning_call = args->call_stack;
+ calld->pollent = NULL;
+ GRPC_CALL_STACK_REF(calld->owning_call, "initial_read_service_config");
+ grpc_closure_sched(
+ exec_ctx,
+ grpc_closure_init(&calld->read_service_config,
+ initial_read_service_config_locked, elem,
+ grpc_combiner_scheduler(chand->combiner, false)),
+ GRPC_ERROR_NONE);
return GRPC_ERROR_NONE;
}
@@ -1150,13 +1179,15 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
call_data *calld = elem->call_data;
grpc_deadline_state_destroy(exec_ctx, elem);
grpc_slice_unref_internal(exec_ctx, calld->path);
+ if (calld->method_params != NULL) {
+ method_parameters_unref(calld->method_params);
+ }
GRPC_ERROR_UNREF(calld->cancel_error);
grpc_subchannel_call *call = GET_CALL(calld);
if (call != NULL && call != CANCELLED_CALL) {
GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
}
GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
- gpr_mu_destroy(&calld->mu);
GPR_ASSERT(calld->waiting_ops_count == 0);
if (calld->connected_subchannel != NULL) {
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
@@ -1192,26 +1223,37 @@ const grpc_channel_filter grpc_client_channel_filter = {
"client-channel",
};
+static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error_ignored) {
+ channel_data *chand = arg;
+ if (chand->lb_policy != NULL) {
+ grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy);
+ } else {
+ chand->exit_idle_when_lb_policy_arrives = true;
+ if (!chand->started_resolving && chand->resolver != NULL) {
+ GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
+ chand->started_resolving = true;
+ grpc_resolver_next_locked(exec_ctx, chand->resolver,
+ &chand->resolver_result,
+ &chand->on_resolver_result_changed);
+ }
+ }
+ GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
+}
+
grpc_connectivity_state grpc_client_channel_check_connectivity_state(
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
channel_data *chand = elem->channel_data;
- grpc_connectivity_state out;
- gpr_mu_lock(&chand->mu);
- out = grpc_connectivity_state_check(&chand->state_tracker, NULL);
+ grpc_connectivity_state out =
+ grpc_connectivity_state_check(&chand->state_tracker);
if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
- if (chand->lb_policy != NULL) {
- grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
- } else {
- chand->exit_idle_when_lb_policy_arrives = true;
- if (!chand->started_resolving && chand->resolver != NULL) {
- GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
- chand->started_resolving = true;
- grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
- &chand->on_resolver_result_changed);
- }
- }
+ GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
+ grpc_closure_sched(
+ exec_ctx,
+ grpc_closure_create(try_to_connect_locked, chand,
+ grpc_combiner_scheduler(chand->combiner, false)),
+ GRPC_ERROR_NONE);
}
- gpr_mu_unlock(&chand->mu);
return out;
}
@@ -1219,6 +1261,7 @@ typedef struct {
channel_data *chand;
grpc_pollset *pollset;
grpc_closure *on_complete;
+ grpc_connectivity_state *state;
grpc_closure my_closure;
} external_connectivity_watcher;
@@ -1231,7 +1274,16 @@ static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
"external_connectivity_watcher");
gpr_free(w);
- follow_up->cb(exec_ctx, follow_up->cb_arg, error);
+ grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
+}
+
+static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error_ignored) {
+ external_connectivity_watcher *w = arg;
+ grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
+ grpc_schedule_on_exec_ctx);
+ grpc_connectivity_state_notify_on_state_change(
+ exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
}
void grpc_client_channel_watch_connectivity_state(
@@ -1242,13 +1294,13 @@ void grpc_client_channel_watch_connectivity_state(
w->chand = chand;
w->pollset = pollset;
w->on_complete = on_complete;
+ w->state = state;
grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
- grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
- grpc_schedule_on_exec_ctx);
GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
"external_connectivity_watcher");
- gpr_mu_lock(&chand->mu);
- grpc_connectivity_state_notify_on_state_change(
- exec_ctx, &chand->state_tracker, state, &w->my_closure);
- gpr_mu_unlock(&chand->mu);
+ grpc_closure_sched(
+ exec_ctx,
+ grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
+ grpc_combiner_scheduler(chand->combiner, true)),
+ GRPC_ERROR_NONE);
}
diff --git a/src/core/ext/client_channel/client_channel_plugin.c b/src/core/ext/client_channel/client_channel_plugin.c
index 7f75233727..28d3b63f99 100644
--- a/src/core/ext/client_channel/client_channel_plugin.c
+++ b/src/core/ext/client_channel/client_channel_plugin.c
@@ -39,6 +39,7 @@
#include "src/core/ext/client_channel/client_channel.h"
#include "src/core/ext/client_channel/http_connect_handshaker.h"
+#include "src/core/ext/client_channel/http_proxy.h"
#include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/proxy_mapper_registry.h"
#include "src/core/ext/client_channel/resolver_registry.h"
@@ -63,7 +64,7 @@ static bool set_default_host_if_unset(grpc_exec_ctx *exec_ctx,
}
}
char *default_authority = grpc_get_default_authority(
- grpc_channel_stack_builder_get_target(builder));
+ exec_ctx, grpc_channel_stack_builder_get_target(builder));
if (default_authority != NULL) {
grpc_arg arg;
arg.type = GRPC_ARG_STRING;
@@ -82,6 +83,7 @@ void grpc_client_channel_init(void) {
grpc_lb_policy_registry_init();
grpc_resolver_registry_init();
grpc_proxy_mapper_registry_init();
+ grpc_register_http_proxy_mapper();
grpc_subchannel_index_init();
grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MIN,
set_default_host_if_unset, NULL);
diff --git a/src/core/ext/client_channel/http_proxy.c b/src/core/ext/client_channel/http_proxy.c
index 9a6c818c4e..e280cef101 100644
--- a/src/core/ext/client_channel/http_proxy.c
+++ b/src/core/ext/client_channel/http_proxy.c
@@ -40,13 +40,17 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
+#include "src/core/ext/client_channel/http_connect_handshaker.h"
+#include "src/core/ext/client_channel/proxy_mapper_registry.h"
#include "src/core/ext/client_channel/uri_parser.h"
+#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/support/env.h"
-char* grpc_get_http_proxy_server() {
+static char* grpc_get_http_proxy_server(grpc_exec_ctx* exec_ctx) {
char* uri_str = gpr_getenv("http_proxy");
if (uri_str == NULL) return NULL;
- grpc_uri* uri = grpc_uri_parse(uri_str, false /* suppress_errors */);
+ grpc_uri* uri =
+ grpc_uri_parse(exec_ctx, uri_str, false /* suppress_errors */);
char* proxy_name = NULL;
if (uri == NULL || uri->authority == NULL) {
gpr_log(GPR_ERROR, "cannot parse value of 'http_proxy' env var");
@@ -66,3 +70,56 @@ done:
grpc_uri_destroy(uri);
return proxy_name;
}
+
+static bool proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
+ grpc_proxy_mapper* mapper,
+ const char* server_uri,
+ const grpc_channel_args* args,
+ char** name_to_resolve,
+ grpc_channel_args** new_args) {
+ *name_to_resolve = grpc_get_http_proxy_server(exec_ctx);
+ if (*name_to_resolve == NULL) return false;
+ grpc_uri* uri =
+ grpc_uri_parse(exec_ctx, server_uri, false /* suppress_errors */);
+ if (uri == NULL || uri->path[0] == '\0') {
+ gpr_log(GPR_ERROR,
+ "'http_proxy' environment variable set, but cannot "
+ "parse server URI '%s' -- not using proxy",
+ server_uri);
+ if (uri != NULL) grpc_uri_destroy(uri);
+ return false;
+ }
+ if (strcmp(uri->scheme, "unix") == 0) {
+ gpr_log(GPR_INFO, "not using proxy for Unix domain socket '%s'",
+ server_uri);
+ grpc_uri_destroy(uri);
+ return false;
+ }
+ grpc_arg new_arg;
+ new_arg.key = GRPC_ARG_HTTP_CONNECT_SERVER;
+ new_arg.type = GRPC_ARG_STRING;
+ new_arg.value.string = uri->path[0] == '/' ? uri->path + 1 : uri->path;
+ *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1);
+ grpc_uri_destroy(uri);
+ return true;
+}
+
+static bool proxy_mapper_map_address(grpc_exec_ctx* exec_ctx,
+ grpc_proxy_mapper* mapper,
+ const grpc_resolved_address* address,
+ const grpc_channel_args* args,
+ grpc_resolved_address** new_address,
+ grpc_channel_args** new_args) {
+ return false;
+}
+
+static void proxy_mapper_destroy(grpc_proxy_mapper* mapper) {}
+
+static const grpc_proxy_mapper_vtable proxy_mapper_vtable = {
+ proxy_mapper_map_name, proxy_mapper_map_address, proxy_mapper_destroy};
+
+static grpc_proxy_mapper proxy_mapper = {&proxy_mapper_vtable};
+
+void grpc_register_http_proxy_mapper() {
+ grpc_proxy_mapper_register(true /* at_start */, &proxy_mapper);
+}
diff --git a/src/core/ext/client_channel/http_proxy.h b/src/core/ext/client_channel/http_proxy.h
index 0d77ae253b..c8882b1ef1 100644
--- a/src/core/ext/client_channel/http_proxy.h
+++ b/src/core/ext/client_channel/http_proxy.h
@@ -34,8 +34,6 @@
#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H
#define GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H
-/// Returns the name of the proxy to use, or NULL if no proxy is configured.
-/// Caller takes ownership of result.
-char* grpc_get_http_proxy_server();
+void grpc_register_http_proxy_mapper();
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_HTTP_PROXY_H */
diff --git a/src/core/ext/client_channel/lb_policy.c b/src/core/ext/client_channel/lb_policy.c
index 45ee72e2f0..aba51add53 100644
--- a/src/core/ext/client_channel/lb_policy.c
+++ b/src/core/ext/client_channel/lb_policy.c
@@ -32,14 +32,17 @@
*/
#include "src/core/ext/client_channel/lb_policy.h"
+#include "src/core/lib/iomgr/combiner.h"
#define WEAK_REF_BITS 16
void grpc_lb_policy_init(grpc_lb_policy *policy,
- const grpc_lb_policy_vtable *vtable) {
+ const grpc_lb_policy_vtable *vtable,
+ grpc_combiner *combiner) {
policy->vtable = vtable;
gpr_atm_no_barrier_store(&policy->ref_pair, 1 << WEAK_REF_BITS);
policy->interested_parties = grpc_pollset_set_create();
+ policy->combiner = GRPC_COMBINER_REF(combiner, "lb_policy");
}
#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
@@ -71,6 +74,13 @@ void grpc_lb_policy_ref(grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
ref_mutate(policy, 1 << WEAK_REF_BITS, 0 REF_MUTATE_PASS_ARGS("STRONG_REF"));
}
+static void shutdown_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ grpc_lb_policy *policy = arg;
+ policy->vtable->shutdown_locked(exec_ctx, policy);
+ GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, policy, "strong-unref");
+}
+
void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
gpr_atm old_val =
@@ -79,10 +89,15 @@ void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx,
gpr_atm mask = ~(gpr_atm)((1 << WEAK_REF_BITS) - 1);
gpr_atm check = 1 << WEAK_REF_BITS;
if ((old_val & mask) == check) {
- policy->vtable->shutdown(exec_ctx, policy);
+ grpc_closure_sched(
+ exec_ctx,
+ grpc_closure_create(shutdown_locked, policy,
+ grpc_combiner_scheduler(policy->combiner, false)),
+ GRPC_ERROR_NONE);
+ } else {
+ grpc_lb_policy_weak_unref(exec_ctx,
+ policy REF_FUNC_PASS_ARGS("strong-unref"));
}
- grpc_lb_policy_weak_unref(exec_ctx,
- policy REF_FUNC_PASS_ARGS("strong-unref"));
}
void grpc_lb_policy_weak_ref(grpc_lb_policy *policy REF_FUNC_EXTRA_ARGS) {
@@ -94,53 +109,59 @@ void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx,
gpr_atm old_val =
ref_mutate(policy, -(gpr_atm)1, 1 REF_MUTATE_PASS_ARGS("WEAK_UNREF"));
if (old_val == 1) {
- grpc_pollset_set_destroy(policy->interested_parties);
+ grpc_pollset_set_destroy(exec_ctx, policy->interested_parties);
+ grpc_combiner *combiner = policy->combiner;
policy->vtable->destroy(exec_ctx, policy);
+ GRPC_COMBINER_UNREF(exec_ctx, combiner, "lb_policy");
}
}
-int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
- const grpc_lb_policy_pick_args *pick_args,
- grpc_connected_subchannel **target, void **user_data,
- grpc_closure *on_complete) {
- return policy->vtable->pick(exec_ctx, policy, pick_args, target, user_data,
- on_complete);
+int grpc_lb_policy_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+ const grpc_lb_policy_pick_args *pick_args,
+ grpc_connected_subchannel **target,
+ void **user_data, grpc_closure *on_complete) {
+ return policy->vtable->pick_locked(exec_ctx, policy, pick_args, target,
+ user_data, on_complete);
}
-void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
- grpc_connected_subchannel **target,
- grpc_error *error) {
- policy->vtable->cancel_pick(exec_ctx, policy, target, error);
+void grpc_lb_policy_cancel_pick_locked(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *policy,
+ grpc_connected_subchannel **target,
+ grpc_error *error) {
+ policy->vtable->cancel_pick_locked(exec_ctx, policy, target, error);
}
-void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx,
- grpc_lb_policy *policy,
- uint32_t initial_metadata_flags_mask,
- uint32_t initial_metadata_flags_eq,
- grpc_error *error) {
- policy->vtable->cancel_picks(exec_ctx, policy, initial_metadata_flags_mask,
- initial_metadata_flags_eq, error);
+void grpc_lb_policy_cancel_picks_locked(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *policy,
+ uint32_t initial_metadata_flags_mask,
+ uint32_t initial_metadata_flags_eq,
+ grpc_error *error) {
+ policy->vtable->cancel_picks_locked(exec_ctx, policy,
+ initial_metadata_flags_mask,
+ initial_metadata_flags_eq, error);
}
-void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
- policy->vtable->exit_idle(exec_ctx, policy);
+void grpc_lb_policy_exit_idle_locked(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *policy) {
+ policy->vtable->exit_idle_locked(exec_ctx, policy);
}
-void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
- grpc_closure *closure) {
- policy->vtable->ping_one(exec_ctx, policy, closure);
+void grpc_lb_policy_ping_one_locked(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *policy,
+ grpc_closure *closure) {
+ policy->vtable->ping_one_locked(exec_ctx, policy, closure);
}
-void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
- grpc_lb_policy *policy,
- grpc_connectivity_state *state,
- grpc_closure *closure) {
- policy->vtable->notify_on_state_change(exec_ctx, policy, state, closure);
+void grpc_lb_policy_notify_on_state_change_locked(
+ grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+ grpc_connectivity_state *state, grpc_closure *closure) {
+ policy->vtable->notify_on_state_change_locked(exec_ctx, policy, state,
+ closure);
}
-grpc_connectivity_state grpc_lb_policy_check_connectivity(
+grpc_connectivity_state grpc_lb_policy_check_connectivity_locked(
grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_error **connectivity_error) {
- return policy->vtable->check_connectivity(exec_ctx, policy,
- connectivity_error);
+ return policy->vtable->check_connectivity_locked(exec_ctx, policy,
+ connectivity_error);
}
diff --git a/src/core/ext/client_channel/lb_policy.h b/src/core/ext/client_channel/lb_policy.h
index 120c641edc..3405709c2c 100644
--- a/src/core/ext/client_channel/lb_policy.h
+++ b/src/core/ext/client_channel/lb_policy.h
@@ -51,6 +51,8 @@ struct grpc_lb_policy {
gpr_atm ref_pair;
/* owned pointer to interested parties in load balancing decisions */
grpc_pollset_set *interested_parties;
+ /* combiner under which lb_policy actions take place */
+ grpc_combiner *combiner;
};
/** Extra arguments for an LB pick */
@@ -69,42 +71,44 @@ typedef struct grpc_lb_policy_pick_args {
struct grpc_lb_policy_vtable {
void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
- void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+ void (*shutdown_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
/** \see grpc_lb_policy_pick */
- int (*pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
- const grpc_lb_policy_pick_args *pick_args,
- grpc_connected_subchannel **target, void **user_data,
- grpc_closure *on_complete);
+ int (*pick_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+ const grpc_lb_policy_pick_args *pick_args,
+ grpc_connected_subchannel **target, void **user_data,
+ grpc_closure *on_complete);
/** \see grpc_lb_policy_cancel_pick */
- void (*cancel_pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
- grpc_connected_subchannel **target, grpc_error *error);
+ void (*cancel_pick_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+ grpc_connected_subchannel **target,
+ grpc_error *error);
/** \see grpc_lb_policy_cancel_picks */
- void (*cancel_picks)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
- uint32_t initial_metadata_flags_mask,
- uint32_t initial_metadata_flags_eq, grpc_error *error);
+ void (*cancel_picks_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+ uint32_t initial_metadata_flags_mask,
+ uint32_t initial_metadata_flags_eq,
+ grpc_error *error);
/** \see grpc_lb_policy_ping_one */
- void (*ping_one)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
- grpc_closure *closure);
+ void (*ping_one_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+ grpc_closure *closure);
/** Try to enter a READY connectivity state */
- void (*exit_idle)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+ void (*exit_idle_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
/** check the current connectivity of the lb_policy */
- grpc_connectivity_state (*check_connectivity)(
+ grpc_connectivity_state (*check_connectivity_locked)(
grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_error **connectivity_error);
/** call notify when the connectivity state of a channel changes from *state.
Updates *state with the new state of the policy. Calling with a NULL \a
state cancels the subscription. */
- void (*notify_on_state_change)(grpc_exec_ctx *exec_ctx,
- grpc_lb_policy *policy,
- grpc_connectivity_state *state,
- grpc_closure *closure);
+ void (*notify_on_state_change_locked)(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *policy,
+ grpc_connectivity_state *state,
+ grpc_closure *closure);
};
/*#define GRPC_LB_POLICY_REFCOUNT_DEBUG*/
@@ -144,7 +148,8 @@ void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
/** called by concrete implementations to initialize the base struct */
void grpc_lb_policy_init(grpc_lb_policy *policy,
- const grpc_lb_policy_vtable *vtable);
+ const grpc_lb_policy_vtable *vtable,
+ grpc_combiner *combiner);
/** Finds an appropriate subchannel for a call, based on \a pick_args.
@@ -159,43 +164,45 @@ void grpc_lb_policy_init(grpc_lb_policy *policy,
Any IO should be done under the \a interested_parties \a grpc_pollset_set
in the \a grpc_lb_policy struct. */
-int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
- const grpc_lb_policy_pick_args *pick_args,
- grpc_connected_subchannel **target, void **user_data,
- grpc_closure *on_complete);
+int grpc_lb_policy_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+ const grpc_lb_policy_pick_args *pick_args,
+ grpc_connected_subchannel **target,
+ void **user_data, grpc_closure *on_complete);
/** Perform a connected subchannel ping (see \a grpc_connected_subchannel_ping)
against one of the connected subchannels managed by \a policy. */
-void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
- grpc_closure *closure);
+void grpc_lb_policy_ping_one_locked(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *policy,
+ grpc_closure *closure);
/** Cancel picks for \a target.
The \a on_complete callback of the pending picks will be invoked with \a
*target set to NULL. */
-void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
- grpc_connected_subchannel **target,
- grpc_error *error);
+void grpc_lb_policy_cancel_pick_locked(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *policy,
+ grpc_connected_subchannel **target,
+ grpc_error *error);
/** Cancel all pending picks for which their \a initial_metadata_flags (as given
in the call to \a grpc_lb_policy_pick) matches \a initial_metadata_flags_eq
when AND'd with \a initial_metadata_flags_mask */
-void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx,
- grpc_lb_policy *policy,
- uint32_t initial_metadata_flags_mask,
- uint32_t initial_metadata_flags_eq,
- grpc_error *error);
+void grpc_lb_policy_cancel_picks_locked(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *policy,
+ uint32_t initial_metadata_flags_mask,
+ uint32_t initial_metadata_flags_eq,
+ grpc_error *error);
/** Try to enter a READY connectivity state */
-void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
+void grpc_lb_policy_exit_idle_locked(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *policy);
/* Call notify when the connectivity state of a channel changes from \a *state.
* Updates \a *state with the new state of the policy */
-void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
- grpc_lb_policy *policy,
- grpc_connectivity_state *state,
- grpc_closure *closure);
+void grpc_lb_policy_notify_on_state_change_locked(
+ grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
+ grpc_connectivity_state *state, grpc_closure *closure);
-grpc_connectivity_state grpc_lb_policy_check_connectivity(
+grpc_connectivity_state grpc_lb_policy_check_connectivity_locked(
grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_error **connectivity_error);
diff --git a/src/core/ext/client_channel/lb_policy_factory.h b/src/core/ext/client_channel/lb_policy_factory.h
index 9b8b03f982..27c12c0d73 100644
--- a/src/core/ext/client_channel/lb_policy_factory.h
+++ b/src/core/ext/client_channel/lb_policy_factory.h
@@ -107,6 +107,7 @@ grpc_arg grpc_lb_addresses_create_channel_arg(
typedef struct grpc_lb_policy_args {
grpc_client_channel_factory *client_channel_factory;
grpc_channel_args *args;
+ grpc_combiner *combiner;
} grpc_lb_policy_args;
struct grpc_lb_policy_factory_vtable {
diff --git a/src/core/ext/client_channel/parse_address.c b/src/core/ext/client_channel/parse_address.c
index b1d55ad0f5..cd1b2cd80c 100644
--- a/src/core/ext/client_channel/parse_address.c
+++ b/src/core/ext/client_channel/parse_address.c
@@ -44,16 +44,18 @@
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
+#include "src/core/lib/support/string.h"
#ifdef GRPC_HAVE_UNIX_SOCKET
int parse_unix(grpc_uri *uri, grpc_resolved_address *resolved_addr) {
struct sockaddr_un *un = (struct sockaddr_un *)resolved_addr->addr;
-
+ const size_t maxlen = sizeof(un->sun_path);
+ const size_t path_len = strnlen(uri->path, maxlen);
+ if (path_len == maxlen) return 0;
un->sun_family = AF_UNIX;
strcpy(un->sun_path, uri->path);
- resolved_addr->len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
-
+ resolved_addr->len = sizeof(*un);
return 1;
}
@@ -119,9 +121,33 @@ int parse_ipv6(grpc_uri *uri, grpc_resolved_address *resolved_addr) {
memset(in6, 0, sizeof(*in6));
resolved_addr->len = sizeof(*in6);
in6->sin6_family = AF_INET6;
- if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
- gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host);
- goto done;
+
+ /* Handle the RFC6874 syntax for IPv6 zone identifiers. */
+ char *host_end = (char *)gpr_memrchr(host, '%', strlen(host));
+ if (host_end != NULL) {
+ GPR_ASSERT(host_end >= host);
+ char host_without_scope[INET6_ADDRSTRLEN];
+ size_t host_without_scope_len = (size_t)(host_end - host);
+ uint32_t sin6_scope_id = 0;
+ strncpy(host_without_scope, host, host_without_scope_len);
+ host_without_scope[host_without_scope_len] = '\0';
+ if (inet_pton(AF_INET6, host_without_scope, &in6->sin6_addr) == 0) {
+ gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host_without_scope);
+ goto done;
+ }
+ if (gpr_parse_bytes_to_uint32(host_end + 1,
+ strlen(host) - host_without_scope_len - 1,
+ &sin6_scope_id) == 0) {
+ gpr_log(GPR_ERROR, "invalid ipv6 scope id: '%s'", host_end + 1);
+ goto done;
+ }
+ // Handle "sin6_scope_id" being type "u_long". See grpc issue ##10027.
+ in6->sin6_scope_id = sin6_scope_id;
+ } else {
+ if (inet_pton(AF_INET6, host, &in6->sin6_addr) == 0) {
+ gpr_log(GPR_ERROR, "invalid ipv6 address: '%s'", host);
+ goto done;
+ }
}
if (port != NULL) {
diff --git a/src/core/ext/client_channel/proxy_mapper.c b/src/core/ext/client_channel/proxy_mapper.c
index 6b6f328d3c..f92afe847b 100644
--- a/src/core/ext/client_channel/proxy_mapper.c
+++ b/src/core/ext/client_channel/proxy_mapper.c
@@ -38,13 +38,24 @@ void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable,
mapper->vtable = vtable;
}
-bool grpc_proxy_mapper_map(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
- const grpc_resolved_address* address,
- const grpc_channel_args* args,
- grpc_resolved_address** new_address,
- grpc_channel_args** new_args) {
- return mapper->vtable->map(exec_ctx, mapper, address, args, new_address,
- new_args);
+bool grpc_proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
+ grpc_proxy_mapper* mapper,
+ const char* server_uri,
+ const grpc_channel_args* args,
+ char** name_to_resolve,
+ grpc_channel_args** new_args) {
+ return mapper->vtable->map_name(exec_ctx, mapper, server_uri, args,
+ name_to_resolve, new_args);
+}
+
+bool grpc_proxy_mapper_map_address(grpc_exec_ctx* exec_ctx,
+ grpc_proxy_mapper* mapper,
+ const grpc_resolved_address* address,
+ const grpc_channel_args* args,
+ grpc_resolved_address** new_address,
+ grpc_channel_args** new_args) {
+ return mapper->vtable->map_address(exec_ctx, mapper, address, args,
+ new_address, new_args);
}
void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper) {
diff --git a/src/core/ext/client_channel/proxy_mapper.h b/src/core/ext/client_channel/proxy_mapper.h
index fa930379e7..6e4607fe4d 100644
--- a/src/core/ext/client_channel/proxy_mapper.h
+++ b/src/core/ext/client_channel/proxy_mapper.h
@@ -43,15 +43,22 @@
typedef struct grpc_proxy_mapper grpc_proxy_mapper;
typedef struct {
+ /// Determines the proxy name to resolve for \a server_uri.
+ /// If no proxy is needed, returns false.
+ /// Otherwise, sets \a name_to_resolve, optionally sets \a new_args,
+ /// and returns true.
+ bool (*map_name)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
+ const char* server_uri, const grpc_channel_args* args,
+ char** name_to_resolve, grpc_channel_args** new_args);
/// Determines the proxy address to use to contact \a address.
/// If no proxy is needed, returns false.
/// Otherwise, sets \a new_address, optionally sets \a new_args, and
/// returns true.
- bool (*map)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
- const grpc_resolved_address* address,
- const grpc_channel_args* args,
- grpc_resolved_address** new_address,
- grpc_channel_args** new_args);
+ bool (*map_address)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
+ const grpc_resolved_address* address,
+ const grpc_channel_args* args,
+ grpc_resolved_address** new_address,
+ grpc_channel_args** new_args);
/// Destroys \a mapper.
void (*destroy)(grpc_proxy_mapper* mapper);
} grpc_proxy_mapper_vtable;
@@ -63,11 +70,20 @@ struct grpc_proxy_mapper {
void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable,
grpc_proxy_mapper* mapper);
-bool grpc_proxy_mapper_map(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
- const grpc_resolved_address* address,
- const grpc_channel_args* args,
- grpc_resolved_address** new_address,
- grpc_channel_args** new_args);
+bool grpc_proxy_mapper_map_name(grpc_exec_ctx* exec_ctx,
+ grpc_proxy_mapper* mapper,
+ const char* server_uri,
+ const grpc_channel_args* args,
+ char** name_to_resolve,
+ grpc_channel_args** new_args);
+
+bool grpc_proxy_mapper_map_address(grpc_exec_ctx* exec_ctx,
+ grpc_proxy_mapper* mapper,
+ const grpc_resolved_address* address,
+ const grpc_channel_args* args,
+ grpc_resolved_address** new_address,
+ grpc_channel_args** new_args);
+
void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_H */
diff --git a/src/core/ext/client_channel/proxy_mapper_registry.c b/src/core/ext/client_channel/proxy_mapper_registry.c
index 0a156c8b1c..2c44b9d490 100644
--- a/src/core/ext/client_channel/proxy_mapper_registry.c
+++ b/src/core/ext/client_channel/proxy_mapper_registry.c
@@ -61,15 +61,28 @@ static void grpc_proxy_mapper_list_register(grpc_proxy_mapper_list* list,
++list->num_mappers;
}
-static bool grpc_proxy_mapper_list_map(grpc_exec_ctx* exec_ctx,
- grpc_proxy_mapper_list* list,
- const grpc_resolved_address* address,
- const grpc_channel_args* args,
- grpc_resolved_address** new_address,
- grpc_channel_args** new_args) {
+static bool grpc_proxy_mapper_list_map_name(grpc_exec_ctx* exec_ctx,
+ grpc_proxy_mapper_list* list,
+ const char* server_uri,
+ const grpc_channel_args* args,
+ char** name_to_resolve,
+ grpc_channel_args** new_args) {
for (size_t i = 0; i < list->num_mappers; ++i) {
- if (grpc_proxy_mapper_map(exec_ctx, list->list[i], address, args,
- new_address, new_args)) {
+ if (grpc_proxy_mapper_map_name(exec_ctx, list->list[i], server_uri, args,
+ name_to_resolve, new_args)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool grpc_proxy_mapper_list_map_address(
+ grpc_exec_ctx* exec_ctx, grpc_proxy_mapper_list* list,
+ const grpc_resolved_address* address, const grpc_channel_args* args,
+ grpc_resolved_address** new_address, grpc_channel_args** new_args) {
+ for (size_t i = 0; i < list->num_mappers; ++i) {
+ if (grpc_proxy_mapper_map_address(exec_ctx, list->list[i], address, args,
+ new_address, new_args)) {
return true;
}
}
@@ -101,11 +114,20 @@ void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper) {
grpc_proxy_mapper_list_register(&g_proxy_mapper_list, at_start, mapper);
}
-bool grpc_proxy_mappers_map(grpc_exec_ctx* exec_ctx,
- const grpc_resolved_address* address,
- const grpc_channel_args* args,
- grpc_resolved_address** new_address,
- grpc_channel_args** new_args) {
- return grpc_proxy_mapper_list_map(exec_ctx, &g_proxy_mapper_list, address,
- args, new_address, new_args);
+bool grpc_proxy_mappers_map_name(grpc_exec_ctx* exec_ctx,
+ const char* server_uri,
+ const grpc_channel_args* args,
+ char** name_to_resolve,
+ grpc_channel_args** new_args) {
+ return grpc_proxy_mapper_list_map_name(exec_ctx, &g_proxy_mapper_list,
+ server_uri, args, name_to_resolve,
+ new_args);
+}
+bool grpc_proxy_mappers_map_address(grpc_exec_ctx* exec_ctx,
+ const grpc_resolved_address* address,
+ const grpc_channel_args* args,
+ grpc_resolved_address** new_address,
+ grpc_channel_args** new_args) {
+ return grpc_proxy_mapper_list_map_address(
+ exec_ctx, &g_proxy_mapper_list, address, args, new_address, new_args);
}
diff --git a/src/core/ext/client_channel/proxy_mapper_registry.h b/src/core/ext/client_channel/proxy_mapper_registry.h
index b76af8d456..742b57a2d4 100644
--- a/src/core/ext/client_channel/proxy_mapper_registry.h
+++ b/src/core/ext/client_channel/proxy_mapper_registry.h
@@ -44,10 +44,16 @@ void grpc_proxy_mapper_registry_shutdown();
/// the list. Otherwise, it will be added to the end.
void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper);
-bool grpc_proxy_mappers_map(grpc_exec_ctx* exec_ctx,
- const grpc_resolved_address* address,
- const grpc_channel_args* args,
- grpc_resolved_address** new_address,
- grpc_channel_args** new_args);
+bool grpc_proxy_mappers_map_name(grpc_exec_ctx* exec_ctx,
+ const char* server_uri,
+ const grpc_channel_args* args,
+ char** name_to_resolve,
+ grpc_channel_args** new_args);
+
+bool grpc_proxy_mappers_map_address(grpc_exec_ctx* exec_ctx,
+ const grpc_resolved_address* address,
+ const grpc_channel_args* args,
+ grpc_resolved_address** new_address,
+ grpc_channel_args** new_args);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H */
diff --git a/src/core/ext/client_channel/resolver.c b/src/core/ext/client_channel/resolver.c
index 2ae4fe862e..b1a1faa6c9 100644
--- a/src/core/ext/client_channel/resolver.c
+++ b/src/core/ext/client_channel/resolver.c
@@ -32,10 +32,13 @@
*/
#include "src/core/ext/client_channel/resolver.h"
+#include "src/core/lib/iomgr/combiner.h"
void grpc_resolver_init(grpc_resolver *resolver,
- const grpc_resolver_vtable *vtable) {
+ const grpc_resolver_vtable *vtable,
+ grpc_combiner *combiner) {
resolver->vtable = vtable;
+ resolver->combiner = GRPC_COMBINER_REF(combiner, "resolver");
gpr_ref_init(&resolver->refs, 1);
}
@@ -62,20 +65,24 @@ void grpc_resolver_unref(grpc_resolver *resolver,
void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
#endif
if (gpr_unref(&resolver->refs)) {
+ grpc_combiner *combiner = resolver->combiner;
resolver->vtable->destroy(exec_ctx, resolver);
+ GRPC_COMBINER_UNREF(exec_ctx, combiner, "resolver");
}
}
-void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
- resolver->vtable->shutdown(exec_ctx, resolver);
+void grpc_resolver_shutdown_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver) {
+ resolver->vtable->shutdown_locked(exec_ctx, resolver);
}
-void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
- grpc_resolver *resolver) {
- resolver->vtable->channel_saw_error(exec_ctx, resolver);
+void grpc_resolver_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver) {
+ resolver->vtable->channel_saw_error_locked(exec_ctx, resolver);
}
-void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
- grpc_channel_args **result, grpc_closure *on_complete) {
- resolver->vtable->next(exec_ctx, resolver, result, on_complete);
+void grpc_resolver_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+ grpc_channel_args **result,
+ grpc_closure *on_complete) {
+ resolver->vtable->next_locked(exec_ctx, resolver, result, on_complete);
}
diff --git a/src/core/ext/client_channel/resolver.h b/src/core/ext/client_channel/resolver.h
index 96ece92b9d..bbba424ca5 100644
--- a/src/core/ext/client_channel/resolver.h
+++ b/src/core/ext/client_channel/resolver.h
@@ -44,14 +44,16 @@ typedef struct grpc_resolver_vtable grpc_resolver_vtable;
struct grpc_resolver {
const grpc_resolver_vtable *vtable;
gpr_refcount refs;
+ grpc_combiner *combiner;
};
struct grpc_resolver_vtable {
void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
- void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
- void (*channel_saw_error)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
- void (*next)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
- grpc_channel_args **result, grpc_closure *on_complete);
+ void (*shutdown_locked)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
+ void (*channel_saw_error_locked)(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver);
+ void (*next_locked)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+ grpc_channel_args **result, grpc_closure *on_complete);
};
#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
@@ -70,21 +72,30 @@ void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *policy);
#endif
void grpc_resolver_init(grpc_resolver *resolver,
- const grpc_resolver_vtable *vtable);
+ const grpc_resolver_vtable *vtable,
+ grpc_combiner *combiner);
-void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
+void grpc_resolver_shutdown_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver);
/** Notification that the channel has seen an error on some address.
- Can be used as a hint that re-resolution is desirable soon. */
-void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
- grpc_resolver *resolver);
+ Can be used as a hint that re-resolution is desirable soon.
+
+ Must be called from the combiner passed as a resolver_arg at construction
+ time.*/
+void grpc_resolver_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver);
/** Get the next result from the resolver. Expected to set \a *result with
new channel args and then schedule \a on_complete for execution.
If resolution is fatally broken, set \a *result to NULL and
- schedule \a on_complete. */
-void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
- grpc_channel_args **result, grpc_closure *on_complete);
+ schedule \a on_complete.
+
+ Must be called from the combiner passed as a resolver_arg at construction
+ time.*/
+void grpc_resolver_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+ grpc_channel_args **result,
+ grpc_closure *on_complete);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H */
diff --git a/src/core/ext/client_channel/resolver_factory.h b/src/core/ext/client_channel/resolver_factory.h
index 3792ddca18..e3cd99ec5a 100644
--- a/src/core/ext/client_channel/resolver_factory.h
+++ b/src/core/ext/client_channel/resolver_factory.h
@@ -50,6 +50,7 @@ typedef struct grpc_resolver_args {
grpc_uri *uri;
const grpc_channel_args *args;
grpc_pollset_set *pollset_set;
+ grpc_combiner *combiner;
} grpc_resolver_args;
struct grpc_resolver_factory_vtable {
diff --git a/src/core/ext/client_channel/resolver_registry.c b/src/core/ext/client_channel/resolver_registry.c
index 5110a7cad9..3c5a6fb3ff 100644
--- a/src/core/ext/client_channel/resolver_registry.c
+++ b/src/core/ext/client_channel/resolver_registry.c
@@ -108,22 +108,23 @@ static grpc_resolver_factory *lookup_factory_by_uri(grpc_uri *uri) {
return lookup_factory(uri->scheme);
}
-static grpc_resolver_factory *resolve_factory(const char *target,
+static grpc_resolver_factory *resolve_factory(grpc_exec_ctx *exec_ctx,
+ const char *target,
grpc_uri **uri,
char **canonical_target) {
grpc_resolver_factory *factory = NULL;
GPR_ASSERT(uri != NULL);
- *uri = grpc_uri_parse(target, 1);
+ *uri = grpc_uri_parse(exec_ctx, target, 1);
factory = lookup_factory_by_uri(*uri);
if (factory == NULL) {
grpc_uri_destroy(*uri);
gpr_asprintf(canonical_target, "%s%s", g_default_resolver_prefix, target);
- *uri = grpc_uri_parse(*canonical_target, 1);
+ *uri = grpc_uri_parse(exec_ctx, *canonical_target, 1);
factory = lookup_factory_by_uri(*uri);
if (factory == NULL) {
- grpc_uri_destroy(grpc_uri_parse(target, 0));
- grpc_uri_destroy(grpc_uri_parse(*canonical_target, 0));
+ grpc_uri_destroy(grpc_uri_parse(exec_ctx, target, 0));
+ grpc_uri_destroy(grpc_uri_parse(exec_ctx, *canonical_target, 0));
gpr_log(GPR_ERROR, "don't know how to resolve '%s' or '%s'", target,
*canonical_target);
}
@@ -133,17 +134,19 @@ static grpc_resolver_factory *resolve_factory(const char *target,
grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target,
const grpc_channel_args *args,
- grpc_pollset_set *pollset_set) {
+ grpc_pollset_set *pollset_set,
+ grpc_combiner *combiner) {
grpc_uri *uri = NULL;
char *canonical_target = NULL;
grpc_resolver_factory *factory =
- resolve_factory(target, &uri, &canonical_target);
+ resolve_factory(exec_ctx, target, &uri, &canonical_target);
grpc_resolver *resolver;
grpc_resolver_args resolver_args;
memset(&resolver_args, 0, sizeof(resolver_args));
resolver_args.uri = uri;
resolver_args.args = args;
resolver_args.pollset_set = pollset_set;
+ resolver_args.combiner = combiner;
resolver =
grpc_resolver_factory_create_resolver(exec_ctx, factory, &resolver_args);
grpc_uri_destroy(uri);
@@ -151,21 +154,22 @@ grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target,
return resolver;
}
-char *grpc_get_default_authority(const char *target) {
+char *grpc_get_default_authority(grpc_exec_ctx *exec_ctx, const char *target) {
grpc_uri *uri = NULL;
char *canonical_target = NULL;
grpc_resolver_factory *factory =
- resolve_factory(target, &uri, &canonical_target);
+ resolve_factory(exec_ctx, target, &uri, &canonical_target);
char *authority = grpc_resolver_factory_get_default_authority(factory, uri);
grpc_uri_destroy(uri);
gpr_free(canonical_target);
return authority;
}
-char *grpc_resolver_factory_add_default_prefix_if_needed(const char *target) {
+char *grpc_resolver_factory_add_default_prefix_if_needed(
+ grpc_exec_ctx *exec_ctx, const char *target) {
grpc_uri *uri = NULL;
char *canonical_target = NULL;
- resolve_factory(target, &uri, &canonical_target);
+ resolve_factory(exec_ctx, target, &uri, &canonical_target);
grpc_uri_destroy(uri);
return canonical_target == NULL ? gpr_strdup(target) : canonical_target;
}
diff --git a/src/core/ext/client_channel/resolver_registry.h b/src/core/ext/client_channel/resolver_registry.h
index a4606463eb..1a3ebee25a 100644
--- a/src/core/ext/client_channel/resolver_registry.h
+++ b/src/core/ext/client_channel/resolver_registry.h
@@ -65,7 +65,8 @@ void grpc_register_resolver_type(grpc_resolver_factory *factory);
should not be NULL. */
grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target,
const grpc_channel_args *args,
- grpc_pollset_set *pollset_set);
+ grpc_pollset_set *pollset_set,
+ grpc_combiner *combiner);
/** Find a resolver factory given a name and return an (owned-by-the-caller)
* reference to it */
@@ -73,10 +74,11 @@ grpc_resolver_factory *grpc_resolver_factory_lookup(const char *name);
/** Given a target, return a (freshly allocated with gpr_malloc) string
representing the default authority to pass from a client. */
-char *grpc_get_default_authority(const char *target);
+char *grpc_get_default_authority(grpc_exec_ctx *exec_ctx, const char *target);
/** Returns a newly allocated string containing \a target, adding the
default prefix if needed. */
-char *grpc_resolver_factory_add_default_prefix_if_needed(const char *target);
+char *grpc_resolver_factory_add_default_prefix_if_needed(
+ grpc_exec_ctx *exec_ctx, const char *target);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_REGISTRY_H */
diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c
index abbbfdfd64..5df0a9060d 100644
--- a/src/core/ext/client_channel/subchannel.c
+++ b/src/core/ext/client_channel/subchannel.c
@@ -217,7 +217,7 @@ static void subchannel_destroy(grpc_exec_ctx *exec_ctx, void *arg,
grpc_slice_unref_internal(exec_ctx, c->initial_connect_string);
grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker);
grpc_connector_unref(exec_ctx, c->connector);
- grpc_pollset_set_destroy(c->pollset_set);
+ grpc_pollset_set_destroy(exec_ctx, c->pollset_set);
grpc_subchannel_key_destroy(exec_ctx, c->key);
gpr_free(c);
}
@@ -316,8 +316,7 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
return c;
}
- c = gpr_malloc(sizeof(*c));
- memset(c, 0, sizeof(*c));
+ c = gpr_zalloc(sizeof(*c));
c->key = key;
gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS);
c->connector = connector;
@@ -332,12 +331,12 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
}
c->pollset_set = grpc_pollset_set_create();
grpc_resolved_address *addr = gpr_malloc(sizeof(*addr));
- grpc_get_subchannel_address_arg(args->args, addr);
+ grpc_get_subchannel_address_arg(exec_ctx, args->args, addr);
grpc_set_initial_connect_string(&addr, &c->initial_connect_string);
grpc_resolved_address *new_address = NULL;
grpc_channel_args *new_args = NULL;
- if (grpc_proxy_mappers_map(exec_ctx, addr, args->args, &new_address,
- &new_args)) {
+ if (grpc_proxy_mappers_map_address(exec_ctx, addr, args->args, &new_address,
+ &new_args)) {
GPR_ASSERT(new_address != NULL);
gpr_free(addr);
addr = new_address;
@@ -419,7 +418,7 @@ grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c,
grpc_error **error) {
grpc_connectivity_state state;
gpr_mu_lock(&c->mu);
- state = grpc_connectivity_state_check(&c->state_tracker, error);
+ state = grpc_connectivity_state_get(&c->state_tracker, error);
gpr_mu_unlock(&c->mu);
return state;
}
@@ -438,7 +437,7 @@ static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg,
gpr_mu_unlock(&w->subchannel->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, w->subchannel, "external_state_watcher");
gpr_free(w);
- follow_up->cb(exec_ctx, follow_up->cb_arg, error);
+ grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
}
static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
@@ -765,7 +764,7 @@ grpc_error *grpc_connected_subchannel_create_call(
grpc_polling_entity *pollent, grpc_slice path, gpr_timespec start_time,
gpr_timespec deadline, grpc_subchannel_call **call) {
grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
- *call = gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
+ *call = gpr_zalloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(*call);
(*call)->connection = con; // Ref is added below.
grpc_error *error =
@@ -788,9 +787,9 @@ grpc_call_stack *grpc_subchannel_call_get_call_stack(
return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call);
}
-static void grpc_uri_to_sockaddr(const char *uri_str,
+static void grpc_uri_to_sockaddr(grpc_exec_ctx *exec_ctx, const char *uri_str,
grpc_resolved_address *addr) {
- grpc_uri *uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */);
+ grpc_uri *uri = grpc_uri_parse(exec_ctx, uri_str, 0 /* suppress_errors */);
GPR_ASSERT(uri != NULL);
if (strcmp(uri->scheme, "ipv4") == 0) {
GPR_ASSERT(parse_ipv4(uri, addr));
@@ -802,12 +801,13 @@ static void grpc_uri_to_sockaddr(const char *uri_str,
grpc_uri_destroy(uri);
}
-void grpc_get_subchannel_address_arg(const grpc_channel_args *args,
+void grpc_get_subchannel_address_arg(grpc_exec_ctx *exec_ctx,
+ 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);
+ grpc_uri_to_sockaddr(exec_ctx, addr_uri_str, addr);
}
}
diff --git a/src/core/ext/client_channel/subchannel.h b/src/core/ext/client_channel/subchannel.h
index 26ce954487..6a70a76467 100644
--- a/src/core/ext/client_channel/subchannel.h
+++ b/src/core/ext/client_channel/subchannel.h
@@ -175,7 +175,8 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
const grpc_subchannel_args *args);
/// Sets \a addr from \a args.
-void grpc_get_subchannel_address_arg(const grpc_channel_args *args,
+void grpc_get_subchannel_address_arg(grpc_exec_ctx *exec_ctx,
+ const grpc_channel_args *args,
grpc_resolved_address *addr);
/// Returns the URI string for the address to connect to.
diff --git a/src/core/ext/client_channel/uri_parser.c b/src/core/ext/client_channel/uri_parser.c
index f8c946b275..d385db0801 100644
--- a/src/core/ext/client_channel/uri_parser.c
+++ b/src/core/ext/client_channel/uri_parser.c
@@ -35,13 +35,15 @@
#include <string.h>
-#include <grpc/slice.h>
#include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/string_util.h>
+#include "src/core/lib/slice/percent_encoding.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
#include "src/core/lib/support/string.h"
/** a size_t default value... maps to all 1's */
@@ -68,11 +70,16 @@ static grpc_uri *bad_uri(const char *uri_text, size_t pos, const char *section,
return NULL;
}
-/** Returns a copy of \a src[begin, end) */
-static char *copy_component(const char *src, size_t begin, size_t end) {
- char *out = gpr_malloc(end - begin + 1);
- memcpy(out, src + begin, end - begin);
- out[end - begin] = 0;
+/** Returns a copy of percent decoded \a src[begin, end) */
+static char *decode_and_copy_component(grpc_exec_ctx *exec_ctx, const char *src,
+ size_t begin, size_t end) {
+ grpc_slice component =
+ grpc_slice_from_copied_buffer(src + begin, end - begin);
+ grpc_slice decoded_component =
+ grpc_permissive_percent_decode_slice(component);
+ char *out = grpc_dump_slice(decoded_component, GPR_DUMP_ASCII);
+ grpc_slice_unref_internal(exec_ctx, component);
+ grpc_slice_unref_internal(exec_ctx, decoded_component);
return out;
}
@@ -175,7 +182,8 @@ static void parse_query_parts(grpc_uri *uri) {
}
}
-grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors) {
+grpc_uri *grpc_uri_parse(grpc_exec_ctx *exec_ctx, const char *uri_text,
+ int suppress_errors) {
grpc_uri *uri;
size_t scheme_begin = 0;
size_t scheme_end = NOT_SET;
@@ -262,13 +270,17 @@ grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors) {
fragment_end = i;
}
- uri = gpr_malloc(sizeof(*uri));
- memset(uri, 0, sizeof(*uri));
- uri->scheme = copy_component(uri_text, scheme_begin, scheme_end);
- uri->authority = copy_component(uri_text, authority_begin, authority_end);
- uri->path = copy_component(uri_text, path_begin, path_end);
- uri->query = copy_component(uri_text, query_begin, query_end);
- uri->fragment = copy_component(uri_text, fragment_begin, fragment_end);
+ uri = gpr_zalloc(sizeof(*uri));
+ uri->scheme =
+ decode_and_copy_component(exec_ctx, uri_text, scheme_begin, scheme_end);
+ uri->authority = decode_and_copy_component(exec_ctx, uri_text,
+ authority_begin, authority_end);
+ uri->path =
+ decode_and_copy_component(exec_ctx, uri_text, path_begin, path_end);
+ uri->query =
+ decode_and_copy_component(exec_ctx, uri_text, query_begin, query_end);
+ uri->fragment = decode_and_copy_component(exec_ctx, uri_text, fragment_begin,
+ fragment_end);
parse_query_parts(uri);
return uri;
diff --git a/src/core/ext/client_channel/uri_parser.h b/src/core/ext/client_channel/uri_parser.h
index 5fe0e8f35e..efd4302c1c 100644
--- a/src/core/ext/client_channel/uri_parser.h
+++ b/src/core/ext/client_channel/uri_parser.h
@@ -35,6 +35,7 @@
#define GRPC_CORE_EXT_CLIENT_CHANNEL_URI_PARSER_H
#include <stddef.h>
+#include "src/core/lib/iomgr/exec_ctx.h"
typedef struct {
char *scheme;
@@ -51,7 +52,8 @@ typedef struct {
} grpc_uri;
/** parse a uri, return NULL on failure */
-grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors);
+grpc_uri *grpc_uri_parse(grpc_exec_ctx *exec_ctx, const char *uri_text,
+ int suppress_errors);
/** return the part of a query string after the '=' in "?key=xxx&...", or NULL
* if key is not present */
diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c
index ab62e5ed6a..d612591f2e 100644
--- a/src/core/ext/lb_policy/grpclb/grpclb.c
+++ b/src/core/ext/lb_policy/grpclb/grpclb.c
@@ -115,6 +115,7 @@
#include "src/core/ext/lb_policy/grpclb/grpclb_channel.h"
#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/timer.h"
@@ -237,9 +238,7 @@ static void add_pending_pick(pending_pick **root,
const grpc_lb_policy_pick_args *pick_args,
grpc_connected_subchannel **target,
grpc_closure *on_complete) {
- pending_pick *pp = gpr_malloc(sizeof(*pp));
- memset(pp, 0, sizeof(pending_pick));
- memset(&pp->wrapped_on_complete_arg, 0, sizeof(wrapped_rr_closure_arg));
+ pending_pick *pp = gpr_zalloc(sizeof(*pp));
pp->next = *root;
pp->pick_args = *pick_args;
pp->target = target;
@@ -264,9 +263,7 @@ typedef struct pending_ping {
} pending_ping;
static void add_pending_ping(pending_ping **root, grpc_closure *notify) {
- pending_ping *pping = gpr_malloc(sizeof(*pping));
- memset(pping, 0, sizeof(pending_ping));
- memset(&pping->wrapped_notify_arg, 0, sizeof(wrapped_rr_closure_arg));
+ pending_ping *pping = gpr_zalloc(sizeof(*pping));
pping->wrapped_notify_arg.wrapped_closure = notify;
pping->wrapped_notify_arg.free_when_done = pping;
pping->next = *root;
@@ -285,9 +282,6 @@ typedef struct glb_lb_policy {
/** base policy: must be first */
grpc_lb_policy base;
- /** mutex protecting remaining members */
- gpr_mu mu;
-
/** who the client is trying to communicate with */
const char *server_name;
grpc_client_channel_factory *cc_factory;
@@ -492,9 +486,8 @@ static grpc_lb_addresses *process_serverlist_locked(
static bool update_lb_connectivity_status_locked(
grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
grpc_connectivity_state new_rr_state, grpc_error *new_rr_state_error) {
- grpc_error *curr_state_error;
- const grpc_connectivity_state curr_glb_state = grpc_connectivity_state_check(
- &glb_policy->state_tracker, &curr_state_error);
+ const grpc_connectivity_state curr_glb_state =
+ grpc_connectivity_state_check(&glb_policy->state_tracker);
/* The new connectivity status is a function of the previous one and the new
* input coming from the status of the RR policy.
@@ -558,9 +551,9 @@ static bool pick_from_internal_rr_locked(
const grpc_lb_policy_pick_args *pick_args,
grpc_connected_subchannel **target, wrapped_rr_closure_arg *wc_arg) {
GPR_ASSERT(rr_policy != NULL);
- const bool pick_done =
- grpc_lb_policy_pick(exec_ctx, rr_policy, pick_args, target,
- (void **)&wc_arg->lb_token, &wc_arg->wrapper_closure);
+ const bool pick_done = grpc_lb_policy_pick_locked(
+ exec_ctx, rr_policy, pick_args, target, (void **)&wc_arg->lb_token,
+ &wc_arg->wrapper_closure);
if (pick_done) {
/* synchronous grpc_lb_policy_pick call. Unref the RR policy. */
if (grpc_lb_glb_trace) {
@@ -591,6 +584,7 @@ static grpc_lb_policy *create_rr_locked(
grpc_lb_policy_args args;
memset(&args, 0, sizeof(args));
args.client_channel_factory = glb_policy->cc_factory;
+ args.combiner = glb_policy->base.combiner;
grpc_lb_addresses *addresses =
process_serverlist_locked(exec_ctx, serverlist);
@@ -609,8 +603,8 @@ static grpc_lb_policy *create_rr_locked(
return rr;
}
-static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error);
+static void glb_rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx,
+ void *arg, grpc_error *error);
/* glb_policy->rr_policy may be NULL (initial handover) */
static void rr_handover_locked(grpc_exec_ctx *exec_ctx,
glb_lb_policy *glb_policy) {
@@ -634,8 +628,8 @@ static void rr_handover_locked(grpc_exec_ctx *exec_ctx,
grpc_error *new_rr_state_error = NULL;
const grpc_connectivity_state new_rr_state =
- grpc_lb_policy_check_connectivity(exec_ctx, new_rr_policy,
- &new_rr_state_error);
+ grpc_lb_policy_check_connectivity_locked(exec_ctx, new_rr_policy,
+ &new_rr_state_error);
/* Connectivity state is a function of the new RR policy just created */
const bool replace_old_rr = update_lb_connectivity_status_locked(
exec_ctx, glb_policy, new_rr_state, new_rr_state_error);
@@ -676,19 +670,19 @@ static void rr_handover_locked(grpc_exec_ctx *exec_ctx,
/* Allocate the data for the tracking of the new RR policy's connectivity.
* It'll be deallocated in glb_rr_connectivity_changed() */
rr_connectivity_data *rr_connectivity =
- gpr_malloc(sizeof(rr_connectivity_data));
- memset(rr_connectivity, 0, sizeof(rr_connectivity_data));
- grpc_closure_init(&rr_connectivity->on_change, glb_rr_connectivity_changed,
- rr_connectivity, grpc_schedule_on_exec_ctx);
+ gpr_zalloc(sizeof(rr_connectivity_data));
+ grpc_closure_init(&rr_connectivity->on_change,
+ glb_rr_connectivity_changed_locked, rr_connectivity,
+ grpc_combiner_scheduler(glb_policy->base.combiner, false));
rr_connectivity->glb_policy = glb_policy;
rr_connectivity->state = new_rr_state;
/* Subscribe to changes to the connectivity of the new RR */
GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "rr_connectivity_cb");
- grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
- &rr_connectivity->state,
- &rr_connectivity->on_change);
- grpc_lb_policy_exit_idle(exec_ctx, glb_policy->rr_policy);
+ grpc_lb_policy_notify_on_state_change_locked(exec_ctx, glb_policy->rr_policy,
+ &rr_connectivity->state,
+ &rr_connectivity->on_change);
+ grpc_lb_policy_exit_idle_locked(exec_ctx, glb_policy->rr_policy);
/* Update picks and pings in wait */
pending_pick *pp;
@@ -714,17 +708,16 @@ static void rr_handover_locked(grpc_exec_ctx *exec_ctx,
gpr_log(GPR_INFO, "Pending ping about to PING from 0x%" PRIxPTR "",
(intptr_t)glb_policy->rr_policy);
}
- grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy,
- &pping->wrapped_notify_arg.wrapper_closure);
+ grpc_lb_policy_ping_one_locked(exec_ctx, glb_policy->rr_policy,
+ &pping->wrapped_notify_arg.wrapper_closure);
}
}
-static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static void glb_rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx,
+ void *arg, grpc_error *error) {
rr_connectivity_data *rr_connectivity = arg;
glb_lb_policy *glb_policy = rr_connectivity->glb_policy;
- gpr_mu_lock(&glb_policy->mu);
const bool shutting_down = glb_policy->shutting_down;
bool unref_needed = false;
GRPC_ERROR_REF(error);
@@ -741,11 +734,10 @@ static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
update_lb_connectivity_status_locked(exec_ctx, glb_policy,
rr_connectivity->state, error);
/* Resubscribe. Reuse the "rr_connectivity_cb" weak ref. */
- grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
- &rr_connectivity->state,
- &rr_connectivity->on_change);
+ grpc_lb_policy_notify_on_state_change_locked(
+ exec_ctx, glb_policy->rr_policy, &rr_connectivity->state,
+ &rr_connectivity->on_change);
}
- gpr_mu_unlock(&glb_policy->mu);
if (unref_needed) {
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
"rr_connectivity_cb");
@@ -863,14 +855,13 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
}
if (num_grpclb_addrs == 0) return NULL;
- glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy));
- memset(glb_policy, 0, sizeof(*glb_policy));
+ glb_lb_policy *glb_policy = gpr_zalloc(sizeof(*glb_policy));
/* Get server name. */
arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI);
GPR_ASSERT(arg != NULL);
GPR_ASSERT(arg->type == GRPC_ARG_STRING);
- grpc_uri *uri = grpc_uri_parse(arg->value.string, true);
+ grpc_uri *uri = grpc_uri_parse(exec_ctx, arg->value.string, true);
GPR_ASSERT(uri->path[0] != '\0');
glb_policy->server_name =
gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path);
@@ -900,8 +891,7 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
gpr_free(glb_policy);
return NULL;
}
- grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable);
- gpr_mu_init(&glb_policy->mu);
+ grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable, args->combiner);
grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE,
"grpclb");
return &glb_policy->base;
@@ -919,13 +909,11 @@ static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
if (glb_policy->serverlist != NULL) {
grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
}
- gpr_mu_destroy(&glb_policy->mu);
gpr_free(glb_policy);
}
-static void glb_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+static void glb_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
- gpr_mu_lock(&glb_policy->mu);
glb_policy->shutting_down = true;
pending_pick *pp = glb_policy->pending_picks;
@@ -942,7 +930,6 @@ static void glb_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
* while holding glb_policy->mu: lb_on_server_status_received, invoked due to
* the cancel, needs to acquire that same lock */
grpc_call *lb_call = glb_policy->lb_call;
- gpr_mu_unlock(&glb_policy->mu);
/* glb_policy->lb_call and this local lb_call must be consistent at this point
* because glb_policy->lb_call is only assigned in lb_call_init_locked as part
@@ -968,11 +955,10 @@ static void glb_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
}
}
-static void glb_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
- grpc_connected_subchannel **target,
- grpc_error *error) {
+static void glb_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ grpc_connected_subchannel **target,
+ grpc_error *error) {
glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
- gpr_mu_lock(&glb_policy->mu);
pending_pick *pp = glb_policy->pending_picks;
glb_policy->pending_picks = NULL;
while (pp != NULL) {
@@ -988,16 +974,15 @@ static void glb_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
pp = next;
}
- gpr_mu_unlock(&glb_policy->mu);
GRPC_ERROR_UNREF(error);
}
-static void glb_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
- uint32_t initial_metadata_flags_mask,
- uint32_t initial_metadata_flags_eq,
- grpc_error *error) {
+static void glb_cancel_picks_locked(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *pol,
+ uint32_t initial_metadata_flags_mask,
+ uint32_t initial_metadata_flags_eq,
+ grpc_error *error) {
glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
- gpr_mu_lock(&glb_policy->mu);
pending_pick *pp = glb_policy->pending_picks;
glb_policy->pending_picks = NULL;
while (pp != NULL) {
@@ -1013,7 +998,6 @@ static void glb_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
pp = next;
}
- gpr_mu_unlock(&glb_policy->mu);
GRPC_ERROR_UNREF(error);
}
@@ -1026,19 +1010,17 @@ static void start_picking_locked(grpc_exec_ctx *exec_ctx,
query_for_backends_locked(exec_ctx, glb_policy);
}
-static void glb_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+static void glb_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
- gpr_mu_lock(&glb_policy->mu);
if (!glb_policy->started_picking) {
start_picking_locked(exec_ctx, glb_policy);
}
- gpr_mu_unlock(&glb_policy->mu);
}
-static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
- const grpc_lb_policy_pick_args *pick_args,
- grpc_connected_subchannel **target, void **user_data,
- grpc_closure *on_complete) {
+static int glb_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ const grpc_lb_policy_pick_args *pick_args,
+ grpc_connected_subchannel **target, void **user_data,
+ grpc_closure *on_complete) {
if (pick_args->lb_token_mdelem_storage == NULL) {
*target = NULL;
grpc_closure_sched(
@@ -1049,7 +1031,6 @@ static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
- gpr_mu_lock(&glb_policy->mu);
glb_policy->deadline = pick_args->deadline;
bool pick_done;
@@ -1060,8 +1041,7 @@ static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
GRPC_LB_POLICY_REF(glb_policy->rr_policy, "glb_pick");
- wrapped_rr_closure_arg *wc_arg = gpr_malloc(sizeof(wrapped_rr_closure_arg));
- memset(wc_arg, 0, sizeof(wrapped_rr_closure_arg));
+ wrapped_rr_closure_arg *wc_arg = gpr_zalloc(sizeof(wrapped_rr_closure_arg));
grpc_closure_init(&wc_arg->wrapper_closure, wrapped_rr_closure, wc_arg,
grpc_schedule_on_exec_ctx);
@@ -1088,53 +1068,43 @@ static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
pick_done = false;
}
- gpr_mu_unlock(&glb_policy->mu);
return pick_done;
}
-static grpc_connectivity_state glb_check_connectivity(
+static grpc_connectivity_state glb_check_connectivity_locked(
grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_error **connectivity_error) {
glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
- grpc_connectivity_state st;
- gpr_mu_lock(&glb_policy->mu);
- st = grpc_connectivity_state_check(&glb_policy->state_tracker,
+ return grpc_connectivity_state_get(&glb_policy->state_tracker,
connectivity_error);
- gpr_mu_unlock(&glb_policy->mu);
- return st;
}
-static void glb_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
- grpc_closure *closure) {
+static void glb_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ grpc_closure *closure) {
glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
- gpr_mu_lock(&glb_policy->mu);
if (glb_policy->rr_policy) {
- grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy, closure);
+ grpc_lb_policy_ping_one_locked(exec_ctx, glb_policy->rr_policy, closure);
} else {
add_pending_ping(&glb_policy->pending_pings, closure);
if (!glb_policy->started_picking) {
start_picking_locked(exec_ctx, glb_policy);
}
}
- gpr_mu_unlock(&glb_policy->mu);
}
-static void glb_notify_on_state_change(grpc_exec_ctx *exec_ctx,
- grpc_lb_policy *pol,
- grpc_connectivity_state *current,
- grpc_closure *notify) {
+static void glb_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *pol,
+ grpc_connectivity_state *current,
+ grpc_closure *notify) {
glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
- gpr_mu_lock(&glb_policy->mu);
grpc_connectivity_state_notify_on_state_change(
exec_ctx, &glb_policy->state_tracker, current, notify);
-
- gpr_mu_unlock(&glb_policy->mu);
}
-static void lb_on_server_status_received(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error);
-static void lb_on_response_received(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error);
+static void lb_on_server_status_received_locked(grpc_exec_ctx *exec_ctx,
+ void *arg, grpc_error *error);
+static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error);
static void lb_call_init_locked(grpc_exec_ctx *exec_ctx,
glb_lb_policy *glb_policy) {
GPR_ASSERT(glb_policy->server_name != NULL);
@@ -1163,11 +1133,11 @@ static void lb_call_init_locked(grpc_exec_ctx *exec_ctx,
grpc_grpclb_request_destroy(request);
grpc_closure_init(&glb_policy->lb_on_server_status_received,
- lb_on_server_status_received, glb_policy,
- grpc_schedule_on_exec_ctx);
+ lb_on_server_status_received_locked, glb_policy,
+ grpc_combiner_scheduler(glb_policy->base.combiner, false));
grpc_closure_init(&glb_policy->lb_on_response_received,
- lb_on_response_received, glb_policy,
- grpc_schedule_on_exec_ctx);
+ lb_on_response_received_locked, glb_policy,
+ grpc_combiner_scheduler(glb_policy->base.combiner, false));
gpr_backoff_init(&glb_policy->lb_call_backoff_state,
GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS,
@@ -1262,14 +1232,13 @@ static void query_for_backends_locked(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(GRPC_CALL_OK == call_error);
}
-static void lb_on_response_received(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
glb_lb_policy *glb_policy = arg;
grpc_op ops[2];
memset(ops, 0, sizeof(ops));
grpc_op *op = ops;
- gpr_mu_lock(&glb_policy->mu);
if (glb_policy->lb_response_payload != NULL) {
gpr_backoff_reset(&glb_policy->lb_call_backoff_state);
/* Received data from the LB server. Look inside
@@ -1343,20 +1312,17 @@ static void lb_on_response_received(grpc_exec_ctx *exec_ctx, void *arg,
&glb_policy->lb_on_response_received); /* loop */
GPR_ASSERT(GRPC_CALL_OK == call_error);
}
- gpr_mu_unlock(&glb_policy->mu);
} else { /* empty payload: call cancelled. */
/* dispose of the "lb_on_response_received" weak ref taken in
* query_for_backends_locked() and reused in every reception loop */
- gpr_mu_unlock(&glb_policy->mu);
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
"lb_on_response_received_empty_payload");
}
}
-static void lb_call_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static void lb_call_on_retry_timer_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
glb_lb_policy *glb_policy = arg;
- gpr_mu_lock(&glb_policy->mu);
if (!glb_policy->shutting_down) {
if (grpc_lb_glb_trace) {
@@ -1366,15 +1332,13 @@ static void lb_call_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
GPR_ASSERT(glb_policy->lb_call == NULL);
query_for_backends_locked(exec_ctx, glb_policy);
}
- gpr_mu_unlock(&glb_policy->mu);
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
"grpclb_on_retry_timer");
}
-static void lb_on_server_status_received(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static void lb_on_server_status_received_locked(grpc_exec_ctx *exec_ctx,
+ void *arg, grpc_error *error) {
glb_lb_policy *glb_policy = arg;
- gpr_mu_lock(&glb_policy->mu);
GPR_ASSERT(glb_policy->lb_call != NULL);
@@ -1409,21 +1373,27 @@ static void lb_on_server_status_received(grpc_exec_ctx *exec_ctx, void *arg,
}
}
GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "grpclb_retry_timer");
- grpc_closure_init(&glb_policy->lb_on_call_retry, lb_call_on_retry_timer,
- glb_policy, grpc_schedule_on_exec_ctx);
+ grpc_closure_init(
+ &glb_policy->lb_on_call_retry, lb_call_on_retry_timer_locked,
+ glb_policy, grpc_combiner_scheduler(glb_policy->base.combiner, false));
grpc_timer_init(exec_ctx, &glb_policy->lb_call_retry_timer, next_try,
&glb_policy->lb_on_call_retry, now);
}
- gpr_mu_unlock(&glb_policy->mu);
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
"lb_on_server_status_received");
}
/* Code wiring the policy with the rest of the core */
static const grpc_lb_policy_vtable glb_lb_policy_vtable = {
- glb_destroy, glb_shutdown, glb_pick,
- glb_cancel_pick, glb_cancel_picks, glb_ping_one,
- glb_exit_idle, glb_check_connectivity, glb_notify_on_state_change};
+ glb_destroy,
+ glb_shutdown_locked,
+ glb_pick_locked,
+ glb_cancel_pick_locked,
+ glb_cancel_picks_locked,
+ glb_ping_one_locked,
+ glb_exit_idle_locked,
+ glb_check_connectivity_locked,
+ glb_notify_on_state_change_locked};
static void glb_factory_ref(grpc_lb_policy_factory *factory) {}
diff --git a/src/core/ext/lb_policy/grpclb/load_balancer_api.c b/src/core/ext/lb_policy/grpclb/load_balancer_api.c
index 837e9c1113..3c4604c402 100644
--- a/src/core/ext/lb_policy/grpclb/load_balancer_api.c
+++ b/src/core/ext/lb_policy/grpclb/load_balancer_api.c
@@ -62,8 +62,7 @@ static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field,
}
dec_arg->num_servers++;
} else { /* second pass. Actually decode. */
- grpc_grpclb_server *server = gpr_malloc(sizeof(grpc_grpclb_server));
- memset(server, 0, sizeof(grpc_grpclb_server));
+ grpc_grpclb_server *server = gpr_zalloc(sizeof(grpc_grpclb_server));
GPR_ASSERT(dec_arg->num_servers > 0);
if (dec_arg->decoding_idx == 0) { /* first iteration of second pass */
dec_arg->servers =
@@ -160,8 +159,7 @@ grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
return NULL;
}
- grpc_grpclb_serverlist *sl = gpr_malloc(sizeof(grpc_grpclb_serverlist));
- memset(sl, 0, sizeof(*sl));
+ grpc_grpclb_serverlist *sl = gpr_zalloc(sizeof(grpc_grpclb_serverlist));
sl->num_servers = arg.num_servers;
sl->servers = arg.servers;
if (res.server_list.has_expiration_interval) {
@@ -183,8 +181,7 @@ void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist) {
grpc_grpclb_serverlist *grpc_grpclb_serverlist_copy(
const grpc_grpclb_serverlist *sl) {
- grpc_grpclb_serverlist *copy = gpr_malloc(sizeof(grpc_grpclb_serverlist));
- memset(copy, 0, sizeof(grpc_grpclb_serverlist));
+ grpc_grpclb_serverlist *copy = gpr_zalloc(sizeof(grpc_grpclb_serverlist));
copy->num_servers = sl->num_servers;
memcpy(&copy->expiration_interval, &sl->expiration_interval,
sizeof(grpc_grpclb_duration));
diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c
index 9f2aa461be..e2a66d16bd 100644
--- a/src/core/ext/lb_policy/pick_first/pick_first.c
+++ b/src/core/ext/lb_policy/pick_first/pick_first.c
@@ -38,6 +38,7 @@
#include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/subchannel.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/transport/connectivity_state.h"
@@ -57,11 +58,11 @@ typedef struct {
grpc_closure connectivity_changed;
- /** the selected channel (a grpc_connected_subchannel) */
- gpr_atm selected;
+ /** remaining members are protected by the combiner */
+
+ /** the selected channel */
+ grpc_connected_subchannel *selected;
- /** mutex protecting remaining members */
- gpr_mu mu;
/** have we started picking? */
int started_picking;
/** are we shut down? */
@@ -77,32 +78,24 @@ typedef struct {
grpc_connectivity_state_tracker state_tracker;
} pick_first_lb_policy;
-#define GET_SELECTED(p) \
- ((grpc_connected_subchannel *)gpr_atm_acq_load(&(p)->selected))
-
static void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
- grpc_connected_subchannel *selected = GET_SELECTED(p);
size_t i;
GPR_ASSERT(p->pending_picks == NULL);
for (i = 0; i < p->num_subchannels; i++) {
GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], "pick_first");
}
- if (selected != NULL) {
- GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, selected, "picked_first");
+ if (p->selected != NULL) {
+ GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, p->selected, "picked_first");
}
grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
gpr_free(p->subchannels);
- gpr_mu_destroy(&p->mu);
gpr_free(p);
}
-static void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+static void pf_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
pending_pick *pp;
- grpc_connected_subchannel *selected;
- gpr_mu_lock(&p->mu);
- selected = GET_SELECTED(p);
p->shutdown = 1;
pp = p->pending_picks;
p->pending_picks = NULL;
@@ -110,15 +103,14 @@ static void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_CREATE("Channel shutdown"), "shutdown");
/* cancel subscription */
- if (selected != NULL) {
+ if (p->selected != NULL) {
grpc_connected_subchannel_notify_on_state_change(
- exec_ctx, selected, NULL, NULL, &p->connectivity_changed);
+ exec_ctx, p->selected, NULL, NULL, &p->connectivity_changed);
} else if (p->num_subchannels > 0) {
grpc_subchannel_notify_on_state_change(
exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL,
&p->connectivity_changed);
}
- gpr_mu_unlock(&p->mu);
while (pp != NULL) {
pending_pick *next = pp->next;
*pp->target = NULL;
@@ -128,12 +120,11 @@ static void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
}
}
-static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
- grpc_connected_subchannel **target,
- grpc_error *error) {
+static void pf_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ grpc_connected_subchannel **target,
+ grpc_error *error) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
pending_pick *pp;
- gpr_mu_lock(&p->mu);
pp = p->pending_picks;
p->pending_picks = NULL;
while (pp != NULL) {
@@ -150,17 +141,15 @@ static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
pp = next;
}
- gpr_mu_unlock(&p->mu);
GRPC_ERROR_UNREF(error);
}
-static void pf_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
- uint32_t initial_metadata_flags_mask,
- uint32_t initial_metadata_flags_eq,
- grpc_error *error) {
+static void pf_cancel_picks_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ uint32_t initial_metadata_flags_mask,
+ uint32_t initial_metadata_flags_eq,
+ grpc_error *error) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
pending_pick *pp;
- gpr_mu_lock(&p->mu);
pp = p->pending_picks;
p->pending_picks = NULL;
while (pp != NULL) {
@@ -177,7 +166,6 @@ static void pf_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
pp = next;
}
- gpr_mu_unlock(&p->mu);
GRPC_ERROR_UNREF(error);
}
@@ -192,63 +180,48 @@ static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) {
&p->connectivity_changed);
}
-static void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+static void pf_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
- gpr_mu_lock(&p->mu);
if (!p->started_picking) {
start_picking(exec_ctx, p);
}
- gpr_mu_unlock(&p->mu);
}
-static int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
- const grpc_lb_policy_pick_args *pick_args,
- grpc_connected_subchannel **target, void **user_data,
- grpc_closure *on_complete) {
+static int pf_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ const grpc_lb_policy_pick_args *pick_args,
+ grpc_connected_subchannel **target, void **user_data,
+ grpc_closure *on_complete) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
pending_pick *pp;
/* Check atomically for a selected channel */
- grpc_connected_subchannel *selected = GET_SELECTED(p);
- if (selected != NULL) {
- *target = GRPC_CONNECTED_SUBCHANNEL_REF(selected, "picked");
+ if (p->selected != NULL) {
+ *target = GRPC_CONNECTED_SUBCHANNEL_REF(p->selected, "picked");
return 1;
}
- /* No subchannel selected yet, so acquire lock and then attempt again */
- gpr_mu_lock(&p->mu);
- selected = GET_SELECTED(p);
- if (selected) {
- gpr_mu_unlock(&p->mu);
- *target = GRPC_CONNECTED_SUBCHANNEL_REF(selected, "picked");
- return 1;
- } else {
- if (!p->started_picking) {
- start_picking(exec_ctx, p);
- }
- pp = gpr_malloc(sizeof(*pp));
- pp->next = p->pending_picks;
- pp->target = target;
- pp->initial_metadata_flags = pick_args->initial_metadata_flags;
- pp->on_complete = on_complete;
- p->pending_picks = pp;
- gpr_mu_unlock(&p->mu);
- return 0;
+ /* No subchannel selected yet, so try again */
+ if (!p->started_picking) {
+ start_picking(exec_ctx, p);
}
+ pp = gpr_malloc(sizeof(*pp));
+ pp->next = p->pending_picks;
+ pp->target = target;
+ pp->initial_metadata_flags = pick_args->initial_metadata_flags;
+ pp->on_complete = on_complete;
+ p->pending_picks = pp;
+ return 0;
}
-static void destroy_subchannels(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
- pick_first_lb_policy *p = arg;
+static void destroy_subchannels_locked(grpc_exec_ctx *exec_ctx,
+ pick_first_lb_policy *p) {
size_t i;
size_t num_subchannels = p->num_subchannels;
grpc_subchannel **subchannels;
- gpr_mu_lock(&p->mu);
subchannels = p->subchannels;
p->num_subchannels = 0;
p->subchannels = NULL;
- gpr_mu_unlock(&p->mu);
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "destroy_subchannels");
for (i = 0; i < num_subchannels; i++) {
@@ -258,25 +231,19 @@ static void destroy_subchannels(grpc_exec_ctx *exec_ctx, void *arg,
gpr_free(subchannels);
}
-static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
pick_first_lb_policy *p = arg;
grpc_subchannel *selected_subchannel;
pending_pick *pp;
- grpc_connected_subchannel *selected;
GRPC_ERROR_REF(error);
- gpr_mu_lock(&p->mu);
-
- selected = GET_SELECTED(p);
-
if (p->shutdown) {
- gpr_mu_unlock(&p->mu);
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
GRPC_ERROR_UNREF(error);
return;
- } else if (selected != NULL) {
+ } else if (p->selected != NULL) {
if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
/* if the selected channel goes bad, we're done */
p->checking_connectivity = GRPC_CHANNEL_SHUTDOWN;
@@ -286,7 +253,7 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
"selected_changed");
if (p->checking_connectivity != GRPC_CHANNEL_SHUTDOWN) {
grpc_connected_subchannel_notify_on_state_change(
- exec_ctx, selected, p->base.interested_parties,
+ exec_ctx, p->selected, p->base.interested_parties,
&p->checking_connectivity, &p->connectivity_changed);
} else {
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
@@ -301,26 +268,21 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_CHANNEL_READY, GRPC_ERROR_NONE,
"connecting_ready");
selected_subchannel = p->subchannels[p->checking_subchannel];
- selected =
- grpc_subchannel_get_connected_subchannel(selected_subchannel);
- GPR_ASSERT(selected != NULL);
- GRPC_CONNECTED_SUBCHANNEL_REF(selected, "picked_first");
+ p->selected = GRPC_CONNECTED_SUBCHANNEL_REF(
+ grpc_subchannel_get_connected_subchannel(selected_subchannel),
+ "picked_first");
/* drop the pick list: we are connected now */
GRPC_LB_POLICY_WEAK_REF(&p->base, "destroy_subchannels");
- gpr_atm_rel_store(&p->selected, (gpr_atm)selected);
- grpc_closure_sched(exec_ctx,
- grpc_closure_create(destroy_subchannels, p,
- grpc_schedule_on_exec_ctx),
- GRPC_ERROR_NONE);
+ destroy_subchannels_locked(exec_ctx, p);
/* update any calls that were waiting for a pick */
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
- *pp->target = GRPC_CONNECTED_SUBCHANNEL_REF(selected, "picked");
+ *pp->target = GRPC_CONNECTED_SUBCHANNEL_REF(p->selected, "picked");
grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE);
gpr_free(pp);
}
grpc_connected_subchannel_notify_on_state_change(
- exec_ctx, selected, p->base.interested_parties,
+ exec_ctx, p->selected, p->base.interested_parties,
&p->checking_connectivity, &p->connectivity_changed);
break;
case GRPC_CHANNEL_TRANSIENT_FAILURE:
@@ -387,48 +349,44 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
}
}
- gpr_mu_unlock(&p->mu);
-
GRPC_ERROR_UNREF(error);
}
-static grpc_connectivity_state pf_check_connectivity(grpc_exec_ctx *exec_ctx,
- grpc_lb_policy *pol,
- grpc_error **error) {
+static grpc_connectivity_state pf_check_connectivity_locked(
+ grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_error **error) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
- grpc_connectivity_state st;
- gpr_mu_lock(&p->mu);
- st = grpc_connectivity_state_check(&p->state_tracker, error);
- gpr_mu_unlock(&p->mu);
- return st;
+ return grpc_connectivity_state_get(&p->state_tracker, error);
}
-static void pf_notify_on_state_change(grpc_exec_ctx *exec_ctx,
- grpc_lb_policy *pol,
- grpc_connectivity_state *current,
- grpc_closure *notify) {
+static void pf_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *pol,
+ grpc_connectivity_state *current,
+ grpc_closure *notify) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
- gpr_mu_lock(&p->mu);
grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
current, notify);
- gpr_mu_unlock(&p->mu);
}
-static void pf_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
- grpc_closure *closure) {
+static void pf_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ grpc_closure *closure) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
- grpc_connected_subchannel *selected = GET_SELECTED(p);
- if (selected) {
- grpc_connected_subchannel_ping(exec_ctx, selected, closure);
+ if (p->selected) {
+ grpc_connected_subchannel_ping(exec_ctx, p->selected, closure);
} else {
grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_CREATE("Not connected"));
}
}
static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = {
- pf_destroy, pf_shutdown, pf_pick,
- pf_cancel_pick, pf_cancel_picks, pf_ping_one,
- pf_exit_idle, pf_check_connectivity, pf_notify_on_state_change};
+ pf_destroy,
+ pf_shutdown_locked,
+ pf_pick_locked,
+ pf_cancel_pick_locked,
+ pf_cancel_picks_locked,
+ pf_ping_one_locked,
+ pf_exit_idle_locked,
+ pf_check_connectivity_locked,
+ pf_notify_on_state_change_locked};
static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {}
@@ -451,11 +409,9 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
}
if (num_addrs == 0) return NULL;
- pick_first_lb_policy *p = gpr_malloc(sizeof(*p));
- memset(p, 0, sizeof(*p));
+ pick_first_lb_policy *p = gpr_zalloc(sizeof(*p));
- p->subchannels = gpr_malloc(sizeof(grpc_subchannel *) * num_addrs);
- memset(p->subchannels, 0, sizeof(*p->subchannels) * num_addrs);
+ p->subchannels = gpr_zalloc(sizeof(grpc_subchannel *) * num_addrs);
grpc_subchannel_args sc_args;
size_t subchannel_idx = 0;
for (size_t i = 0; i < addresses->num_addresses; i++) {
@@ -489,10 +445,9 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
}
p->num_subchannels = subchannel_idx;
- grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable);
- grpc_closure_init(&p->connectivity_changed, pf_connectivity_changed, p,
- grpc_schedule_on_exec_ctx);
- gpr_mu_init(&p->mu);
+ grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable, args->combiner);
+ grpc_closure_init(&p->connectivity_changed, pf_connectivity_changed_locked, p,
+ grpc_combiner_scheduler(args->combiner, false));
return &p->base;
}
diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c
index 3e060d189a..f2d1d46179 100644
--- a/src/core/ext/lb_policy/round_robin/round_robin.c
+++ b/src/core/ext/lb_policy/round_robin/round_robin.c
@@ -67,6 +67,7 @@
#include "src/core/ext/client_channel/subchannel.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/static_metadata.h"
@@ -134,7 +135,6 @@ typedef struct {
struct round_robin_lb_policy {
/** base policy: must be first */
grpc_lb_policy base;
- gpr_mu mu;
/** total number of addresses received at creation time */
size_t num_addresses;
@@ -213,8 +213,7 @@ static void advance_last_picked_locked(round_robin_lb_policy *p) {
* csc to the list of ready subchannels. */
static ready_list *add_connected_sc_locked(round_robin_lb_policy *p,
subchannel_data *sd) {
- ready_list *new_elem = gpr_malloc(sizeof(ready_list));
- memset(new_elem, 0, sizeof(ready_list));
+ ready_list *new_elem = gpr_zalloc(sizeof(ready_list));
new_elem->subchannel = sd->subchannel;
new_elem->user_data = sd->user_data;
if (p->ready_list.prev == NULL) {
@@ -293,7 +292,6 @@ static void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
gpr_free(p->subchannels);
- gpr_mu_destroy(&p->mu);
elem = p->ready_list.next;
while (elem != NULL && elem != &p->ready_list) {
@@ -309,12 +307,11 @@ static void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
gpr_free(p);
}
-static void rr_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+static void rr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
pending_pick *pp;
size_t i;
- gpr_mu_lock(&p->mu);
if (grpc_lb_round_robin_trace) {
gpr_log(GPR_DEBUG, "Shutting down Round Robin policy at %p", (void *)pol);
}
@@ -335,15 +332,13 @@ static void rr_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
grpc_subchannel_notify_on_state_change(exec_ctx, sd->subchannel, NULL, NULL,
&sd->connectivity_changed_closure);
}
- gpr_mu_unlock(&p->mu);
}
-static void rr_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
- grpc_connected_subchannel **target,
- grpc_error *error) {
+static void rr_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ grpc_connected_subchannel **target,
+ grpc_error *error) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
pending_pick *pp;
- gpr_mu_lock(&p->mu);
pp = p->pending_picks;
p->pending_picks = NULL;
while (pp != NULL) {
@@ -360,17 +355,15 @@ static void rr_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
pp = next;
}
- gpr_mu_unlock(&p->mu);
GRPC_ERROR_UNREF(error);
}
-static void rr_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
- uint32_t initial_metadata_flags_mask,
- uint32_t initial_metadata_flags_eq,
- grpc_error *error) {
+static void rr_cancel_picks_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ uint32_t initial_metadata_flags_mask,
+ uint32_t initial_metadata_flags_eq,
+ grpc_error *error) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
pending_pick *pp;
- gpr_mu_lock(&p->mu);
pp = p->pending_picks;
p->pending_picks = NULL;
while (pp != NULL) {
@@ -388,11 +381,11 @@ static void rr_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
pp = next;
}
- gpr_mu_unlock(&p->mu);
GRPC_ERROR_UNREF(error);
}
-static void start_picking(grpc_exec_ctx *exec_ctx, round_robin_lb_policy *p) {
+static void start_picking_locked(grpc_exec_ctx *exec_ctx,
+ round_robin_lb_policy *p) {
size_t i;
p->started_picking = 1;
@@ -411,23 +404,20 @@ static void start_picking(grpc_exec_ctx *exec_ctx, round_robin_lb_policy *p) {
}
}
-static void rr_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
+static void rr_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
- gpr_mu_lock(&p->mu);
if (!p->started_picking) {
- start_picking(exec_ctx, p);
+ start_picking_locked(exec_ctx, p);
}
- gpr_mu_unlock(&p->mu);
}
-static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
- const grpc_lb_policy_pick_args *pick_args,
- grpc_connected_subchannel **target, void **user_data,
- grpc_closure *on_complete) {
+static int rr_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ const grpc_lb_policy_pick_args *pick_args,
+ grpc_connected_subchannel **target, void **user_data,
+ grpc_closure *on_complete) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
pending_pick *pp;
ready_list *selected;
- gpr_mu_lock(&p->mu);
if (grpc_lb_round_robin_trace) {
gpr_log(GPR_INFO, "Round Robin %p trying to pick", (void *)pol);
@@ -449,12 +439,11 @@ static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
/* only advance the last picked pointer if the selection was used */
advance_last_picked_locked(p);
- gpr_mu_unlock(&p->mu);
return 1;
} else {
/* no pick currently available. Save for later in list of pending picks */
if (!p->started_picking) {
- start_picking(exec_ctx, p);
+ start_picking_locked(exec_ctx, p);
}
pp = gpr_malloc(sizeof(*pp));
pp->next = p->pending_picks;
@@ -463,7 +452,6 @@ static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
pp->initial_metadata_flags = pick_args->initial_metadata_flags;
pp->user_data = user_data;
p->pending_picks = pp;
- gpr_mu_unlock(&p->mu);
return 0;
}
}
@@ -538,17 +526,15 @@ static grpc_connectivity_state update_lb_connectivity_status(
return sd->curr_connectivity_state;
}
-static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static void rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
subchannel_data *sd = arg;
round_robin_lb_policy *p = sd->policy;
pending_pick *pp;
GRPC_ERROR_REF(error);
- gpr_mu_lock(&p->mu);
if (p->shutdown) {
- gpr_mu_unlock(&p->mu);
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "rr_connectivity");
GRPC_ERROR_UNREF(error);
return;
@@ -645,56 +631,51 @@ static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "rr_connectivity");
break;
}
- gpr_mu_unlock(&p->mu);
GRPC_ERROR_UNREF(error);
}
-static grpc_connectivity_state rr_check_connectivity(grpc_exec_ctx *exec_ctx,
- grpc_lb_policy *pol,
- grpc_error **error) {
+static grpc_connectivity_state rr_check_connectivity_locked(
+ grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_error **error) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
- grpc_connectivity_state st;
- gpr_mu_lock(&p->mu);
- st = grpc_connectivity_state_check(&p->state_tracker, error);
- gpr_mu_unlock(&p->mu);
- return st;
+ return grpc_connectivity_state_get(&p->state_tracker, error);
}
-static void rr_notify_on_state_change(grpc_exec_ctx *exec_ctx,
- grpc_lb_policy *pol,
- grpc_connectivity_state *current,
- grpc_closure *notify) {
+static void rr_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx,
+ grpc_lb_policy *pol,
+ grpc_connectivity_state *current,
+ grpc_closure *notify) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
- gpr_mu_lock(&p->mu);
grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
current, notify);
- gpr_mu_unlock(&p->mu);
}
-static void rr_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
- grpc_closure *closure) {
+static void rr_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
+ grpc_closure *closure) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
ready_list *selected;
grpc_connected_subchannel *target;
- gpr_mu_lock(&p->mu);
if ((selected = peek_next_connected_locked(p))) {
- gpr_mu_unlock(&p->mu);
target = GRPC_CONNECTED_SUBCHANNEL_REF(
grpc_subchannel_get_connected_subchannel(selected->subchannel),
"rr_picked");
grpc_connected_subchannel_ping(exec_ctx, target, closure);
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, target, "rr_picked");
} else {
- gpr_mu_unlock(&p->mu);
grpc_closure_sched(exec_ctx, closure,
GRPC_ERROR_CREATE("Round Robin not connected"));
}
}
static const grpc_lb_policy_vtable round_robin_lb_policy_vtable = {
- rr_destroy, rr_shutdown, rr_pick,
- rr_cancel_pick, rr_cancel_picks, rr_ping_one,
- rr_exit_idle, rr_check_connectivity, rr_notify_on_state_change};
+ rr_destroy,
+ rr_shutdown_locked,
+ rr_pick_locked,
+ rr_cancel_pick_locked,
+ rr_cancel_picks_locked,
+ rr_ping_one_locked,
+ rr_exit_idle_locked,
+ rr_check_connectivity_locked,
+ rr_notify_on_state_change_locked};
static void round_robin_factory_ref(grpc_lb_policy_factory *factory) {}
@@ -717,12 +698,10 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
}
if (num_addrs == 0) return NULL;
- round_robin_lb_policy *p = gpr_malloc(sizeof(*p));
- memset(p, 0, sizeof(*p));
+ round_robin_lb_policy *p = gpr_zalloc(sizeof(*p));
p->num_addresses = num_addrs;
- p->subchannels = gpr_malloc(sizeof(*p->subchannels) * num_addrs);
- memset(p->subchannels, 0, sizeof(*p->subchannels) * num_addrs);
+ p->subchannels = gpr_zalloc(sizeof(*p->subchannels) * num_addrs);
grpc_subchannel_args sc_args;
size_t subchannel_idx = 0;
@@ -749,8 +728,7 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
grpc_channel_args_destroy(exec_ctx, new_args);
if (subchannel != NULL) {
- subchannel_data *sd = gpr_malloc(sizeof(*sd));
- memset(sd, 0, sizeof(*sd));
+ subchannel_data *sd = gpr_zalloc(sizeof(*sd));
p->subchannels[subchannel_idx] = sd;
sd->policy = p;
sd->index = subchannel_idx;
@@ -762,7 +740,8 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
}
++subchannel_idx;
grpc_closure_init(&sd->connectivity_changed_closure,
- rr_connectivity_changed, sd, grpc_schedule_on_exec_ctx);
+ rr_connectivity_changed_locked, sd,
+ grpc_combiner_scheduler(args->combiner, false));
}
}
if (subchannel_idx == 0) {
@@ -779,7 +758,7 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
p->ready_list.next = NULL;
p->ready_list_last_pick = &p->ready_list;
- grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable);
+ grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable, args->combiner);
grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
"round_robin");
@@ -787,7 +766,6 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
gpr_log(GPR_DEBUG, "Created RR policy at %p with %lu subchannels",
(void *)p, (unsigned long)p->num_subchannels);
}
- gpr_mu_init(&p->mu);
return &p->base;
}
diff --git a/src/core/ext/load_reporting/load_reporting.c b/src/core/ext/load_reporting/load_reporting.c
index 37b06a737f..942aea4fd1 100644
--- a/src/core/ext/load_reporting/load_reporting.c
+++ b/src/core/ext/load_reporting/load_reporting.c
@@ -34,14 +34,34 @@
#include <limits.h>
#include <string.h>
+#include <grpc/load_reporting.h>
#include <grpc/support/alloc.h>
#include <grpc/support/sync.h>
#include "src/core/ext/load_reporting/load_reporting.h"
#include "src/core/ext/load_reporting/load_reporting_filter.h"
#include "src/core/lib/channel/channel_stack_builder.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/channel_init.h"
+static void destroy_lr_cost_context(void *c) {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_load_reporting_cost_context *cost_ctx = c;
+ for (size_t i = 0; i < cost_ctx->values_count; ++i) {
+ grpc_slice_unref_internal(&exec_ctx, cost_ctx->values[i]);
+ }
+ grpc_exec_ctx_finish(&exec_ctx);
+ gpr_free(cost_ctx->values);
+ gpr_free(cost_ctx);
+}
+
+void grpc_call_set_load_reporting_cost_context(
+ grpc_call *call, grpc_load_reporting_cost_context *ctx) {
+ grpc_call_context_set(call, GRPC_CONTEXT_LR_COST, ctx,
+ destroy_lr_cost_context);
+}
+
static bool is_load_reporting_enabled(const grpc_channel_args *a) {
if (a == NULL) return false;
for (size_t i = 0; i < a->num_args; i++) {
diff --git a/src/core/ext/load_reporting/load_reporting.h b/src/core/ext/load_reporting/load_reporting.h
index a157844734..22859a599a 100644
--- a/src/core/ext/load_reporting/load_reporting.h
+++ b/src/core/ext/load_reporting/load_reporting.h
@@ -35,23 +35,8 @@
#define GRPC_CORE_EXT_LOAD_REPORTING_LOAD_REPORTING_H
#include <grpc/impl/codegen/grpc_types.h>
-#include "src/core/lib/channel/channel_stack.h"
-
-/** Metadata key for the gRPC LB load balancer token.
- *
- * The value corresponding to this key is an opaque token that is given to the
- * frontend as part of each pick; the frontend sends this token to the backend
- * in each request it sends when using that pick. The token is used by the
- * backend to verify the request and to allow the backend to report load to the
- * gRPC LB system. */
-#define GRPC_LB_TOKEN_MD_KEY "lb-token"
-/** Metadata key for gRPC LB cost reporting.
- *
- * The value corresponding to this key is an opaque binary blob reported by the
- * backend as part of its trailing metadata containing cost information for the
- * call. */
-#define GRPC_LB_COST_MD_KEY "lb-cost-bin"
+#include "src/core/lib/channel/channel_stack.h"
/** Identifiers for the invocation point of the users LR callback */
typedef enum grpc_load_reporting_source {
diff --git a/src/core/ext/load_reporting/load_reporting_filter.c b/src/core/ext/load_reporting/load_reporting_filter.c
index 8af6191c3b..c2750634a5 100644
--- a/src/core/ext/load_reporting/load_reporting_filter.c
+++ b/src/core/ext/load_reporting/load_reporting_filter.c
@@ -31,11 +31,13 @@
*
*/
+#include <string.h>
+
+#include <grpc/load_reporting.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
-#include <string.h>
#include "src/core/ext/load_reporting/load_reporting.h"
#include "src/core/ext/load_reporting/load_reporting_filter.h"
@@ -46,8 +48,6 @@
typedef struct call_data {
intptr_t id; /**< an id unique to the call */
- bool have_trailing_md_string;
- grpc_slice trailing_md_string;
bool have_initial_md_string;
grpc_slice initial_md_string;
bool have_service_method;
@@ -100,10 +100,8 @@ static void on_initial_md_ready(grpc_exec_ctx *exec_ctx, void *user_data,
/* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- grpc_call_element_args *args) {
+ const grpc_call_element_args *args) {
call_data *calld = elem->call_data;
- memset(calld, 0, sizeof(call_data));
-
calld->id = (intptr_t)args->call_stack;
grpc_closure_init(&calld->on_initial_md_ready, on_initial_md_ready, elem,
grpc_schedule_on_exec_ctx);
@@ -142,9 +140,6 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
if (calld->have_initial_md_string) {
grpc_slice_unref_internal(exec_ctx, calld->initial_md_string);
}
- if (calld->have_trailing_md_string) {
- grpc_slice_unref_internal(exec_ctx, calld->trailing_md_string);
- }
if (calld->have_service_method) {
grpc_slice_unref_internal(exec_ctx, calld->service_method);
}
@@ -157,8 +152,6 @@ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(!args->is_last);
channel_data *chand = elem->channel_data;
- memset(chand, 0, sizeof(channel_data));
-
chand->id = (intptr_t)args->channel_stack;
/* TODO(dgq): do something with the data
@@ -201,15 +194,6 @@ static void lr_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
/* substitute our callback for the higher callback */
calld->ops_recv_initial_metadata_ready = op->recv_initial_metadata_ready;
op->recv_initial_metadata_ready = &calld->on_initial_md_ready;
- } else if (op->send_trailing_metadata) {
- if (op->send_trailing_metadata->idx.named.lb_cost_bin != NULL) {
- calld->trailing_md_string = grpc_slice_ref_internal(
- GRPC_MDVALUE(op->send_trailing_metadata->idx.named.lb_cost_bin->md));
- calld->have_trailing_md_string = true;
- grpc_metadata_batch_remove(
- exec_ctx, op->send_trailing_metadata,
- op->send_trailing_metadata->idx.named.lb_cost_bin);
- }
}
grpc_call_next_op(exec_ctx, elem, op);
diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c
index 2c9623211b..d227c19c43 100644
--- a/src/core/ext/resolver/dns/native/dns_resolver.c
+++ b/src/core/ext/resolver/dns/native/dns_resolver.c
@@ -40,6 +40,7 @@
#include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/support/backoff.h"
@@ -63,8 +64,6 @@ typedef struct {
/** pollset_set to drive the name resolution process */
grpc_pollset_set *interested_parties;
- /** mutex guarding the rest of the state */
- gpr_mu mu;
/** are we currently resolving? */
bool resolving;
/** which version of the result have we published? */
@@ -95,18 +94,20 @@ static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
dns_resolver *r);
-static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
- grpc_channel_args **target_result,
- grpc_closure *on_complete);
+static void dns_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
+static void dns_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *r);
+static void dns_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
+ grpc_channel_args **target_result,
+ grpc_closure *on_complete);
static const grpc_resolver_vtable dns_resolver_vtable = {
- dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next};
+ dns_destroy, dns_shutdown_locked, dns_channel_saw_error_locked,
+ dns_next_locked};
-static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
+static void dns_shutdown_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver) {
dns_resolver *r = (dns_resolver *)resolver;
- gpr_mu_lock(&r->mu);
if (r->have_retry_timer) {
grpc_timer_cancel(exec_ctx, &r->retry_timer);
}
@@ -116,25 +117,21 @@ static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
GRPC_ERROR_CREATE("Resolver Shutdown"));
r->next_completion = NULL;
}
- gpr_mu_unlock(&r->mu);
}
-static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
- grpc_resolver *resolver) {
+static void dns_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver) {
dns_resolver *r = (dns_resolver *)resolver;
- gpr_mu_lock(&r->mu);
if (!r->resolving) {
gpr_backoff_reset(&r->backoff_state);
dns_start_resolving_locked(exec_ctx, r);
}
- gpr_mu_unlock(&r->mu);
}
-static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
- grpc_channel_args **target_result,
- grpc_closure *on_complete) {
+static void dns_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
+ grpc_channel_args **target_result,
+ grpc_closure *on_complete) {
dns_resolver *r = (dns_resolver *)resolver;
- gpr_mu_lock(&r->mu);
GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete;
r->target_result = target_result;
@@ -144,30 +141,26 @@ static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
} else {
dns_maybe_finish_next_locked(exec_ctx, r);
}
- gpr_mu_unlock(&r->mu);
}
-static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static void dns_on_retry_timer_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
dns_resolver *r = arg;
- gpr_mu_lock(&r->mu);
r->have_retry_timer = false;
if (error == GRPC_ERROR_NONE) {
if (!r->resolving) {
dns_start_resolving_locked(exec_ctx, r);
}
}
- gpr_mu_unlock(&r->mu);
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer");
}
-static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_error *error) {
+static void dns_on_resolved_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
dns_resolver *r = arg;
grpc_channel_args *result = NULL;
- gpr_mu_lock(&r->mu);
GPR_ASSERT(r->resolving);
r->resolving = false;
if (r->addresses != NULL) {
@@ -198,8 +191,8 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
} else {
gpr_log(GPR_DEBUG, "retrying immediately");
}
- grpc_closure_init(&r->on_retry, dns_on_retry_timer, r,
- grpc_schedule_on_exec_ctx);
+ grpc_closure_init(&r->on_retry, dns_on_retry_timer_locked, r,
+ grpc_combiner_scheduler(r->base.combiner, false));
grpc_timer_init(exec_ctx, &r->retry_timer, next_try, &r->on_retry, now);
}
if (r->resolved_result != NULL) {
@@ -208,7 +201,6 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
r->resolved_result = result;
r->resolved_version++;
dns_maybe_finish_next_locked(exec_ctx, r);
- gpr_mu_unlock(&r->mu);
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
}
@@ -221,7 +213,8 @@ static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
r->addresses = NULL;
grpc_resolve_address(
exec_ctx, r->name_to_resolve, r->default_port, r->interested_parties,
- grpc_closure_create(dns_on_resolved, r, grpc_schedule_on_exec_ctx),
+ grpc_closure_create(dns_on_resolved_locked, r,
+ grpc_combiner_scheduler(r->base.combiner, false)),
&r->addresses);
}
@@ -240,11 +233,10 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
dns_resolver *r = (dns_resolver *)gr;
- gpr_mu_destroy(&r->mu);
if (r->resolved_result != NULL) {
grpc_channel_args_destroy(exec_ctx, r->resolved_result);
}
- grpc_pollset_set_destroy(r->interested_parties);
+ grpc_pollset_set_destroy(exec_ctx, r->interested_parties);
gpr_free(r->name_to_resolve);
gpr_free(r->default_port);
grpc_channel_args_destroy(exec_ctx, r->channel_args);
@@ -262,10 +254,8 @@ static grpc_resolver *dns_create(grpc_exec_ctx *exec_ctx,
char *path = args->uri->path;
if (path[0] == '/') ++path;
// Create resolver.
- dns_resolver *r = gpr_malloc(sizeof(dns_resolver));
- memset(r, 0, sizeof(*r));
- gpr_mu_init(&r->mu);
- grpc_resolver_init(&r->base, &dns_resolver_vtable);
+ dns_resolver *r = gpr_zalloc(sizeof(dns_resolver));
+ grpc_resolver_init(&r->base, &dns_resolver_vtable, args->combiner);
r->name_to_resolve = gpr_strdup(path);
r->default_port = gpr_strdup(default_port);
r->channel_args = grpc_channel_args_copy(args->args);
diff --git a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
index a1365f6465..da5923d26f 100644
--- a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
+++ b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
@@ -45,6 +45,7 @@
#include "src/core/ext/client_channel/parse_address.h"
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/slice/slice_internal.h"
@@ -58,8 +59,6 @@ typedef struct {
grpc_lb_addresses *addresses;
/** channel args */
grpc_channel_args *channel_args;
- /** mutex guarding the rest of the state */
- gpr_mu mu;
/** have we published? */
bool published;
/** pending next completion, or NULL */
@@ -73,48 +72,43 @@ static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
sockaddr_resolver *r);
-static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
-static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
- grpc_resolver *r);
-static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
- grpc_channel_args **target_result,
- grpc_closure *on_complete);
+static void sockaddr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
+static void sockaddr_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *r);
+static void sockaddr_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
+ grpc_channel_args **target_result,
+ grpc_closure *on_complete);
static const grpc_resolver_vtable sockaddr_resolver_vtable = {
- sockaddr_destroy, sockaddr_shutdown, sockaddr_channel_saw_error,
- sockaddr_next};
+ sockaddr_destroy, sockaddr_shutdown_locked,
+ sockaddr_channel_saw_error_locked, sockaddr_next_locked};
-static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx,
- grpc_resolver *resolver) {
+static void sockaddr_shutdown_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
- gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) {
*r->target_result = NULL;
grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE);
r->next_completion = NULL;
}
- gpr_mu_unlock(&r->mu);
}
-static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
- grpc_resolver *resolver) {
+static void sockaddr_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
- gpr_mu_lock(&r->mu);
r->published = false;
sockaddr_maybe_finish_next_locked(exec_ctx, r);
- gpr_mu_unlock(&r->mu);
}
-static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
- grpc_channel_args **target_result,
- grpc_closure *on_complete) {
+static void sockaddr_next_locked(grpc_exec_ctx *exec_ctx,
+ grpc_resolver *resolver,
+ grpc_channel_args **target_result,
+ grpc_closure *on_complete) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
- gpr_mu_lock(&r->mu);
GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete;
r->target_result = target_result;
sockaddr_maybe_finish_next_locked(exec_ctx, r);
- gpr_mu_unlock(&r->mu);
}
static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
@@ -131,7 +125,6 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
sockaddr_resolver *r = (sockaddr_resolver *)gr;
- gpr_mu_destroy(&r->mu);
grpc_lb_addresses_destroy(exec_ctx, r->addresses);
grpc_channel_args_destroy(exec_ctx, r->channel_args);
gpr_free(r);
@@ -197,12 +190,10 @@ static grpc_resolver *sockaddr_create(grpc_exec_ctx *exec_ctx,
return NULL;
}
/* Instantiate resolver. */
- sockaddr_resolver *r = gpr_malloc(sizeof(sockaddr_resolver));
- memset(r, 0, sizeof(*r));
+ sockaddr_resolver *r = gpr_zalloc(sizeof(sockaddr_resolver));
r->addresses = addresses;
r->channel_args = grpc_channel_args_copy(args->args);
- gpr_mu_init(&r->mu);
- grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
+ grpc_resolver_init(&r->base, &sockaddr_resolver_vtable, args->combiner);
return &r->base;
}
diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.c b/src/core/ext/transport/chttp2/client/chttp2_connector.c
index d0a762a280..eae0145ecc 100644
--- a/src/core/ext/transport/chttp2/client/chttp2_connector.c
+++ b/src/core/ext/transport/chttp2/client/chttp2_connector.c
@@ -226,7 +226,7 @@ static void chttp2_connector_connect(grpc_exec_ctx *exec_ctx,
grpc_closure *notify) {
chttp2_connector *c = (chttp2_connector *)con;
grpc_resolved_address addr;
- grpc_get_subchannel_address_arg(args->channel_args, &addr);
+ grpc_get_subchannel_address_arg(exec_ctx, args->channel_args, &addr);
gpr_mu_lock(&c->mu);
GPR_ASSERT(c->notify == NULL);
c->notify = notify;
@@ -248,8 +248,7 @@ static const grpc_connector_vtable chttp2_connector_vtable = {
chttp2_connector_connect};
grpc_connector *grpc_chttp2_connector_create() {
- chttp2_connector *c = gpr_malloc(sizeof(*c));
- memset(c, 0, sizeof(*c));
+ chttp2_connector *c = gpr_zalloc(sizeof(*c));
c->base.vtable = &chttp2_connector_vtable;
gpr_mu_init(&c->mu);
gpr_ref_init(&c->refs, 1);
diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
index 490a0c560e..067ac35a5a 100644
--- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c
+++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
@@ -72,8 +72,11 @@ static grpc_channel *client_channel_factory_create_channel(
grpc_arg arg;
arg.type = GRPC_ARG_STRING;
arg.key = GRPC_ARG_SERVER_URI;
- arg.value.string = grpc_resolver_factory_add_default_prefix_if_needed(target);
- grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
+ arg.value.string =
+ grpc_resolver_factory_add_default_prefix_if_needed(exec_ctx, target);
+ const char *to_remove[] = {GRPC_ARG_SERVER_URI};
+ grpc_channel_args *new_args =
+ grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1);
gpr_free(arg.value.string);
grpc_channel *channel = grpc_channel_create(exec_ctx, target, new_args,
GRPC_CLIENT_CHANNEL, NULL);
diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
index d8c18eb122..f0c241d68e 100644
--- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
+++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
@@ -83,7 +83,7 @@ static grpc_subchannel_args *get_secure_naming_subchannel_args(
const char *server_uri_str = server_uri_arg->value.string;
GPR_ASSERT(server_uri_str != NULL);
grpc_uri *server_uri =
- grpc_uri_parse(server_uri_str, true /* supress errors */);
+ grpc_uri_parse(exec_ctx, server_uri_str, true /* supress errors */);
GPR_ASSERT(server_uri != NULL);
const char *server_uri_path;
server_uri_path =
@@ -96,7 +96,7 @@ static grpc_subchannel_args *get_secure_naming_subchannel_args(
const char *target_uri_str =
grpc_get_subchannel_address_uri_arg(args->args);
grpc_uri *target_uri =
- grpc_uri_parse(target_uri_str, false /* suppress errors */);
+ grpc_uri_parse(exec_ctx, target_uri_str, false /* suppress errors */);
GPR_ASSERT(target_uri != NULL);
if (target_uri->path[0] != '\0') { // "path" may be empty
const grpc_slice key = grpc_slice_from_static_string(
@@ -181,8 +181,11 @@ static grpc_channel *client_channel_factory_create_channel(
grpc_arg arg;
arg.type = GRPC_ARG_STRING;
arg.key = GRPC_ARG_SERVER_URI;
- arg.value.string = grpc_resolver_factory_add_default_prefix_if_needed(target);
- grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
+ arg.value.string =
+ grpc_resolver_factory_add_default_prefix_if_needed(exec_ctx, target);
+ const char *to_remove[] = {GRPC_ARG_SERVER_URI};
+ grpc_channel_args *new_args =
+ grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1);
gpr_free(arg.value.string);
grpc_channel *channel = grpc_channel_create(exec_ctx, target, new_args,
GRPC_CLIENT_CHANNEL, NULL);
diff --git a/src/core/ext/transport/chttp2/server/chttp2_server.c b/src/core/ext/transport/chttp2/server/chttp2_server.c
index ae2c3838ed..837b9fd03d 100644
--- a/src/core/ext/transport/chttp2/server/chttp2_server.c
+++ b/src/core/ext/transport/chttp2/server/chttp2_server.c
@@ -55,11 +55,6 @@
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/server.h"
-typedef struct pending_handshake_manager_node {
- grpc_handshake_manager *handshake_mgr;
- struct pending_handshake_manager_node *next;
-} pending_handshake_manager_node;
-
typedef struct {
grpc_server *server;
grpc_tcp_server *tcp_server;
@@ -68,7 +63,7 @@ typedef struct {
bool shutdown;
grpc_closure tcp_server_shutdown_complete;
grpc_closure *server_destroy_listener_done;
- pending_handshake_manager_node *pending_handshake_mgrs;
+ grpc_handshake_manager *pending_handshake_mgrs;
} server_state;
typedef struct {
@@ -78,44 +73,6 @@ typedef struct {
grpc_handshake_manager *handshake_mgr;
} server_connection_state;
-static void pending_handshake_manager_add_locked(
- server_state *state, grpc_handshake_manager *handshake_mgr) {
- pending_handshake_manager_node *node = gpr_malloc(sizeof(*node));
- node->handshake_mgr = handshake_mgr;
- node->next = state->pending_handshake_mgrs;
- state->pending_handshake_mgrs = node;
-}
-
-static void pending_handshake_manager_remove_locked(
- server_state *state, grpc_handshake_manager *handshake_mgr) {
- pending_handshake_manager_node **prev_node = &state->pending_handshake_mgrs;
- for (pending_handshake_manager_node *node = state->pending_handshake_mgrs;
- node != NULL; node = node->next) {
- if (node->handshake_mgr == handshake_mgr) {
- *prev_node = node->next;
- gpr_free(node);
- break;
- }
- prev_node = &node->next;
- }
-}
-
-static void pending_handshake_manager_shutdown_locked(grpc_exec_ctx *exec_ctx,
- server_state *state,
- grpc_error *why) {
- pending_handshake_manager_node *prev_node = NULL;
- for (pending_handshake_manager_node *node = state->pending_handshake_mgrs;
- node != NULL; node = node->next) {
- grpc_handshake_manager_shutdown(exec_ctx, node->handshake_mgr,
- GRPC_ERROR_REF(why));
- gpr_free(prev_node);
- prev_node = node;
- }
- gpr_free(prev_node);
- state->pending_handshake_mgrs = NULL;
- GRPC_ERROR_UNREF(why);
-}
-
static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_handshaker_args *args = arg;
@@ -153,8 +110,9 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
grpc_channel_args_destroy(exec_ctx, args->args);
}
}
- pending_handshake_manager_remove_locked(connection_state->server_state,
- connection_state->handshake_mgr);
+ grpc_handshake_manager_pending_list_remove(
+ &connection_state->server_state->pending_handshake_mgrs,
+ connection_state->handshake_mgr);
gpr_mu_unlock(&connection_state->server_state->mu);
grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr);
grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp_server);
@@ -174,7 +132,8 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
return;
}
grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create();
- pending_handshake_manager_add_locked(state, handshake_mgr);
+ grpc_handshake_manager_pending_list_add(&state->pending_handshake_mgrs,
+ handshake_mgr);
gpr_mu_unlock(&state->mu);
grpc_tcp_server_ref(state->tcp_server);
server_connection_state *connection_state =
@@ -213,8 +172,8 @@ static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *arg,
gpr_mu_lock(&state->mu);
grpc_closure *destroy_done = state->server_destroy_listener_done;
GPR_ASSERT(state->shutdown);
- pending_handshake_manager_shutdown_locked(exec_ctx, state,
- GRPC_ERROR_REF(error));
+ grpc_handshake_manager_pending_list_shutdown_all(
+ exec_ctx, state->pending_handshake_mgrs, GRPC_ERROR_REF(error));
gpr_mu_unlock(&state->mu);
// Flush queued work before destroying handshaker factory, since that
// may do a synchronous unref.
@@ -263,8 +222,7 @@ grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
if (err != GRPC_ERROR_NONE) {
goto error;
}
- state = gpr_malloc(sizeof(*state));
- memset(state, 0, sizeof(*state));
+ state = gpr_zalloc(sizeof(*state));
grpc_closure_init(&state->tcp_server_shutdown_complete,
tcp_server_shutdown_complete, state,
grpc_schedule_on_exec_ctx);
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index 8a9eaa8b6a..a3684535ff 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -48,16 +48,19 @@
#include "src/core/ext/transport/chttp2/transport/varint.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/http/parser.h"
+#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/iomgr/workqueue.h"
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
+#include "src/core/lib/support/env.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/http2_errors.h"
#include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/status_conversion.h"
#include "src/core/lib/transport/timeout_encoding.h"
+#include "src/core/lib/transport/transport.h"
#include "src/core/lib/transport/transport_impl.h"
#define DEFAULT_WINDOW 65535
@@ -66,6 +69,10 @@
#define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024)
#define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024)
+#define DEFAULT_KEEPALIVE_TIME_SECOND INT_MAX
+#define DEFAULT_KEEPALIVE_TIMEOUT_SECOND 20
+#define DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS false
+
#define MAX_CLIENT_STREAM_ID 0x7fffffffu
int grpc_http_trace = 0;
int grpc_flowctl_trace = 0;
@@ -139,6 +146,16 @@ static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
#define DEFAULT_MIN_TIME_BETWEEN_PINGS_MS 0
#define DEFAULT_MAX_PINGS_BETWEEN_DATA 3
+/** keepalive-relevant functions */
+static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error);
+static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error);
+static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error);
+static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error);
+
/*******************************************************************************
* CONSTRUCTION/DESTRUCTION/REFCOUNTING
*/
@@ -168,7 +185,7 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_map_destroy(&t->stream_map);
grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker);
- grpc_combiner_destroy(exec_ctx, t->combiner);
+ GRPC_COMBINER_UNREF(exec_ctx, t->combiner, "chttp2_transport");
cancel_pings(exec_ctx, t, GRPC_ERROR_CREATE("Transport destroyed"));
@@ -218,8 +235,6 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) ==
GRPC_CHTTP2_CLIENT_CONNECT_STRLEN);
- memset(t, 0, sizeof(*t));
-
t->base.vtable = &vtable;
t->ep = ep;
/* one ref is for destroy */
@@ -255,6 +270,17 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
grpc_combiner_scheduler(t->combiner, false));
grpc_closure_init(&t->finish_bdp_ping_locked, finish_bdp_ping_locked, t,
grpc_combiner_scheduler(t->combiner, false));
+ grpc_closure_init(&t->init_keepalive_ping_locked, init_keepalive_ping_locked,
+ t, grpc_combiner_scheduler(t->combiner, false));
+ grpc_closure_init(&t->start_keepalive_ping_locked,
+ start_keepalive_ping_locked, t,
+ grpc_combiner_scheduler(t->combiner, false));
+ grpc_closure_init(&t->finish_keepalive_ping_locked,
+ finish_keepalive_ping_locked, t,
+ grpc_combiner_scheduler(t->combiner, false));
+ grpc_closure_init(&t->keepalive_watchdog_fired_locked,
+ keepalive_watchdog_fired_locked, t,
+ grpc_combiner_scheduler(t->combiner, false));
grpc_bdp_estimator_init(&t->bdp_estimator, t->peer_string);
t->last_pid_update = gpr_now(GPR_CLOCK_MONOTONIC);
@@ -265,7 +291,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
.gain_d = 0,
.initial_control_value = log2(DEFAULT_WINDOW),
.min_control_value = -1,
- .max_control_value = 22,
+ .max_control_value = 25,
.integral_range = 10});
grpc_chttp2_goaway_parser_init(&t->goaway_parser);
@@ -316,6 +342,18 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
gpr_time_from_millis(DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, GPR_TIMESPAN),
};
+ /* client-side keepalive setting */
+ t->keepalive_time =
+ DEFAULT_KEEPALIVE_TIME_SECOND == INT_MAX
+ ? gpr_inf_future(GPR_TIMESPAN)
+ : gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIME_SECOND, GPR_TIMESPAN);
+ t->keepalive_timeout =
+ DEFAULT_KEEPALIVE_TIMEOUT_SECOND == INT_MAX
+ ? gpr_inf_future(GPR_TIMESPAN)
+ : gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIMEOUT_SECOND,
+ GPR_TIMESPAN);
+ t->keepalive_permit_without_calls = DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS;
+
if (channel_args) {
for (i = 0; i < channel_args->num_args; i++) {
if (0 == strcmp(channel_args->args[i].key,
@@ -363,6 +401,28 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_BDP_PROBE)) {
t->enable_bdp_probe = grpc_channel_arg_get_integer(
&channel_args->args[i], (grpc_integer_options){1, 0, 1});
+ } else if (0 == strcmp(channel_args->args[i].key,
+ GRPC_ARG_HTTP2_KEEPALIVE_TIME)) {
+ const int value = grpc_channel_arg_get_integer(
+ &channel_args->args[i],
+ (grpc_integer_options){DEFAULT_KEEPALIVE_TIME_SECOND, 1, INT_MAX});
+ t->keepalive_time = value == INT_MAX
+ ? gpr_inf_future(GPR_TIMESPAN)
+ : gpr_time_from_seconds(value, GPR_TIMESPAN);
+ } else if (0 == strcmp(channel_args->args[i].key,
+ GRPC_ARG_HTTP2_KEEPALIVE_TIMEOUT)) {
+ const int value = grpc_channel_arg_get_integer(
+ &channel_args->args[i],
+ (grpc_integer_options){DEFAULT_KEEPALIVE_TIMEOUT_SECOND, 0,
+ INT_MAX});
+ t->keepalive_timeout = value == INT_MAX
+ ? gpr_inf_future(GPR_TIMESPAN)
+ : gpr_time_from_seconds(value, GPR_TIMESPAN);
+ } else if (0 == strcmp(channel_args->args[i].key,
+ GRPC_ARG_HTTP2_KEEPALIVE_PERMIT_WITHOUT_CALLS)) {
+ t->keepalive_permit_without_calls =
+ (uint32_t)grpc_channel_arg_get_integer(
+ &channel_args->args[i], (grpc_integer_options){0, 0, 1});
} else {
static const struct {
const char *channel_arg_name;
@@ -414,6 +474,16 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
+ /** Start client-side keepalive pings */
+ if (t->is_client) {
+ t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING;
+ GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
+ grpc_timer_init(
+ exec_ctx, &t->keepalive_ping_timer,
+ gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
+ &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC));
+ }
+
grpc_chttp2_initiate_write(exec_ctx, t, false, "init");
post_benign_reclaimer(exec_ctx, t);
}
@@ -441,6 +511,10 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_error *error) {
if (!t->closed) {
+ if (!grpc_error_has_clear_grpc_status(error)) {
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
+ GRPC_STATUS_UNAVAILABLE);
+ }
if (t->write_state != GRPC_CHTTP2_WRITE_STATE_IDLE) {
if (t->close_transport_on_writes_finished == NULL) {
t->close_transport_on_writes_finished =
@@ -450,14 +524,26 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
grpc_error_add_child(t->close_transport_on_writes_finished, error);
return;
}
- if (!grpc_error_has_clear_grpc_status(error)) {
- error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
- GRPC_STATUS_UNAVAILABLE);
- }
t->closed = 1;
connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_REF(error), "close_transport");
grpc_endpoint_shutdown(exec_ctx, t->ep, GRPC_ERROR_REF(error));
+ if (t->is_client) {
+ switch (t->keepalive_state) {
+ case GRPC_CHTTP2_KEEPALIVE_STATE_WAITING: {
+ grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer);
+ break;
+ }
+ case GRPC_CHTTP2_KEEPALIVE_STATE_PINGING: {
+ grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer);
+ grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer);
+ break;
+ }
+ case GRPC_CHTTP2_KEEPALIVE_STATE_DYING: {
+ break;
+ }
+ }
+ }
/* flush writable stream list to avoid dangling references */
grpc_chttp2_stream *s;
@@ -494,8 +580,6 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
- memset(s, 0, sizeof(*s));
-
s->t = t;
s->refcount = refcount;
/* We reserve one 'active stream' that's dropped when the stream is
@@ -569,6 +653,14 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp,
GRPC_ERROR_UNREF(s->read_closed_error);
GRPC_ERROR_UNREF(s->write_closed_error);
+ if (s->incoming_window_delta > 0) {
+ GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA(
+ "destroy", t, s, s->incoming_window_delta);
+ } else if (s->incoming_window_delta < 0) {
+ GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA(
+ "destroy", t, s, -s->incoming_window_delta);
+ }
+
GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "stream");
GPR_TIMER_END("destroy_stream", 0);
@@ -1033,8 +1125,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
grpc_transport_stream_op *op = stream_op;
- grpc_chttp2_transport *t = op->transport_private.args[0];
- grpc_chttp2_stream *s = op->transport_private.args[1];
+ grpc_chttp2_transport *t = op->handler_private.args[0];
+ grpc_chttp2_stream *s = op->handler_private.args[1];
if (grpc_http_trace) {
char *str = grpc_transport_stream_op_string(op);
@@ -1106,8 +1198,11 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
grpc_chttp2_list_add_waiting_for_concurrency(t, s);
maybe_start_some_streams(exec_ctx, t);
} else {
- grpc_chttp2_cancel_stream(exec_ctx, t, s,
- GRPC_ERROR_CREATE("Transport closed"));
+ grpc_chttp2_cancel_stream(
+ exec_ctx, t, s,
+ grpc_error_set_int(GRPC_ERROR_CREATE("Transport closed"),
+ GRPC_ERROR_INT_GRPC_STATUS,
+ GRPC_STATUS_UNAVAILABLE));
}
} else {
GPR_ASSERT(s->id != 0);
@@ -1255,13 +1350,13 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
gpr_free(str);
}
- op->transport_private.args[0] = gt;
- op->transport_private.args[1] = gs;
+ op->handler_private.args[0] = gt;
+ op->handler_private.args[1] = gs;
GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op");
grpc_closure_sched(
exec_ctx,
grpc_closure_init(
- &op->transport_private.closure, perform_stream_op_locked, op,
+ &op->handler_private.closure, perform_stream_op_locked, op,
grpc_combiner_scheduler(t->combiner, op->covered_by_poller)),
GRPC_ERROR_NONE);
GPR_TIMER_END("perform_stream_op", 0);
@@ -1801,13 +1896,13 @@ static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
if (delta == 0 || (bdp != 0 && delta > -1024 && delta < 1024)) {
return;
}
+ if (grpc_bdp_estimator_trace) {
+ gpr_log(GPR_DEBUG, "%s: update initial window size to %d", t->peer_string,
+ (int)bdp);
+ }
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, bdp);
}
-/*******************************************************************************
- * INPUT PROCESSING - PARSING
- */
-
static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t) {
grpc_http_parser parser;
@@ -1976,6 +2071,77 @@ static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "bdp_ping");
}
+static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ grpc_chttp2_transport *t = arg;
+ GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING);
+ if (error == GRPC_ERROR_NONE && !(t->destroying || t->closed)) {
+ if (t->keepalive_permit_without_calls || t->stream_map.count > 0) {
+ t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_PINGING;
+ GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end");
+ send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE,
+ &t->start_keepalive_ping_locked,
+ &t->finish_keepalive_ping_locked);
+ } else {
+ GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
+ grpc_timer_init(
+ exec_ctx, &t->keepalive_ping_timer,
+ gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
+ &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC));
+ }
+ }
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "init keepalive ping");
+}
+
+static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ grpc_chttp2_transport *t = arg;
+ GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog");
+ grpc_timer_init(
+ exec_ctx, &t->keepalive_watchdog_timer,
+ gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_timeout),
+ &t->keepalive_watchdog_fired_locked, gpr_now(GPR_CLOCK_MONOTONIC));
+}
+
+static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ grpc_chttp2_transport *t = arg;
+ if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) {
+ if (error == GRPC_ERROR_NONE) {
+ t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING;
+ grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer);
+ GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
+ grpc_timer_init(
+ exec_ctx, &t->keepalive_ping_timer,
+ gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
+ grpc_closure_create(init_keepalive_ping_locked, t,
+ grpc_combiner_scheduler(t->combiner, false)),
+ gpr_now(GPR_CLOCK_MONOTONIC));
+ }
+ }
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive ping end");
+}
+
+static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ grpc_chttp2_transport *t = arg;
+ if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) {
+ if (error == GRPC_ERROR_NONE) {
+ t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING;
+ close_transport_locked(exec_ctx, t,
+ GRPC_ERROR_CREATE("keepalive watchdog timeout"));
+ }
+ } else {
+ /** The watchdog timer should have been cancelled by
+ finish_keepalive_ping_locked. */
+ if (error != GRPC_ERROR_CANCELLED) {
+ gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)",
+ t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING);
+ }
+ }
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive watchdog");
+}
+
/*******************************************************************************
* CALLBACK LOOP
*/
@@ -2054,8 +2220,8 @@ static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx,
(int64_t)have_already) {
write_type = GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED;
}
- GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, incoming_window_delta,
- add_max_recv_bytes);
+ GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA("op", t, s,
+ add_max_recv_bytes);
GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, announce_window,
add_max_recv_bytes);
if ((int64_t)s->incoming_window_delta + (int64_t)initial_window_size -
@@ -2417,7 +2583,7 @@ static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
grpc_transport *grpc_create_chttp2_transport(
grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args,
grpc_endpoint *ep, int is_client) {
- grpc_chttp2_transport *t = gpr_malloc(sizeof(grpc_chttp2_transport));
+ grpc_chttp2_transport *t = gpr_zalloc(sizeof(grpc_chttp2_transport));
init_transport(exec_ctx, t, channel_args, ep, is_client != 0);
return &t->base;
}
diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.c b/src/core/ext/transport/chttp2/transport/frame_ping.c
index f487533c41..9b4b1a7b84 100644
--- a/src/core/ext/transport/chttp2/transport/frame_ping.c
+++ b/src/core/ext/transport/chttp2/transport/frame_ping.c
@@ -91,7 +91,7 @@ grpc_error *grpc_chttp2_ping_parser_parse(grpc_exec_ctx *exec_ctx, void *parser,
grpc_chttp2_ping_parser *p = parser;
while (p->byte != 8 && cur != end) {
- p->opaque_8bytes |= (((uint64_t)*cur) << (8 * p->byte));
+ p->opaque_8bytes |= (((uint64_t)*cur) << (56 - 8 * p->byte));
cur++;
p->byte++;
}
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.h b/src/core/ext/transport/chttp2/transport/frame_settings.h
index a29dc82106..44137798c0 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.h
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.h
@@ -87,7 +87,7 @@ extern const grpc_chttp2_setting_parameters
grpc_chttp2_settings_parameters[GRPC_CHTTP2_NUM_SETTINGS];
/* Create a settings frame by diffing old & new, and updating old to be new */
-grpc_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *new,
+grpc_slice grpc_chttp2_settings_create(uint32_t *old, const uint32_t *newval,
uint32_t force_mask, size_t count);
/* Create an ack settings frame */
grpc_slice grpc_chttp2_settings_ack_create(void);
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.c b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
index 63df8e135f..84586cd998 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
@@ -173,6 +173,7 @@ static void add_header_data(framer_state *st, grpc_slice slice) {
static uint8_t *add_tiny_header_data(framer_state *st, size_t len) {
ensure_space(st, len);
+ st->stats->header_bytes += len;
return grpc_slice_buffer_tiny_add(st->output, len);
}
diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h
index 075d421dd4..d26812ad6b 100644
--- a/src/core/ext/transport/chttp2/transport/internal.h
+++ b/src/core/ext/transport/chttp2/transport/internal.h
@@ -50,6 +50,7 @@
#include "src/core/ext/transport/chttp2/transport/stream_map.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/transport/bdp_estimator.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/pid_controller.h"
@@ -208,6 +209,12 @@ struct grpc_chttp2_incoming_byte_stream {
grpc_closure finished_action;
};
+typedef enum {
+ GRPC_CHTTP2_KEEPALIVE_STATE_WAITING,
+ GRPC_CHTTP2_KEEPALIVE_STATE_PINGING,
+ GRPC_CHTTP2_KEEPALIVE_STATE_DYING,
+} grpc_chttp2_keepalive_state;
+
struct grpc_chttp2_transport {
grpc_transport base; /* must be first */
gpr_refcount refs;
@@ -271,10 +278,6 @@ struct grpc_chttp2_transport {
/** data to write next write */
grpc_slice_buffer qbuf;
- /** window available to announce to peer */
- int64_t announce_incoming_window;
- /** how much window would we like to have for incoming_window */
- uint32_t connection_window_target;
/** how much data are we willing to buffer when the WRITE_BUFFER_HINT is set?
*/
uint32_t write_buffer_size;
@@ -328,6 +331,16 @@ struct grpc_chttp2_transport {
/** window available for peer to send to us */
int64_t incoming_window;
+ /** calculating what we should give for incoming window:
+ we track the total amount of flow control over initial window size
+ across all streams: this is data that we want to receive right now (it
+ has an outstanding read)
+ and the total amount of flow control under initial window size across all
+ streams: this is data we've read early
+ we want to adjust incoming_window such that:
+ incoming_window = total_over - max(bdp - total_under, 0) */
+ int64_t stream_total_over_incoming_window;
+ int64_t stream_total_under_incoming_window;
/* deframing */
grpc_chttp2_deframe_transport_state deframe_state;
@@ -376,6 +389,28 @@ struct grpc_chttp2_transport {
grpc_closure benign_reclaimer_locked;
/** destructive cleanup closure */
grpc_closure destructive_reclaimer_locked;
+
+ /* keep-alive ping support */
+ /** Closure to initialize a keepalive ping */
+ grpc_closure init_keepalive_ping_locked;
+ /** Closure to run when the keepalive ping is sent */
+ grpc_closure start_keepalive_ping_locked;
+ /** Cousure to run when the keepalive ping ack is received */
+ grpc_closure finish_keepalive_ping_locked;
+ /** Closrue to run when the keepalive ping timeouts */
+ grpc_closure keepalive_watchdog_fired_locked;
+ /** timer to initiate ping events */
+ grpc_timer keepalive_ping_timer;
+ /** watchdog to kill the transport when waiting for the keepalive ping */
+ grpc_timer keepalive_watchdog_timer;
+ /** time duration in between pings */
+ gpr_timespec keepalive_time;
+ /** grace period for a ping to complete before watchdog kicks in */
+ gpr_timespec keepalive_timeout;
+ /** if keepalive pings are allowed when there's no outstanding streams */
+ bool keepalive_permit_without_calls;
+ /** keep-alive state machine state */
+ grpc_chttp2_keepalive_state keepalive_state;
};
typedef enum {
@@ -634,6 +669,44 @@ typedef enum {
GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, dst_context, 0, dst_context, dst_var, \
amount)
+#define GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE( \
+ phase, transport, dst_context) \
+ if (dst_context->incoming_window_delta < 0) { \
+ transport->stream_total_under_incoming_window += \
+ dst_context->incoming_window_delta; \
+ } else if (dst_context->incoming_window_delta > 0) { \
+ transport->stream_total_over_incoming_window -= \
+ dst_context->incoming_window_delta; \
+ }
+
+#define GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE( \
+ phase, transport, dst_context) \
+ if (dst_context->incoming_window_delta < 0) { \
+ transport->stream_total_under_incoming_window -= \
+ dst_context->incoming_window_delta; \
+ } else if (dst_context->incoming_window_delta > 0) { \
+ transport->stream_total_over_incoming_window += \
+ dst_context->incoming_window_delta; \
+ }
+
+#define GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA( \
+ phase, transport, dst_context, amount) \
+ GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE(phase, transport, \
+ dst_context); \
+ GRPC_CHTTP2_FLOW_DEBIT_STREAM(phase, transport, dst_context, \
+ incoming_window_delta, amount); \
+ GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE(phase, transport, \
+ dst_context);
+
+#define GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA( \
+ phase, transport, dst_context, amount) \
+ GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE(phase, transport, \
+ dst_context); \
+ GRPC_CHTTP2_FLOW_CREDIT_STREAM(phase, transport, dst_context, \
+ incoming_window_delta, amount); \
+ GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE(phase, transport, \
+ dst_context);
+
#define GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, id, dst_context, \
dst_var, amount) \
do { \
@@ -752,4 +825,6 @@ void grpc_chttp2_fail_pending_writes(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_chttp2_stream *s, grpc_error *error);
+uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t);
+
#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H */
diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c
index 24bd93067b..e7f2597f89 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.c
+++ b/src/core/ext/transport/chttp2/transport/parsing.c
@@ -376,34 +376,47 @@ static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx,
return err;
}
- uint32_t target_incoming_window = GPR_MAX(
- t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
- 1024);
- GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", t, incoming_window,
- incoming_frame_size);
- if (t->incoming_window <= target_incoming_window / 2) {
- grpc_chttp2_initiate_write(exec_ctx, t, false, "flow_control");
- }
-
if (s != NULL) {
if (incoming_frame_size >
s->incoming_window_delta +
t->settings[GRPC_ACKED_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]) {
- char *msg;
- gpr_asprintf(&msg,
- "frame of size %d overflows incoming window of %" PRId64,
- t->incoming_frame_size,
- s->incoming_window_delta +
- t->settings[GRPC_ACKED_SETTINGS]
- [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
- grpc_error *err = GRPC_ERROR_CREATE(msg);
- gpr_free(msg);
- return err;
+ if (incoming_frame_size <=
+ s->incoming_window_delta +
+ t->settings[GRPC_SENT_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]) {
+ gpr_log(
+ GPR_ERROR,
+ "Incoming frame of size %d exceeds incoming window size of %" PRId64
+ ".\n"
+ "The (un-acked, future) window size would be %" PRId64
+ " which is not exceeded.\n"
+ "This would usually cause a disconnection, but allowing it due to "
+ "broken HTTP2 implementations in the wild.\n"
+ "See (for example) https://github.com/netty/netty/issues/6520.",
+ t->incoming_frame_size,
+ s->incoming_window_delta +
+ t->settings[GRPC_ACKED_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
+ s->incoming_window_delta +
+ t->settings[GRPC_SENT_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
+ } else {
+ char *msg;
+ gpr_asprintf(&msg,
+ "frame of size %d overflows incoming window of %" PRId64,
+ t->incoming_frame_size,
+ s->incoming_window_delta +
+ t->settings[GRPC_ACKED_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
+ grpc_error *err = GRPC_ERROR_CREATE(msg);
+ gpr_free(msg);
+ return err;
+ }
}
- GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", t, s, incoming_window_delta,
- incoming_frame_size);
+ GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA("parse", t, s,
+ incoming_frame_size);
if ((int64_t)t->settings[GRPC_SENT_SETTINGS]
[GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] +
(int64_t)s->incoming_window_delta - (int64_t)s->announce_window <=
@@ -417,6 +430,13 @@ static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx,
s->received_bytes += incoming_frame_size;
}
+ uint32_t target_incoming_window = grpc_chttp2_target_incoming_window(t);
+ GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", t, incoming_window,
+ incoming_frame_size);
+ if (t->incoming_window <= target_incoming_window / 2) {
+ grpc_chttp2_initiate_write(exec_ctx, t, false, "flow_control");
+ }
+
return GRPC_ERROR_NONE;
}
diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c
index 05e6f59947..2b9d93cae7 100644
--- a/src/core/ext/transport/chttp2/transport/writing.c
+++ b/src/core/ext/transport/chttp2/transport/writing.c
@@ -152,6 +152,17 @@ static bool stream_ref_if_not_destroyed(gpr_refcount *r) {
return true;
}
+uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t) {
+ return (uint32_t)GPR_MAX(
+ (int64_t)((1u << 31) - 1),
+ t->stream_total_over_incoming_window +
+ (int64_t)GPR_MAX(
+ t->settings[GRPC_SENT_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] -
+ t->stream_total_under_incoming_window,
+ 0));
+}
+
bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t) {
grpc_chttp2_stream *s;
@@ -310,13 +321,12 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx,
/* if the grpc_chttp2_transport is ready to send a window update, do so here
also; 3/4 is a magic number that will likely get tuned soon */
- uint32_t target_incoming_window = GPR_MAX(
- t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE],
- 1024);
+ uint32_t target_incoming_window = grpc_chttp2_target_incoming_window(t);
uint32_t threshold_to_send_transport_window_update =
t->outbuf.count > 0 ? 3 * target_incoming_window / 4
: target_incoming_window / 2;
- if (t->incoming_window <= threshold_to_send_transport_window_update) {
+ if (t->incoming_window <= threshold_to_send_transport_window_update &&
+ t->incoming_window != target_incoming_window) {
maybe_initiate_ping(exec_ctx, t,
GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE);
uint32_t announced = (uint32_t)GPR_CLAMP(
diff --git a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c
index 477cf07f45..b6e9e845df 100644
--- a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c
+++ b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c
@@ -39,6 +39,7 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
+#include "src/core/ext/transport/cronet/transport/cronet_transport.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/transport_impl.h"
@@ -54,16 +55,14 @@ extern grpc_transport_vtable grpc_cronet_vtable;
GRPCAPI grpc_channel *grpc_cronet_secure_channel_create(
void *engine, const char *target, const grpc_channel_args *args,
void *reserved) {
- cronet_transport *ct = gpr_malloc(sizeof(cronet_transport));
- ct->base.vtable = &grpc_cronet_vtable;
- ct->engine = engine;
- ct->host = gpr_malloc(strlen(target) + 1);
- strcpy(ct->host, target);
gpr_log(GPR_DEBUG,
"grpc_create_cronet_transport: stream_engine = %p, target=%s", engine,
- ct->host);
+ target);
+
+ grpc_transport *ct =
+ grpc_create_cronet_transport(engine, target, args, reserved);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
return grpc_channel_create(&exec_ctx, target, args,
- GRPC_CLIENT_DIRECT_CHANNEL, (grpc_transport *)ct);
+ GRPC_CLIENT_DIRECT_CHANNEL, ct);
}
diff --git a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c
index da6c0b4fbc..0dc6a5152f 100644
--- a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c
+++ b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c
@@ -80,4 +80,16 @@ void bidirectional_stream_cancel(bidirectional_stream* stream) {
GPR_ASSERT(0);
}
+void bidirectional_stream_disable_auto_flush(bidirectional_stream* stream,
+ bool disable_auto_flush) {
+ GPR_ASSERT(0);
+}
+
+void bidirectional_stream_delay_request_headers_until_flush(
+ bidirectional_stream* stream, bool delay_headers_until_flush) {
+ GPR_ASSERT(0);
+}
+
+void bidirectional_stream_flush(bidirectional_stream* stream) { GPR_ASSERT(0); }
+
#endif /* GRPC_COMPILE_WITH_CRONET */
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c
index d755b1f147..fabfaf8a27 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.c
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.c
@@ -54,6 +54,7 @@
#include "third_party/objective_c/Cronet/bidirectional_stream_c.h"
#define GRPC_HEADER_SIZE_IN_BYTES 5
+#define GRPC_FLUSH_READ_SIZE 4096
#define CRONET_LOG(...) \
do { \
@@ -88,7 +89,7 @@ enum e_op_id {
/* Cronet callbacks. See cronet_c_for_grpc.h for documentation for each. */
-static void on_request_headers_sent(bidirectional_stream *);
+static void on_stream_ready(bidirectional_stream *);
static void on_response_headers_received(
bidirectional_stream *, const bidirectional_stream_header_array *,
const char *);
@@ -100,7 +101,7 @@ static void on_succeeded(bidirectional_stream *);
static void on_failed(bidirectional_stream *, int);
static void on_canceled(bidirectional_stream *);
static bidirectional_stream_callback cronet_callbacks = {
- on_request_headers_sent,
+ on_stream_ready,
on_response_headers_received,
on_read_completed,
on_write_completed,
@@ -114,6 +115,7 @@ struct grpc_cronet_transport {
grpc_transport base; /* must be first element in this structure */
stream_engine *engine;
char *host;
+ bool use_packet_coalescing;
};
typedef struct grpc_cronet_transport grpc_cronet_transport;
@@ -150,8 +152,17 @@ struct write_state {
struct op_state {
bool state_op_done[OP_NUM_OPS];
bool state_callback_received[OP_NUM_OPS];
+ /* A non-zero gRPC status code has been seen */
bool fail_state;
+ /* Transport is discarding all buffered messages */
bool flush_read;
+ bool flush_cronet_when_ready;
+ bool pending_write_for_trailer;
+ bool pending_send_message;
+ /* User requested RECV_TRAILING_METADATA */
+ bool pending_recv_trailing_metadata;
+ /* Cronet has not issued a callback of a bidirectional read */
+ bool pending_read_from_cronet;
grpc_error *cancel_error;
/* data structure for storing data coming from server */
struct read_state rs;
@@ -175,7 +186,7 @@ struct op_storage {
struct stream_obj {
struct op_and_state *oas;
grpc_transport_stream_op *curr_op;
- grpc_cronet_transport curr_ct;
+ grpc_cronet_transport *curr_ct;
grpc_stream *curr_gs;
bidirectional_stream *cbs;
bidirectional_stream_header_array header_array;
@@ -244,11 +255,35 @@ static const char *op_id_string(enum e_op_id i) {
return "UNKNOWN";
}
-static void free_read_buffer(stream_obj *s) {
+static void null_and_maybe_free_read_buffer(stream_obj *s) {
if (s->state.rs.read_buffer &&
s->state.rs.read_buffer != s->state.rs.grpc_header_bytes) {
gpr_free(s->state.rs.read_buffer);
- s->state.rs.read_buffer = NULL;
+ }
+ s->state.rs.read_buffer = NULL;
+}
+
+static void maybe_flush_read(stream_obj *s) {
+ /* To enter flush read state (discarding all the buffered messages in
+ * transport layer), two conditions must be satisfied: 1) non-zero grpc status
+ * has been received, and 2) an op requesting the status code
+ * (RECV_TRAILING_METADATA) is issued by the user. (See
+ * doc/status_ordering.md) */
+ /* Whenever the evaluation of any of the two condition is changed, we check
+ * whether we should enter the flush read state. */
+ if (s->state.pending_recv_trailing_metadata && s->state.fail_state) {
+ if (!s->state.flush_read) {
+ CRONET_LOG(GPR_DEBUG, "%p: Flush read", s);
+ s->state.flush_read = true;
+ null_and_maybe_free_read_buffer(s);
+ s->state.rs.read_buffer = gpr_malloc(GRPC_FLUSH_READ_SIZE);
+ if (!s->state.pending_read_from_cronet) {
+ CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs);
+ bidirectional_stream_read(s->cbs, s->state.rs.read_buffer,
+ GRPC_FLUSH_READ_SIZE);
+ s->state.pending_read_from_cronet = true;
+ }
+ }
}
}
@@ -274,6 +309,13 @@ static void add_to_storage(struct stream_obj *s, grpc_transport_stream_op *op) {
new_op->next = storage->head;
storage->head = new_op;
storage->num_pending_ops++;
+ if (op->send_message) {
+ s->state.pending_send_message = true;
+ }
+ if (op->recv_trailing_metadata) {
+ s->state.pending_recv_trailing_metadata = true;
+ maybe_flush_read(s);
+ }
CRONET_LOG(GPR_DEBUG, "adding new op %p. %d in the queue.", new_op,
storage->num_pending_ops);
gpr_mu_unlock(&s->mu);
@@ -360,7 +402,7 @@ static void on_failed(bidirectional_stream *stream, int net_error) {
gpr_free(s->state.ws.write_buffer);
s->state.ws.write_buffer = NULL;
}
- free_read_buffer(s);
+ null_and_maybe_free_read_buffer(s);
gpr_mu_unlock(&s->mu);
execute_from_storage(s);
}
@@ -383,7 +425,7 @@ static void on_canceled(bidirectional_stream *stream) {
gpr_free(s->state.ws.write_buffer);
s->state.ws.write_buffer = NULL;
}
- free_read_buffer(s);
+ null_and_maybe_free_read_buffer(s);
gpr_mu_unlock(&s->mu);
execute_from_storage(s);
}
@@ -398,7 +440,7 @@ static void on_succeeded(bidirectional_stream *stream) {
bidirectional_stream_destroy(s->cbs);
s->state.state_callback_received[OP_SUCCEEDED] = true;
s->cbs = NULL;
- free_read_buffer(s);
+ null_and_maybe_free_read_buffer(s);
gpr_mu_unlock(&s->mu);
execute_from_storage(s);
}
@@ -406,9 +448,10 @@ static void on_succeeded(bidirectional_stream *stream) {
/*
Cronet callback
*/
-static void on_request_headers_sent(bidirectional_stream *stream) {
- CRONET_LOG(GPR_DEBUG, "W: on_request_headers_sent(%p)", stream);
+static void on_stream_ready(bidirectional_stream *stream) {
+ CRONET_LOG(GPR_DEBUG, "W: on_stream_ready(%p)", stream);
stream_obj *s = (stream_obj *)stream->annotation;
+ grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct;
gpr_mu_lock(&s->mu);
s->state.state_op_done[OP_SEND_INITIAL_METADATA] = true;
s->state.state_callback_received[OP_SEND_INITIAL_METADATA] = true;
@@ -417,6 +460,14 @@ static void on_request_headers_sent(bidirectional_stream *stream) {
gpr_free(s->header_array.headers);
s->header_array.headers = NULL;
}
+ /* Send the initial metadata on wire if there is no SEND_MESSAGE or
+ * SEND_TRAILING_METADATA ops pending */
+ if (t->use_packet_coalescing) {
+ if (s->state.flush_cronet_when_ready) {
+ CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_flush (%p)", s->cbs);
+ bidirectional_stream_flush(stream);
+ }
+ }
gpr_mu_unlock(&s->mu);
execute_from_storage(s);
}
@@ -457,6 +508,7 @@ static void on_response_headers_received(
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs);
bidirectional_stream_read(s->cbs, s->state.rs.read_buffer,
s->state.rs.remaining_bytes);
+ s->state.pending_read_from_cronet = true;
}
gpr_mu_unlock(&s->mu);
grpc_exec_ctx_finish(&exec_ctx);
@@ -488,10 +540,13 @@ static void on_read_completed(bidirectional_stream *stream, char *data,
CRONET_LOG(GPR_DEBUG, "R: on_read_completed(%p, %p, %d)", stream, data,
count);
gpr_mu_lock(&s->mu);
+ s->state.pending_read_from_cronet = false;
s->state.state_callback_received[OP_RECV_MESSAGE] = true;
if (count > 0 && s->state.flush_read) {
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs);
- bidirectional_stream_read(s->cbs, s->state.rs.read_buffer, 4096);
+ bidirectional_stream_read(s->cbs, s->state.rs.read_buffer,
+ GRPC_FLUSH_READ_SIZE);
+ s->state.pending_read_from_cronet = true;
gpr_mu_unlock(&s->mu);
} else if (count > 0) {
s->state.rs.received_bytes += count;
@@ -502,16 +557,14 @@ static void on_read_completed(bidirectional_stream *stream, char *data,
bidirectional_stream_read(
s->cbs, s->state.rs.read_buffer + s->state.rs.received_bytes,
s->state.rs.remaining_bytes);
+ s->state.pending_read_from_cronet = true;
gpr_mu_unlock(&s->mu);
} else {
gpr_mu_unlock(&s->mu);
execute_from_storage(s);
}
} else {
- if (s->state.flush_read) {
- gpr_free(s->state.rs.read_buffer);
- s->state.rs.read_buffer = NULL;
- }
+ null_and_maybe_free_read_buffer(s);
s->state.rs.read_stream_closed = true;
gpr_mu_unlock(&s->mu);
execute_from_storage(s);
@@ -528,6 +581,7 @@ static void on_response_trailers_received(
CRONET_LOG(GPR_DEBUG, "R: on_response_trailers_received(%p,%p)", stream,
trailers);
stream_obj *s = (stream_obj *)stream->annotation;
+ grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct;
gpr_mu_lock(&s->mu);
memset(&s->state.rs.trailing_metadata, 0,
sizeof(s->state.rs.trailing_metadata));
@@ -547,6 +601,7 @@ static void on_response_trailers_received(
if (0 == strcmp(trailers->headers[i].key, "grpc-status") &&
0 != strcmp(trailers->headers[i].value, "0")) {
s->state.fail_state = true;
+ maybe_flush_read(s);
}
}
s->state.state_callback_received[OP_RECV_TRAILING_METADATA] = true;
@@ -558,6 +613,10 @@ static void on_response_trailers_received(
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs);
s->state.state_callback_received[OP_SEND_MESSAGE] = false;
bidirectional_stream_write(s->cbs, "", 0, true);
+ if (t->use_packet_coalescing) {
+ CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs);
+ bidirectional_stream_flush(s->cbs);
+ }
s->state.state_op_done[OP_SEND_TRAILING_METADATA] = true;
gpr_mu_unlock(&s->mu);
@@ -607,7 +666,7 @@ static void convert_metadata_to_cronet_headers(
curr = curr->next;
num_headers_available++;
}
- /* Allocate enough memory. It is freed in the on_request_headers_sent callback
+ /* Allocate enough memory. It is freed in the on_stream_ready callback
*/
bidirectional_stream_header *headers =
(bidirectional_stream_header *)gpr_malloc(
@@ -687,8 +746,10 @@ static bool header_has_authority(grpc_linked_mdelem *head) {
executed. This is the heart of the state machine.
*/
static bool op_can_be_run(grpc_transport_stream_op *curr_op,
- struct op_state *stream_state,
- struct op_state *op_state, enum e_op_id op_id) {
+ struct stream_obj *s, struct op_state *op_state,
+ enum e_op_id op_id) {
+ struct op_state *stream_state = &s->state;
+ grpc_cronet_transport *t = s->curr_ct;
bool result = true;
/* When call is canceled, every op can be run, except under following
conditions
@@ -755,12 +816,14 @@ static bool op_can_be_run(grpc_transport_stream_op *curr_op,
else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA])
result = false;
/* we haven't sent message yet */
- else if (curr_op->send_message &&
+ else if (stream_state->pending_send_message &&
!stream_state->state_op_done[OP_SEND_MESSAGE])
result = false;
/* we haven't got on_write_completed for the send yet */
else if (stream_state->state_op_done[OP_SEND_MESSAGE] &&
- !stream_state->state_callback_received[OP_SEND_MESSAGE])
+ !stream_state->state_callback_received[OP_SEND_MESSAGE] &&
+ !(t->use_packet_coalescing &&
+ stream_state->pending_write_for_trailer))
result = false;
} else if (op_id == OP_CANCEL_ERROR) {
/* already executed */
@@ -833,24 +896,28 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
struct op_and_state *oas) {
grpc_transport_stream_op *stream_op = &oas->op;
struct stream_obj *s = oas->s;
+ grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct;
struct op_state *stream_state = &s->state;
enum e_op_result result = NO_ACTION_POSSIBLE;
if (stream_op->send_initial_metadata &&
- op_can_be_run(stream_op, stream_state, &oas->state,
- OP_SEND_INITIAL_METADATA)) {
+ op_can_be_run(stream_op, s, &oas->state, OP_SEND_INITIAL_METADATA)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_INITIAL_METADATA", oas);
/* Start new cronet stream. It is destroyed in on_succeeded, on_canceled,
* on_failed */
GPR_ASSERT(s->cbs == NULL);
GPR_ASSERT(!stream_state->state_op_done[OP_SEND_INITIAL_METADATA]);
- s->cbs = bidirectional_stream_create(s->curr_ct.engine, s->curr_gs,
- &cronet_callbacks);
+ s->cbs =
+ bidirectional_stream_create(t->engine, s->curr_gs, &cronet_callbacks);
CRONET_LOG(GPR_DEBUG, "%p = bidirectional_stream_create()", s->cbs);
+ if (t->use_packet_coalescing) {
+ bidirectional_stream_disable_auto_flush(s->cbs, true);
+ bidirectional_stream_delay_request_headers_until_flush(s->cbs, true);
+ }
char *url = NULL;
const char *method = "POST";
s->header_array.headers = NULL;
convert_metadata_to_cronet_headers(
- stream_op->send_initial_metadata->list.head, s->curr_ct.host, &url,
+ stream_op->send_initial_metadata->list.head, t->host, &url,
&s->header_array.headers, &s->header_array.count, &method);
s->header_array.capacity = s->header_array.count;
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, url);
@@ -862,30 +929,16 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
gpr_free((void *)s->header_array.headers[header_index].value);
}
stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true;
- result = ACTION_TAKEN_WITH_CALLBACK;
- } else if (stream_op->recv_initial_metadata &&
- op_can_be_run(stream_op, stream_state, &oas->state,
- OP_RECV_INITIAL_METADATA)) {
- CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_INITIAL_METADATA", oas);
- if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
- grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
- GRPC_ERROR_NONE);
- } else if (stream_state->state_callback_received[OP_FAILED]) {
- grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
- GRPC_ERROR_NONE);
- } else {
- grpc_chttp2_incoming_metadata_buffer_publish(
- exec_ctx, &oas->s->state.rs.initial_metadata,
- stream_op->recv_initial_metadata);
- grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
- GRPC_ERROR_NONE);
+ if (t->use_packet_coalescing) {
+ if (!stream_op->send_message && !stream_op->send_trailing_metadata) {
+ s->state.flush_cronet_when_ready = true;
+ }
}
- stream_state->state_op_done[OP_RECV_INITIAL_METADATA] = true;
- result = ACTION_TAKEN_NO_CALLBACK;
+ result = ACTION_TAKEN_WITH_CALLBACK;
} else if (stream_op->send_message &&
- op_can_be_run(stream_op, stream_state, &oas->state,
- OP_SEND_MESSAGE)) {
+ op_can_be_run(stream_op, s, &oas->state, OP_SEND_MESSAGE)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_MESSAGE", oas);
+ stream_state->pending_send_message = false;
if (stream_state->state_callback_received[OP_FAILED]) {
result = NO_ACTION_POSSIBLE;
CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed.");
@@ -916,16 +969,63 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
bidirectional_stream_write(s->cbs, stream_state->ws.write_buffer,
(int)write_buffer_size, false);
- result = ACTION_TAKEN_WITH_CALLBACK;
+ if (t->use_packet_coalescing) {
+ if (!stream_op->send_trailing_metadata) {
+ CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs);
+ bidirectional_stream_flush(s->cbs);
+ result = ACTION_TAKEN_WITH_CALLBACK;
+ } else {
+ stream_state->pending_write_for_trailer = true;
+ result = ACTION_TAKEN_NO_CALLBACK;
+ }
+ } else {
+ result = ACTION_TAKEN_WITH_CALLBACK;
+ }
} else {
result = NO_ACTION_POSSIBLE;
}
}
stream_state->state_op_done[OP_SEND_MESSAGE] = true;
oas->state.state_op_done[OP_SEND_MESSAGE] = true;
+ } else if (stream_op->send_trailing_metadata &&
+ op_can_be_run(stream_op, s, &oas->state,
+ OP_SEND_TRAILING_METADATA)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_TRAILING_METADATA", oas);
+ if (stream_state->state_callback_received[OP_FAILED]) {
+ result = NO_ACTION_POSSIBLE;
+ CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed.");
+ } else {
+ CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs);
+ stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
+ bidirectional_stream_write(s->cbs, "", 0, true);
+ if (t->use_packet_coalescing) {
+ CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs);
+ bidirectional_stream_flush(s->cbs);
+ }
+ result = ACTION_TAKEN_WITH_CALLBACK;
+ }
+ stream_state->state_op_done[OP_SEND_TRAILING_METADATA] = true;
+ } else if (stream_op->recv_initial_metadata &&
+ op_can_be_run(stream_op, s, &oas->state,
+ OP_RECV_INITIAL_METADATA)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_INITIAL_METADATA", oas);
+ if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
+ grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
+ GRPC_ERROR_NONE);
+ } else if (stream_state->state_callback_received[OP_FAILED]) {
+ grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
+ GRPC_ERROR_NONE);
+ } else {
+ grpc_chttp2_incoming_metadata_buffer_publish(
+ exec_ctx, &oas->s->state.rs.initial_metadata,
+ stream_op->recv_initial_metadata);
+ grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
+ GRPC_ERROR_NONE);
+ }
+ stream_state->state_op_done[OP_RECV_INITIAL_METADATA] = true;
+ result = ACTION_TAKEN_NO_CALLBACK;
} else if (stream_op->recv_message &&
- op_can_be_run(stream_op, stream_state, &oas->state,
- OP_RECV_MESSAGE)) {
+ op_can_be_run(stream_op, s, &oas->state, OP_RECV_MESSAGE)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_MESSAGE", oas);
if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
CRONET_LOG(GPR_DEBUG, "Stream is cancelled.");
@@ -947,6 +1047,13 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
stream_state->state_op_done[OP_RECV_MESSAGE] = true;
oas->state.state_op_done[OP_RECV_MESSAGE] = true;
result = ACTION_TAKEN_NO_CALLBACK;
+ } else if (stream_state->flush_read) {
+ CRONET_LOG(GPR_DEBUG, "flush read");
+ grpc_closure_sched(exec_ctx, stream_op->recv_message_ready,
+ GRPC_ERROR_NONE);
+ stream_state->state_op_done[OP_RECV_MESSAGE] = true;
+ oas->state.state_op_done[OP_RECV_MESSAGE] = true;
+ result = ACTION_TAKEN_NO_CALLBACK;
} else if (stream_state->rs.length_field_received == false) {
if (stream_state->rs.received_bytes == GRPC_HEADER_SIZE_IN_BYTES &&
stream_state->rs.remaining_bytes == 0) {
@@ -967,6 +1074,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
true; /* Indicates that at least one read request has been made */
bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer,
stream_state->rs.remaining_bytes);
+ stream_state->pending_read_from_cronet = true;
result = ACTION_TAKEN_WITH_CALLBACK;
} else {
stream_state->rs.remaining_bytes = 0;
@@ -980,6 +1088,18 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_NONE);
stream_state->state_op_done[OP_RECV_MESSAGE] = true;
oas->state.state_op_done[OP_RECV_MESSAGE] = true;
+
+ /* Extra read to trigger on_succeed */
+ stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes;
+ stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES;
+ stream_state->rs.received_bytes = 0;
+ stream_state->rs.length_field_received = false;
+ CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs);
+ stream_state->state_op_done[OP_READ_REQ_MADE] =
+ true; /* Indicates that at least one read request has been made */
+ bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer,
+ stream_state->rs.remaining_bytes);
+ stream_state->pending_read_from_cronet = true;
result = ACTION_TAKEN_NO_CALLBACK;
}
} else if (stream_state->rs.remaining_bytes == 0) {
@@ -992,6 +1112,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
true; /* Indicates that at least one read request has been made */
bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer,
stream_state->rs.remaining_bytes);
+ stream_state->pending_read_from_cronet = true;
result = ACTION_TAKEN_WITH_CALLBACK;
} else {
result = NO_ACTION_POSSIBLE;
@@ -1003,7 +1124,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
uint8_t *dst_p = GRPC_SLICE_START_PTR(read_data_slice);
memcpy(dst_p, stream_state->rs.read_buffer,
(size_t)stream_state->rs.length_field);
- free_read_buffer(s);
+ null_and_maybe_free_read_buffer(s);
grpc_slice_buffer_init(&stream_state->rs.read_slice_buffer);
grpc_slice_buffer_add(&stream_state->rs.read_slice_buffer,
read_data_slice);
@@ -1024,10 +1145,11 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs);
bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer,
stream_state->rs.remaining_bytes);
+ stream_state->pending_read_from_cronet = true;
result = ACTION_TAKEN_NO_CALLBACK;
}
} else if (stream_op->recv_trailing_metadata &&
- op_can_be_run(stream_op, stream_state, &oas->state,
+ op_can_be_run(stream_op, s, &oas->state,
OP_RECV_TRAILING_METADATA)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_TRAILING_METADATA", oas);
if (oas->s->state.rs.trailing_metadata_valid) {
@@ -1038,23 +1160,8 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
}
stream_state->state_op_done[OP_RECV_TRAILING_METADATA] = true;
result = ACTION_TAKEN_NO_CALLBACK;
- } else if (stream_op->send_trailing_metadata &&
- op_can_be_run(stream_op, stream_state, &oas->state,
- OP_SEND_TRAILING_METADATA)) {
- CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_TRAILING_METADATA", oas);
- if (stream_state->state_callback_received[OP_FAILED]) {
- result = NO_ACTION_POSSIBLE;
- CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed.");
- } else {
- CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs);
- stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
- bidirectional_stream_write(s->cbs, "", 0, true);
- result = ACTION_TAKEN_WITH_CALLBACK;
- }
- stream_state->state_op_done[OP_SEND_TRAILING_METADATA] = true;
} else if (stream_op->cancel_error &&
- op_can_be_run(stream_op, stream_state, &oas->state,
- OP_CANCEL_ERROR)) {
+ op_can_be_run(stream_op, s, &oas->state, OP_CANCEL_ERROR)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_CANCEL_ERROR", oas);
CRONET_LOG(GPR_DEBUG, "W: bidirectional_stream_cancel(%p)", s->cbs);
if (s->cbs) {
@@ -1068,8 +1175,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
stream_state->cancel_error = GRPC_ERROR_REF(stream_op->cancel_error);
}
} else if (stream_op->on_complete &&
- op_can_be_run(stream_op, stream_state, &oas->state,
- OP_ON_COMPLETE)) {
+ op_can_be_run(stream_op, s, &oas->state, OP_ON_COMPLETE)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_ON_COMPLETE", oas);
if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
grpc_closure_sched(exec_ctx, stream_op->on_complete,
@@ -1097,15 +1203,6 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
make a note */
if (stream_op->recv_message)
stream_state->state_op_done[OP_RECV_MESSAGE_AND_ON_COMPLETE] = true;
- } else if (stream_state->fail_state && !stream_state->flush_read) {
- CRONET_LOG(GPR_DEBUG, "running: %p flush read", oas);
- if (stream_state->rs.read_buffer &&
- stream_state->rs.read_buffer != stream_state->rs.grpc_header_bytes) {
- gpr_free(stream_state->rs.read_buffer);
- stream_state->rs.read_buffer = NULL;
- }
- stream_state->rs.read_buffer = gpr_malloc(4096);
- stream_state->flush_read = true;
} else {
result = NO_ACTION_POSSIBLE;
}
@@ -1133,6 +1230,14 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
sizeof(s->state.state_callback_received));
s->state.fail_state = s->state.flush_read = false;
s->state.cancel_error = NULL;
+ s->state.flush_cronet_when_ready = s->state.pending_write_for_trailer = false;
+ s->state.pending_send_message = false;
+ s->state.pending_recv_trailing_metadata = false;
+ s->state.pending_read_from_cronet = false;
+
+ s->curr_gs = gs;
+ s->curr_ct = (grpc_cronet_transport *)gt;
+
gpr_mu_init(&s->mu);
return 0;
}
@@ -1147,39 +1252,30 @@ static void set_pollset_set_do_nothing(grpc_exec_ctx *exec_ctx,
static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_transport_stream_op *op) {
CRONET_LOG(GPR_DEBUG, "perform_stream_op");
- stream_obj *s = (stream_obj *)gs;
- s->curr_gs = gs;
- memcpy(&s->curr_ct, gt, sizeof(grpc_cronet_transport));
- add_to_storage(s, op);
if (op->send_initial_metadata &&
header_has_authority(op->send_initial_metadata->list.head)) {
/* Cronet does not support :authority header field. We cancel the call when
- this field is present in metadata */
- bidirectional_stream_header_array header_array;
- bidirectional_stream_header *header;
- bidirectional_stream cbs;
- CRONET_LOG(GPR_DEBUG,
- ":authority header is provided but not supported;"
- " cancel operations");
- /* Notify application that operation is cancelled by forging trailers */
- header_array.count = 1;
- header_array.capacity = 1;
- header_array.headers = gpr_malloc(sizeof(bidirectional_stream_header));
- header = (bidirectional_stream_header *)header_array.headers;
- header->key = "grpc-status";
- header->value = "1"; /* Return status GRPC_STATUS_CANCELLED */
- cbs.annotation = (void *)s;
- s->state.state_op_done[OP_CANCEL_ERROR] = true;
- on_response_trailers_received(&cbs, &header_array);
- gpr_free(header_array.headers);
- } else {
- execute_from_storage(s);
+ this field is present in metadata */
+ if (op->recv_initial_metadata_ready) {
+ grpc_closure_sched(exec_ctx, op->recv_initial_metadata_ready,
+ GRPC_ERROR_CANCELLED);
+ }
+ if (op->recv_message_ready) {
+ grpc_closure_sched(exec_ctx, op->recv_message_ready,
+ GRPC_ERROR_CANCELLED);
+ }
+ grpc_closure_sched(exec_ctx, op->on_complete, GRPC_ERROR_CANCELLED);
+ return;
}
+ stream_obj *s = (stream_obj *)gs;
+ add_to_storage(s, op);
+ execute_from_storage(s);
}
static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, void *and_free_memory) {
stream_obj *s = (stream_obj *)gs;
+ null_and_maybe_free_read_buffer(s);
GRPC_ERROR_UNREF(s->state.cancel_error);
}
@@ -1197,14 +1293,58 @@ static grpc_endpoint *get_endpoint(grpc_exec_ctx *exec_ctx,
static void perform_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_transport_op *op) {}
-const grpc_transport_vtable grpc_cronet_vtable = {sizeof(stream_obj),
- "cronet_http",
- init_stream,
- set_pollset_do_nothing,
- set_pollset_set_do_nothing,
- perform_stream_op,
- perform_op,
- destroy_stream,
- destroy_transport,
- get_peer,
- get_endpoint};
+static const grpc_transport_vtable grpc_cronet_vtable = {
+ sizeof(stream_obj),
+ "cronet_http",
+ init_stream,
+ set_pollset_do_nothing,
+ set_pollset_set_do_nothing,
+ perform_stream_op,
+ perform_op,
+ destroy_stream,
+ destroy_transport,
+ get_peer,
+ get_endpoint};
+
+grpc_transport *grpc_create_cronet_transport(void *engine, const char *target,
+ const grpc_channel_args *args,
+ void *reserved) {
+ grpc_cronet_transport *ct = gpr_malloc(sizeof(grpc_cronet_transport));
+ if (!ct) {
+ goto error;
+ }
+ ct->base.vtable = &grpc_cronet_vtable;
+ ct->engine = engine;
+ ct->host = gpr_malloc(strlen(target) + 1);
+ if (!ct->host) {
+ goto error;
+ }
+ strcpy(ct->host, target);
+
+ ct->use_packet_coalescing = true;
+ if (args) {
+ for (size_t i = 0; i < args->num_args; i++) {
+ if (0 ==
+ strcmp(args->args[i].key, GRPC_ARG_USE_CRONET_PACKET_COALESCING)) {
+ if (args->args[i].type != GRPC_ARG_INTEGER) {
+ gpr_log(GPR_ERROR, "%s ignored: it must be an integer",
+ GRPC_ARG_USE_CRONET_PACKET_COALESCING);
+ } else {
+ ct->use_packet_coalescing = (args->args[i].value.integer != 0);
+ }
+ }
+ }
+ }
+
+ return &ct->base;
+
+error:
+ if (ct) {
+ if (ct->host) {
+ gpr_free(ct->host);
+ }
+ gpr_free(ct);
+ }
+
+ return NULL;
+}
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.h b/src/core/ext/transport/cronet/transport/cronet_transport.h
new file mode 100644
index 0000000000..169ce31fd7
--- /dev/null
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * Copyright 2016, 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.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_TRANSPORT_H
+#define GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_TRANSPORT_H
+
+#include "src/core/lib/transport/transport.h"
+
+grpc_transport *grpc_create_cronet_transport(void *engine, const char *target,
+ const grpc_channel_args *args,
+ void *reserved);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_TRANSPORT_H */
diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c
index ec973d4e7f..3fb2a60ac7 100644
--- a/src/core/lib/channel/channel_stack.c
+++ b/src/core/lib/channel/channel_stack.c
@@ -173,7 +173,6 @@ grpc_error *grpc_call_stack_init(
grpc_slice path, gpr_timespec start_time, gpr_timespec deadline,
grpc_call_stack *call_stack) {
grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
- grpc_call_element_args args;
size_t count = channel_stack->count;
grpc_call_element *call_elems;
char *user_data;
@@ -188,13 +187,15 @@ grpc_error *grpc_call_stack_init(
/* init per-filter data */
grpc_error *first_error = GRPC_ERROR_NONE;
- args.start_time = start_time;
+ const grpc_call_element_args args = {
+ .start_time = start_time,
+ .call_stack = call_stack,
+ .server_transport_data = transport_server_data,
+ .context = context,
+ .path = path,
+ .deadline = deadline,
+ };
for (i = 0; i < count; i++) {
- args.call_stack = call_stack;
- args.server_transport_data = transport_server_data;
- args.context = context;
- args.path = path;
- args.deadline = deadline;
call_elems[i].filter = channel_elems[i].filter;
call_elems[i].channel_data = channel_elems[i].channel_data;
call_elems[i].call_data = user_data;
diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h
index 1cf07d43c2..6d3340bcbf 100644
--- a/src/core/lib/channel/channel_stack.h
+++ b/src/core/lib/channel/channel_stack.h
@@ -128,10 +128,11 @@ typedef struct {
server_transport_data is an opaque pointer. If it is NULL, this call is
on a client; if it is non-NULL, then it points to memory owned by the
transport and is on the server. Most filters want to ignore this
- argument. */
+ argument.
+ Implementations may assume that elem->call_data is all zeros. */
grpc_error *(*init_call_elem)(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- grpc_call_element_args *args);
+ const grpc_call_element_args *args);
void (*set_pollset_or_pollset_set)(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_polling_entity *pollent);
@@ -152,7 +153,8 @@ typedef struct {
is what needs initializing.
is_first, is_last designate this elements position in the stack, and are
useful for asserting correct configuration by upper layer code.
- The filter does not need to do any chaining */
+ The filter does not need to do any chaining.
+ Implementations may assume that elem->call_data is all zeros. */
grpc_error *(*init_channel_elem)(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
grpc_channel_element_args *args);
diff --git a/src/core/lib/channel/channel_stack_builder.c b/src/core/lib/channel/channel_stack_builder.c
index 5f9e3b4539..b515b7321a 100644
--- a/src/core/lib/channel/channel_stack_builder.c
+++ b/src/core/lib/channel/channel_stack_builder.c
@@ -65,8 +65,7 @@ struct grpc_channel_stack_builder_iterator {
};
grpc_channel_stack_builder *grpc_channel_stack_builder_create(void) {
- grpc_channel_stack_builder *b = gpr_malloc(sizeof(*b));
- memset(b, 0, sizeof(*b));
+ grpc_channel_stack_builder *b = gpr_zalloc(sizeof(*b));
b->begin.filter = NULL;
b->end.filter = NULL;
@@ -251,7 +250,7 @@ grpc_error *grpc_channel_stack_builder_finish(
size_t channel_stack_size = grpc_channel_stack_size(filters, num_filters);
// allocate memory, with prefix_bytes followed by channel_stack_size
- *result = gpr_malloc(prefix_bytes + channel_stack_size);
+ *result = gpr_zalloc(prefix_bytes + channel_stack_size);
// fetch a pointer to the channel stack
grpc_channel_stack *channel_stack =
(grpc_channel_stack *)((char *)(*result) + prefix_bytes);
diff --git a/src/core/lib/channel/compress_filter.c b/src/core/lib/channel/compress_filter.c
index c860d60d88..aa41014a21 100644
--- a/src/core/lib/channel/compress_filter.c
+++ b/src/core/lib/channel/compress_filter.c
@@ -105,7 +105,6 @@ static grpc_error *process_send_initial_metadata(
static grpc_error *process_send_initial_metadata(
grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_metadata_batch *initial_metadata) {
- grpc_error *error;
call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data;
/* Parse incoming request for compression. If any, it'll be available
@@ -144,10 +143,13 @@ static grpc_error *process_send_initial_metadata(
calld->has_compression_algorithm = 1; /* GPR_TRUE */
}
+ grpc_error *error = GRPC_ERROR_NONE;
/* hint compression algorithm */
- error = grpc_metadata_batch_add_tail(
- exec_ctx, initial_metadata, &calld->compression_algorithm_storage,
- grpc_compression_encoding_mdelem(calld->compression_algorithm));
+ if (calld->compression_algorithm != GRPC_COMPRESS_NONE) {
+ error = grpc_metadata_batch_add_tail(
+ exec_ctx, initial_metadata, &calld->compression_algorithm_storage,
+ grpc_compression_encoding_mdelem(calld->compression_algorithm));
+ }
if (error != GRPC_ERROR_NONE) return error;
@@ -272,7 +274,7 @@ static void compress_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
/* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- grpc_call_element_args *args) {
+ const grpc_call_element_args *args) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
diff --git a/src/core/lib/channel/connected_channel.c b/src/core/lib/channel/connected_channel.c
index 068c61c92a..29796f7ca7 100644
--- a/src/core/lib/channel/connected_channel.c
+++ b/src/core/lib/channel/connected_channel.c
@@ -83,7 +83,7 @@ static void con_start_transport_op(grpc_exec_ctx *exec_ctx,
/* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- grpc_call_element_args *args) {
+ const grpc_call_element_args *args) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
int r = grpc_transport_init_stream(
diff --git a/src/core/lib/channel/context.h b/src/core/lib/channel/context.h
index 6c931ad28a..2c1174ce7a 100644
--- a/src/core/lib/channel/context.h
+++ b/src/core/lib/channel/context.h
@@ -50,6 +50,9 @@ typedef enum {
/// Reserved for traffic_class_context.
GRPC_CONTEXT_TRAFFIC,
+ /// Costs for Load Reporting.
+ GRPC_CONTEXT_LR_COST,
+
GRPC_CONTEXT_COUNT
} grpc_context_index;
diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c
index bc9a2effc2..5a12d62f1d 100644
--- a/src/core/lib/channel/deadline_filter.c
+++ b/src/core/lib/channel/deadline_filter.c
@@ -52,9 +52,6 @@ static void timer_callback(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) {
grpc_call_element* elem = arg;
grpc_deadline_state* deadline_state = elem->call_data;
- gpr_mu_lock(&deadline_state->timer_mu);
- deadline_state->timer_pending = false;
- gpr_mu_unlock(&deadline_state->timer_mu);
if (error != GRPC_ERROR_CANCELLED) {
grpc_call_element_signal_error(
exec_ctx, elem,
@@ -66,53 +63,64 @@ static void timer_callback(grpc_exec_ctx* exec_ctx, void* arg,
}
// Starts the deadline timer.
-static void start_timer_if_needed_locked(grpc_exec_ctx* exec_ctx,
- grpc_call_element* elem,
- gpr_timespec deadline) {
- grpc_deadline_state* deadline_state = elem->call_data;
- deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
- // Note: We do not start the timer if there is already a timer
- // pending. This should be okay, because this is only called from two
- // functions exported by this module: grpc_deadline_state_start(), which
- // starts the initial timer, and grpc_deadline_state_reset(), which
- // cancels any pre-existing timer before starting a new one. In
- // particular, we want to ensure that if grpc_deadline_state_start()
- // winds up trying to start the timer after grpc_deadline_state_reset()
- // has already done so, we ignore the value from the former.
- if (!deadline_state->timer_pending &&
- gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) != 0) {
- // Take a reference to the call stack, to be owned by the timer.
- GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer");
- deadline_state->timer_pending = true;
- grpc_closure_init(&deadline_state->timer_callback, timer_callback, elem,
- grpc_schedule_on_exec_ctx);
- grpc_timer_init(exec_ctx, &deadline_state->timer, deadline,
- &deadline_state->timer_callback,
- gpr_now(GPR_CLOCK_MONOTONIC));
- }
-}
static void start_timer_if_needed(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem,
gpr_timespec deadline) {
+ deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
+ if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) == 0) {
+ return;
+ }
grpc_deadline_state* deadline_state = elem->call_data;
- gpr_mu_lock(&deadline_state->timer_mu);
- start_timer_if_needed_locked(exec_ctx, elem, deadline);
- gpr_mu_unlock(&deadline_state->timer_mu);
+ grpc_deadline_timer_state cur_state;
+ grpc_closure* closure = NULL;
+retry:
+ cur_state =
+ (grpc_deadline_timer_state)gpr_atm_acq_load(&deadline_state->timer_state);
+ switch (cur_state) {
+ case GRPC_DEADLINE_STATE_PENDING:
+ // Note: We do not start the timer if there is already a timer
+ return;
+ case GRPC_DEADLINE_STATE_FINISHED:
+ if (gpr_atm_rel_cas(&deadline_state->timer_state,
+ GRPC_DEADLINE_STATE_FINISHED,
+ GRPC_DEADLINE_STATE_PENDING)) {
+ // If we've already created and destroyed a timer, we always create a
+ // new closure: we have no other guarantee that the inlined closure is
+ // not in use (it may hold a pending call to timer_callback)
+ closure = grpc_closure_create(timer_callback, elem,
+ grpc_schedule_on_exec_ctx);
+ } else {
+ goto retry;
+ }
+ break;
+ case GRPC_DEADLINE_STATE_INITIAL:
+ if (gpr_atm_rel_cas(&deadline_state->timer_state,
+ GRPC_DEADLINE_STATE_INITIAL,
+ GRPC_DEADLINE_STATE_PENDING)) {
+ closure =
+ grpc_closure_init(&deadline_state->timer_callback, timer_callback,
+ elem, grpc_schedule_on_exec_ctx);
+ } else {
+ goto retry;
+ }
+ break;
+ }
+ GPR_ASSERT(closure);
+ GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer");
+ grpc_timer_init(exec_ctx, &deadline_state->timer, deadline, closure,
+ gpr_now(GPR_CLOCK_MONOTONIC));
}
// Cancels the deadline timer.
-static void cancel_timer_if_needed_locked(grpc_exec_ctx* exec_ctx,
- grpc_deadline_state* deadline_state) {
- if (deadline_state->timer_pending) {
- grpc_timer_cancel(exec_ctx, &deadline_state->timer);
- deadline_state->timer_pending = false;
- }
-}
static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx,
grpc_deadline_state* deadline_state) {
- gpr_mu_lock(&deadline_state->timer_mu);
- cancel_timer_if_needed_locked(exec_ctx, deadline_state);
- gpr_mu_unlock(&deadline_state->timer_mu);
+ if (gpr_atm_rel_cas(&deadline_state->timer_state, GRPC_DEADLINE_STATE_PENDING,
+ GRPC_DEADLINE_STATE_FINISHED)) {
+ grpc_timer_cancel(exec_ctx, &deadline_state->timer);
+ } else {
+ // timer was either in STATE_INITAL (nothing to cancel)
+ // OR in STATE_FINISHED (again nothing to cancel)
+ }
}
// Callback run when the call is complete.
@@ -120,8 +128,8 @@ static void on_complete(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {
grpc_deadline_state* deadline_state = arg;
cancel_timer_if_needed(exec_ctx, deadline_state);
// Invoke the next callback.
- deadline_state->next_on_complete->cb(
- exec_ctx, deadline_state->next_on_complete->cb_arg, error);
+ grpc_closure_run(exec_ctx, deadline_state->next_on_complete,
+ GRPC_ERROR_REF(error));
}
// Inject our own on_complete callback into op.
@@ -136,16 +144,13 @@ static void inject_on_complete_cb(grpc_deadline_state* deadline_state,
void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
grpc_call_stack* call_stack) {
grpc_deadline_state* deadline_state = elem->call_data;
- memset(deadline_state, 0, sizeof(*deadline_state));
deadline_state->call_stack = call_stack;
- gpr_mu_init(&deadline_state->timer_mu);
}
void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem) {
grpc_deadline_state* deadline_state = elem->call_data;
cancel_timer_if_needed(exec_ctx, deadline_state);
- gpr_mu_destroy(&deadline_state->timer_mu);
}
// Callback and associated state for starting the timer after call stack
@@ -187,10 +192,8 @@ void grpc_deadline_state_start(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
gpr_timespec new_deadline) {
grpc_deadline_state* deadline_state = elem->call_data;
- gpr_mu_lock(&deadline_state->timer_mu);
- cancel_timer_if_needed_locked(exec_ctx, deadline_state);
- start_timer_if_needed_locked(exec_ctx, elem, new_deadline);
- gpr_mu_unlock(&deadline_state->timer_mu);
+ cancel_timer_if_needed(exec_ctx, deadline_state);
+ start_timer_if_needed(exec_ctx, elem, new_deadline);
}
void grpc_deadline_state_client_start_transport_stream_op(
@@ -244,9 +247,7 @@ typedef struct server_call_data {
// Constructor for call_data. Used for both client and server filters.
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem,
- grpc_call_element_args* args) {
- // Note: size of call data is different between client and server.
- memset(elem->call_data, 0, elem->filter->sizeof_call_data);
+ const grpc_call_element_args* args) {
grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
grpc_deadline_state_start(exec_ctx, elem, args->deadline);
return GRPC_ERROR_NONE;
diff --git a/src/core/lib/channel/deadline_filter.h b/src/core/lib/channel/deadline_filter.h
index bd2b84f79e..72cd5cb929 100644
--- a/src/core/lib/channel/deadline_filter.h
+++ b/src/core/lib/channel/deadline_filter.h
@@ -35,16 +35,18 @@
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/iomgr/timer.h"
+typedef enum grpc_deadline_timer_state {
+ GRPC_DEADLINE_STATE_INITIAL,
+ GRPC_DEADLINE_STATE_PENDING,
+ GRPC_DEADLINE_STATE_FINISHED
+} grpc_deadline_timer_state;
+
// State used for filters that enforce call deadlines.
// Must be the first field in the filter's call_data.
typedef struct grpc_deadline_state {
// We take a reference to the call stack for the timer callback.
grpc_call_stack* call_stack;
- // Guards access to timer_pending and timer.
- gpr_mu timer_mu;
- // True if the timer callback is currently pending.
- bool timer_pending;
- // The deadline timer.
+ gpr_atm timer_state;
grpc_timer timer;
grpc_closure timer_callback;
// Closure to invoke when the call is complete.
@@ -60,6 +62,7 @@ typedef struct grpc_deadline_state {
// elem->call_data is a grpc_deadline_state.
//
+// assumes elem->call_data is zero'd
void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
grpc_call_stack* call_stack);
void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx,
diff --git a/src/core/lib/channel/handshaker.c b/src/core/lib/channel/handshaker.c
index 5bed2d041d..1b4240bb10 100644
--- a/src/core/lib/channel/handshaker.c
+++ b/src/core/lib/channel/handshaker.c
@@ -92,16 +92,52 @@ struct grpc_handshake_manager {
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;
};
grpc_handshake_manager* grpc_handshake_manager_create() {
- grpc_handshake_manager* mgr = gpr_malloc(sizeof(grpc_handshake_manager));
- memset(mgr, 0, sizeof(*mgr));
+ grpc_handshake_manager* mgr = 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 == NULL);
+ GPR_ASSERT(mgr->next == NULL);
+ mgr->next = *head;
+ if (*head) {
+ (*head)->prev = mgr;
+ }
+ *head = mgr;
+}
+
+void grpc_handshake_manager_pending_list_remove(grpc_handshake_manager** head,
+ grpc_handshake_manager* mgr) {
+ if (mgr->next != NULL) {
+ mgr->next->prev = mgr->prev;
+ }
+ if (mgr->prev != NULL) {
+ mgr->prev->next = mgr->next;
+ } else {
+ GPR_ASSERT(*head == mgr);
+ *head = mgr->next;
+ }
+}
+
+void grpc_handshake_manager_pending_list_shutdown_all(
+ grpc_exec_ctx* exec_ctx, grpc_handshake_manager* head, grpc_error* why) {
+ while (head != NULL) {
+ grpc_handshake_manager_shutdown(exec_ctx, head, 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,
diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h
index a8e3692add..5f97c3fc73 100644
--- a/src/core/lib/channel/handshaker.h
+++ b/src/core/lib/channel/handshaker.h
@@ -163,4 +163,20 @@ void grpc_handshake_manager_do_handshake(
gpr_timespec 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_exec_ctx* exec_ctx, grpc_handshake_manager* head, grpc_error* why);
+
#endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H */
diff --git a/src/core/lib/channel/http_client_filter.c b/src/core/lib/channel/http_client_filter.c
index 49a2a980e0..c031533dd8 100644
--- a/src/core/lib/channel/http_client_filter.c
+++ b/src/core/lib/channel/http_client_filter.c
@@ -386,7 +386,7 @@ static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
/* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- grpc_call_element_args *args) {
+ const grpc_call_element_args *args) {
call_data *calld = elem->call_data;
calld->on_done_recv_initial_metadata = NULL;
calld->on_done_recv_trailing_metadata = NULL;
diff --git a/src/core/lib/channel/http_server_filter.c b/src/core/lib/channel/http_server_filter.c
index 3f992977c0..fb70de8e96 100644
--- a/src/core/lib/channel/http_server_filter.c
+++ b/src/core/lib/channel/http_server_filter.c
@@ -198,14 +198,17 @@ static grpc_error *server_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_STR_KEY, ":path"));
}
- if (b->idx.named.host != NULL) {
+ if (b->idx.named.host != NULL && b->idx.named.authority == NULL) {
+ grpc_linked_mdelem *el = b->idx.named.host;
+ grpc_mdelem md = GRPC_MDELEM_REF(el->md);
+ grpc_metadata_batch_remove(exec_ctx, b, el);
add_error(
error_name, &error,
- grpc_metadata_batch_substitute(
- exec_ctx, b, b->idx.named.host,
- grpc_mdelem_from_slices(
- exec_ctx, GRPC_MDSTR_AUTHORITY,
- grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.host->md)))));
+ grpc_metadata_batch_add_head(
+ exec_ctx, b, el, grpc_mdelem_from_slices(
+ exec_ctx, GRPC_MDSTR_AUTHORITY,
+ grpc_slice_ref_internal(GRPC_MDVALUE(md)))));
+ GRPC_MDELEM_UNREF(exec_ctx, md);
}
if (b->idx.named.authority == NULL) {
@@ -249,12 +252,11 @@ static void hs_on_complete(grpc_exec_ctx *exec_ctx, void *user_data,
*calld->pp_recv_message = calld->payload_bin_delivered
? NULL
: (grpc_byte_stream *)&calld->read_stream;
- calld->recv_message_ready->cb(exec_ctx, calld->recv_message_ready->cb_arg,
- err);
+ grpc_closure_run(exec_ctx, calld->recv_message_ready, GRPC_ERROR_REF(err));
calld->recv_message_ready = NULL;
calld->payload_bin_delivered = true;
}
- calld->on_complete->cb(exec_ctx, calld->on_complete->cb_arg, err);
+ grpc_closure_run(exec_ctx, calld->on_complete, GRPC_ERROR_REF(err));
}
static void hs_recv_message_ready(grpc_exec_ctx *exec_ctx, void *user_data,
@@ -265,8 +267,7 @@ static void hs_recv_message_ready(grpc_exec_ctx *exec_ctx, void *user_data,
/* do nothing. This is probably a GET request, and payload will be returned
in hs_on_complete callback. */
} else {
- calld->recv_message_ready->cb(exec_ctx, calld->recv_message_ready->cb_arg,
- err);
+ grpc_closure_run(exec_ctx, calld->recv_message_ready, GRPC_ERROR_REF(err));
}
}
@@ -340,11 +341,10 @@ static void hs_start_transport_op(grpc_exec_ctx *exec_ctx,
/* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- grpc_call_element_args *args) {
+ const grpc_call_element_args *args) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
/* initialize members */
- memset(calld, 0, sizeof(*calld));
grpc_closure_init(&calld->hs_on_recv, hs_on_recv, elem,
grpc_schedule_on_exec_ctx);
grpc_closure_init(&calld->hs_on_complete, hs_on_complete, elem,
diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c
index 5e22860cfb..b424c0d2ac 100644
--- a/src/core/lib/channel/message_size_filter.c
+++ b/src/core/lib/channel/message_size_filter.c
@@ -166,7 +166,7 @@ static void start_transport_stream_op(grpc_exec_ctx* exec_ctx,
// Constructor for call_data.
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem,
- grpc_call_element_args* args) {
+ const grpc_call_element_args* args) {
channel_data* chand = elem->channel_data;
call_data* calld = elem->call_data;
calld->next_recv_message_ready = NULL;
@@ -208,7 +208,6 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
grpc_channel_element_args* args) {
GPR_ASSERT(!args->is_last);
channel_data* chand = elem->channel_data;
- memset(chand, 0, sizeof(*chand));
chand->max_send_size = GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH;
chand->max_recv_size = GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH;
for (size_t i = 0; i < args->channel_args->num_args; ++i) {
diff --git a/src/core/lib/http/httpcli.c b/src/core/lib/http/httpcli.c
index fb2108987b..6d7aa43b81 100644
--- a/src/core/lib/http/httpcli.c
+++ b/src/core/lib/http/httpcli.c
@@ -93,8 +93,9 @@ void grpc_httpcli_context_init(grpc_httpcli_context *context) {
context->pollset_set = grpc_pollset_set_create();
}
-void grpc_httpcli_context_destroy(grpc_httpcli_context *context) {
- grpc_pollset_set_destroy(context->pollset_set);
+void grpc_httpcli_context_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_httpcli_context *context) {
+ grpc_pollset_set_destroy(exec_ctx, context->pollset_set);
}
static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req,
diff --git a/src/core/lib/http/httpcli.h b/src/core/lib/http/httpcli.h
index 11e03b44df..8ae03ee78f 100644
--- a/src/core/lib/http/httpcli.h
+++ b/src/core/lib/http/httpcli.h
@@ -83,7 +83,8 @@ typedef struct grpc_httpcli_request {
typedef struct grpc_http_response grpc_httpcli_response;
void grpc_httpcli_context_init(grpc_httpcli_context *context);
-void grpc_httpcli_context_destroy(grpc_httpcli_context *context);
+void grpc_httpcli_context_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_httpcli_context *context);
/* Asynchronously perform a HTTP GET.
'context' specifies the http context under which to do the get
diff --git a/src/core/lib/http/httpcli_security_connector.c b/src/core/lib/http/httpcli_security_connector.c
index f4f6f3c27a..354d2f4a09 100644
--- a/src/core/lib/http/httpcli_security_connector.c
+++ b/src/core/lib/http/httpcli_security_connector.c
@@ -118,8 +118,7 @@ static grpc_security_status httpcli_ssl_channel_security_connector_create(
return GRPC_SECURITY_ERROR;
}
- c = gpr_malloc(sizeof(grpc_httpcli_ssl_channel_security_connector));
- memset(c, 0, sizeof(grpc_httpcli_ssl_channel_security_connector));
+ c = gpr_zalloc(sizeof(grpc_httpcli_ssl_channel_security_connector));
gpr_ref_init(&c->base.base.refcount, 1);
c->base.base.vtable = &httpcli_ssl_vtable;
diff --git a/src/core/lib/http/parser.c b/src/core/lib/http/parser.c
index 2f84adc187..b9c56c103c 100644
--- a/src/core/lib/http/parser.c
+++ b/src/core/lib/http/parser.c
@@ -284,9 +284,9 @@ static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte,
case GRPC_HTTP_HEADERS:
if (parser->cur_line_length >= GRPC_HTTP_PARSER_MAX_HEADER_LENGTH) {
if (grpc_http1_trace)
- gpr_log(GPR_ERROR, "HTTP client max line length (%d) exceeded",
+ gpr_log(GPR_ERROR, "HTTP header max line length (%d) exceeded",
GRPC_HTTP_PARSER_MAX_HEADER_LENGTH);
- return GRPC_ERROR_NONE;
+ return GRPC_ERROR_CREATE("HTTP header max line length exceeded");
}
parser->cur_line[parser->cur_line_length] = byte;
parser->cur_line_length++;
diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c
index ba6c7087a9..fa9966c3a6 100644
--- a/src/core/lib/iomgr/combiner.c
+++ b/src/core/lib/iomgr/combiner.c
@@ -72,6 +72,7 @@ struct grpc_combiner {
bool final_list_covered_by_poller;
grpc_closure_list final_list;
grpc_closure offload;
+ gpr_refcount refs;
};
static void combiner_exec_uncovered(grpc_exec_ctx *exec_ctx,
@@ -126,6 +127,7 @@ static bool is_covered_by_poller(grpc_combiner *lock) {
grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) {
grpc_combiner *lock = gpr_malloc(sizeof(*lock));
+ gpr_ref_init(&lock->refs, 1);
lock->next_combiner_on_this_exec_ctx = NULL;
lock->time_to_execute_final_list = false;
lock->optional_workqueue = optional_workqueue;
@@ -152,7 +154,7 @@ static void really_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
gpr_free(lock);
}
-void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
+static void start_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -STATE_UNORPHANED);
GRPC_COMBINER_TRACE(gpr_log(
GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state));
@@ -161,6 +163,30 @@ void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) {
}
}
+#ifdef GRPC_COMBINER_REFCOUNT_DEBUG
+#define GRPC_COMBINER_DEBUG_SPAM(op, delta) \
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, \
+ "combiner[%p] %s %" PRIdPTR " --> %" PRIdPTR " %s", lock, (op), \
+ gpr_atm_no_barrier_load(&lock->refs.count), \
+ gpr_atm_no_barrier_load(&lock->refs.count) + (delta), reason);
+#else
+#define GRPC_COMBINER_DEBUG_SPAM(op, delta)
+#endif
+
+void grpc_combiner_unref(grpc_exec_ctx *exec_ctx,
+ grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS) {
+ GRPC_COMBINER_DEBUG_SPAM("UNREF", -1);
+ if (gpr_unref(&lock->refs)) {
+ start_destroy(exec_ctx, lock);
+ }
+}
+
+grpc_combiner *grpc_combiner_ref(grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS) {
+ GRPC_COMBINER_DEBUG_SPAM(" REF", 1);
+ gpr_ref(&lock->refs);
+ return lock;
+}
+
static void push_last_on_exec_ctx(grpc_exec_ctx *exec_ctx,
grpc_combiner *lock) {
lock->next_combiner_on_this_exec_ctx = NULL;
diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h
index 81dff85d40..75dcb0b70a 100644
--- a/src/core/lib/iomgr/combiner.h
+++ b/src/core/lib/iomgr/combiner.h
@@ -48,8 +48,27 @@
// Initialize the lock, with an optional workqueue to shift load to when
// necessary
grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue);
-// Destroy the lock
-void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock);
+
+//#define GRPC_COMBINER_REFCOUNT_DEBUG
+#ifdef GRPC_COMBINER_REFCOUNT_DEBUG
+#define GRPC_COMBINER_DEBUG_ARGS \
+ , const char *file, int line, const char *reason
+#define GRPC_COMBINER_REF(combiner, reason) \
+ grpc_combiner_ref((combiner), __FILE__, __LINE__, (reason))
+#define GRPC_COMBINER_UNREF(exec_ctx, combiner, reason) \
+ grpc_combiner_unref((exec_ctx), (combiner), __FILE__, __LINE__, (reason))
+#else
+#define GRPC_COMBINER_DEBUG_ARGS
+#define GRPC_COMBINER_REF(combiner, reason) grpc_combiner_ref((combiner))
+#define GRPC_COMBINER_UNREF(exec_ctx, combiner, reason) \
+ grpc_combiner_unref((exec_ctx), (combiner))
+#endif
+
+// Ref/unref the lock, for when we're sharing the lock ownership
+// Prefer to use the macros above
+grpc_combiner *grpc_combiner_ref(grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS);
+void grpc_combiner_unref(grpc_exec_ctx *exec_ctx,
+ grpc_combiner *lock GRPC_COMBINER_DEBUG_ARGS);
// Fetch a scheduler to schedule closures against
grpc_closure_scheduler *grpc_combiner_scheduler(grpc_combiner *lock,
bool covered_by_poller);
diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c
index dbe5b139f9..7cdbe30198 100644
--- a/src/core/lib/iomgr/error.c
+++ b/src/core/lib/iomgr/error.c
@@ -35,6 +35,7 @@
#include <string.h>
+#include <grpc/slice.h>
#include <grpc/status.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@@ -47,46 +48,7 @@
#include "src/core/lib/iomgr/error_internal.h"
#include "src/core/lib/profiling/timers.h"
-
-static void destroy_integer(void *key) {}
-
-static void *copy_integer(void *key) { return key; }
-
-static long compare_integers(void *key1, void *key2) {
- return GPR_ICMP((uintptr_t)key1, (uintptr_t)key2);
-}
-
-static void destroy_string(void *str) { gpr_free(str); }
-
-static void *copy_string(void *str) { return gpr_strdup(str); }
-
-static void destroy_err(void *err) { GRPC_ERROR_UNREF(err); }
-
-static void *copy_err(void *err) { return GRPC_ERROR_REF(err); }
-
-static void destroy_time(void *tm) { gpr_free(tm); }
-
-static gpr_timespec *box_time(gpr_timespec tm) {
- gpr_timespec *out = gpr_malloc(sizeof(*out));
- *out = tm;
- return out;
-}
-
-static void *copy_time(void *tm) { return box_time(*(gpr_timespec *)tm); }
-
-static const gpr_avl_vtable avl_vtable_ints = {destroy_integer, copy_integer,
- compare_integers,
- destroy_integer, copy_integer};
-
-static const gpr_avl_vtable avl_vtable_strs = {destroy_integer, copy_integer,
- compare_integers, destroy_string,
- copy_string};
-
-static const gpr_avl_vtable avl_vtable_times = {
- destroy_integer, copy_integer, compare_integers, destroy_time, copy_time};
-
-static const gpr_avl_vtable avl_vtable_errs = {
- destroy_integer, copy_integer, compare_integers, destroy_err, copy_err};
+#include "src/core/lib/slice/slice_internal.h"
static const char *error_int_name(grpc_error_ints key) {
switch (key) {
@@ -120,6 +82,8 @@ static const char *error_int_name(grpc_error_ints key) {
return "limit";
case GRPC_ERROR_INT_OCCURRED_DURING_WRITE:
return "occurred_during_write";
+ case GRPC_ERROR_INT_MAX:
+ GPR_UNREACHABLE_CODE(return "unknown");
}
GPR_UNREACHABLE_CODE(return "unknown");
}
@@ -150,6 +114,8 @@ static const char *error_str_name(grpc_error_strs key) {
return "filename";
case GRPC_ERROR_STR_QUEUED_BUFFERS:
return "queued_buffers";
+ case GRPC_ERROR_STR_MAX:
+ GPR_UNREACHABLE_CODE(return "unknown");
}
GPR_UNREACHABLE_CODE(return "unknown");
}
@@ -158,6 +124,8 @@ static const char *error_time_name(grpc_error_times key) {
switch (key) {
case GRPC_ERROR_TIME_CREATED:
return "created";
+ case GRPC_ERROR_TIME_MAX:
+ GPR_UNREACHABLE_CODE(return "unknown");
}
GPR_UNREACHABLE_CODE(return "unknown");
}
@@ -184,12 +152,36 @@ grpc_error *grpc_error_ref(grpc_error *err) {
}
#endif
+static void unref_errs(grpc_error *err) {
+ uint8_t slot = err->first_err;
+ while (slot != UINT8_MAX) {
+ grpc_linked_error *lerr = (grpc_linked_error *)(err->arena + slot);
+ GRPC_ERROR_UNREF(lerr->err);
+ GPR_ASSERT(err->last_err == slot ? lerr->next == UINT8_MAX
+ : lerr->next != UINT8_MAX);
+ slot = lerr->next;
+ }
+}
+
+static void unref_slice(grpc_slice slice) {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_slice_unref_internal(&exec_ctx, slice);
+ grpc_exec_ctx_finish(&exec_ctx);
+}
+
+static void unref_strs(grpc_error *err) {
+ for (size_t which = 0; which < GRPC_ERROR_STR_MAX; ++which) {
+ uint8_t slot = err->strs[which];
+ if (slot != UINT8_MAX) {
+ unref_slice(*(grpc_slice *)(err->arena + slot));
+ }
+ }
+}
+
static void error_destroy(grpc_error *err) {
GPR_ASSERT(!grpc_error_is_special(err));
- gpr_avl_unref(err->ints);
- gpr_avl_unref(err->strs);
- gpr_avl_unref(err->errs);
- gpr_avl_unref(err->times);
+ unref_errs(err);
+ unref_strs(err);
gpr_free((void *)gpr_atm_acq_load(&err->error_string));
gpr_free(err);
}
@@ -213,67 +205,189 @@ void grpc_error_unref(grpc_error *err) {
}
#endif
+static uint8_t get_placement(grpc_error **err, size_t size) {
+ GPR_ASSERT(*err);
+ uint8_t slots = (uint8_t)(size / sizeof(intptr_t));
+ if ((*err)->arena_size + slots > (*err)->arena_capacity) {
+ (*err)->arena_capacity = (uint8_t)(3 * (*err)->arena_capacity / 2);
+ *err = gpr_realloc(
+ *err, sizeof(grpc_error) + (*err)->arena_capacity * sizeof(intptr_t));
+ }
+ uint8_t placement = (*err)->arena_size;
+ (*err)->arena_size = (uint8_t)((*err)->arena_size + slots);
+ return placement;
+}
+
+static void internal_set_int(grpc_error **err, grpc_error_ints which,
+ intptr_t value) {
+ // GPR_ASSERT((*err)->ints[which] == UINT8_MAX); // TODO, enforce this
+ uint8_t slot = (*err)->ints[which];
+ if (slot == UINT8_MAX) {
+ slot = get_placement(err, sizeof(value));
+ }
+ (*err)->ints[which] = slot;
+ (*err)->arena[slot] = value;
+}
+
+static void internal_set_str(grpc_error **err, grpc_error_strs which,
+ grpc_slice value) {
+ // GPR_ASSERT((*err)->strs[which] == UINT8_MAX); // TODO, enforce this
+ uint8_t slot = (*err)->strs[which];
+ if (slot == UINT8_MAX) {
+ slot = get_placement(err, sizeof(value));
+ } else {
+ unref_slice(*(grpc_slice *)((*err)->arena + slot));
+ }
+ (*err)->strs[which] = slot;
+ memcpy((*err)->arena + slot, &value, sizeof(value));
+}
+
+static void internal_set_time(grpc_error **err, grpc_error_times which,
+ gpr_timespec value) {
+ // GPR_ASSERT((*err)->times[which] == UINT8_MAX); // TODO, enforce this
+ uint8_t slot = (*err)->times[which];
+ if (slot == UINT8_MAX) {
+ slot = get_placement(err, sizeof(value));
+ }
+ (*err)->times[which] = slot;
+ memcpy((*err)->arena + slot, &value, sizeof(value));
+}
+
+static void internal_add_error(grpc_error **err, grpc_error *new) {
+ grpc_linked_error new_last = {new, UINT8_MAX};
+ uint8_t slot = get_placement(err, sizeof(grpc_linked_error));
+ if ((*err)->first_err == UINT8_MAX) {
+ GPR_ASSERT((*err)->last_err == UINT8_MAX);
+ (*err)->last_err = slot;
+ (*err)->first_err = slot;
+ } else {
+ GPR_ASSERT((*err)->last_err != UINT8_MAX);
+ grpc_linked_error *old_last =
+ (grpc_linked_error *)((*err)->arena + (*err)->last_err);
+ old_last->next = slot;
+ (*err)->last_err = slot;
+ }
+ memcpy((*err)->arena + slot, &new_last, sizeof(grpc_linked_error));
+}
+
+#define SLOTS_PER_INT (sizeof(intptr_t) / sizeof(intptr_t))
+#define SLOTS_PER_STR (sizeof(grpc_slice) / sizeof(intptr_t))
+#define SLOTS_PER_TIME (sizeof(gpr_timespec) / sizeof(intptr_t))
+#define SLOTS_PER_LINKED_ERROR (sizeof(grpc_linked_error) / sizeof(intptr_t))
+
+// size of storing one int and two slices and a timespec. For line, desc, file,
+// and time created
+#define DEFAULT_ERROR_CAPACITY \
+ (SLOTS_PER_INT + (SLOTS_PER_STR * 2) + SLOTS_PER_TIME)
+
+// It is very common to include and extra int and string in an error
+#define SURPLUS_CAPACITY (2 * SLOTS_PER_INT + SLOTS_PER_TIME)
+
grpc_error *grpc_error_create(const char *file, int line, const char *desc,
grpc_error **referencing,
size_t num_referencing) {
GPR_TIMER_BEGIN("grpc_error_create", 0);
- grpc_error *err = gpr_malloc(sizeof(*err));
+ uint8_t initial_arena_capacity = (uint8_t)(
+ DEFAULT_ERROR_CAPACITY +
+ (uint8_t)(num_referencing * SLOTS_PER_LINKED_ERROR) + SURPLUS_CAPACITY);
+ grpc_error *err =
+ gpr_malloc(sizeof(*err) + initial_arena_capacity * sizeof(intptr_t));
if (err == NULL) { // TODO(ctiller): make gpr_malloc return NULL
return GRPC_ERROR_OOM;
}
#ifdef GRPC_ERROR_REFCOUNT_DEBUG
gpr_log(GPR_DEBUG, "%p create [%s:%d]", err, file, line);
#endif
- err->ints = gpr_avl_add(gpr_avl_create(&avl_vtable_ints),
- (void *)(uintptr_t)GRPC_ERROR_INT_FILE_LINE,
- (void *)(uintptr_t)line);
- err->strs = gpr_avl_add(
- gpr_avl_add(gpr_avl_create(&avl_vtable_strs),
- (void *)(uintptr_t)GRPC_ERROR_STR_FILE, gpr_strdup(file)),
- (void *)(uintptr_t)GRPC_ERROR_STR_DESCRIPTION, gpr_strdup(desc));
- err->errs = gpr_avl_create(&avl_vtable_errs);
- err->next_err = 0;
- for (size_t i = 0; i < num_referencing; i++) {
+
+ err->arena_size = 0;
+ err->arena_capacity = initial_arena_capacity;
+ err->first_err = UINT8_MAX;
+ err->last_err = UINT8_MAX;
+
+ memset(err->ints, UINT8_MAX, GRPC_ERROR_INT_MAX);
+ memset(err->strs, UINT8_MAX, GRPC_ERROR_STR_MAX);
+ memset(err->times, UINT8_MAX, GRPC_ERROR_TIME_MAX);
+
+ internal_set_int(&err, GRPC_ERROR_INT_FILE_LINE, line);
+ internal_set_str(&err, GRPC_ERROR_STR_FILE,
+ grpc_slice_from_static_string(file));
+ internal_set_str(
+ &err, GRPC_ERROR_STR_DESCRIPTION,
+ grpc_slice_from_copied_buffer(
+ desc,
+ strlen(desc) +
+ 1)); // TODO, pull this up. // TODO(ncteisen), pull this up.
+
+ for (size_t i = 0; i < num_referencing; ++i) {
if (referencing[i] == GRPC_ERROR_NONE) continue;
- err->errs = gpr_avl_add(err->errs, (void *)(err->next_err++),
- GRPC_ERROR_REF(referencing[i]));
+ internal_add_error(
+ &err,
+ GRPC_ERROR_REF(
+ referencing[i])); // TODO(ncteisen), change ownership semantics
}
- err->times = gpr_avl_add(gpr_avl_create(&avl_vtable_times),
- (void *)(uintptr_t)GRPC_ERROR_TIME_CREATED,
- box_time(gpr_now(GPR_CLOCK_REALTIME)));
+
+ internal_set_time(&err, GRPC_ERROR_TIME_CREATED, gpr_now(GPR_CLOCK_REALTIME));
+
gpr_atm_no_barrier_store(&err->error_string, 0);
gpr_ref_init(&err->refs, 1);
GPR_TIMER_END("grpc_error_create", 0);
return err;
}
+static void ref_strs(grpc_error *err) {
+ for (size_t i = 0; i < GRPC_ERROR_STR_MAX; ++i) {
+ uint8_t slot = err->strs[i];
+ if (slot != UINT8_MAX) {
+ grpc_slice_ref_internal(*(grpc_slice *)(err->arena + slot));
+ }
+ }
+}
+
+static void ref_errs(grpc_error *err) {
+ uint8_t slot = err->first_err;
+ while (slot != UINT8_MAX) {
+ grpc_linked_error *lerr = (grpc_linked_error *)(err->arena + slot);
+ GRPC_ERROR_REF(lerr->err);
+ slot = lerr->next;
+ }
+}
+
static grpc_error *copy_error_and_unref(grpc_error *in) {
GPR_TIMER_BEGIN("copy_error_and_unref", 0);
grpc_error *out;
if (grpc_error_is_special(in)) {
- if (in == GRPC_ERROR_NONE)
- out = grpc_error_set_int(GRPC_ERROR_CREATE("no error"),
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK);
- else if (in == GRPC_ERROR_OOM)
- out = GRPC_ERROR_CREATE("oom");
- else if (in == GRPC_ERROR_CANCELLED)
- out =
- grpc_error_set_int(GRPC_ERROR_CREATE("cancelled"),
- GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_CANCELLED);
- else
- out = GRPC_ERROR_CREATE("unknown");
+ out = GRPC_ERROR_CREATE("unknown");
+ if (in == GRPC_ERROR_NONE) {
+ internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION,
+ grpc_slice_from_static_string("no error"));
+ internal_set_int(&out, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_OK);
+ } else if (in == GRPC_ERROR_OOM) {
+ internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION,
+ grpc_slice_from_static_string("oom"));
+ } else if (in == GRPC_ERROR_CANCELLED) {
+ internal_set_str(&out, GRPC_ERROR_STR_DESCRIPTION,
+ grpc_slice_from_static_string("cancelled"));
+ internal_set_int(&out, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_CANCELLED);
+ }
+ } else if (gpr_ref_is_unique(&in->refs)) {
+ out = in;
} else {
- out = gpr_malloc(sizeof(*out));
+ uint8_t new_arena_capacity = in->arena_capacity;
+ // the returned err will be added to, so we ensure this is room to avoid
+ // unneeded allocations.
+ if (in->arena_capacity - in->arena_size < (uint8_t)SLOTS_PER_STR) {
+ new_arena_capacity = (uint8_t)(3 * new_arena_capacity / 2);
+ }
+ out = gpr_malloc(sizeof(*in) + new_arena_capacity * sizeof(intptr_t));
#ifdef GRPC_ERROR_REFCOUNT_DEBUG
gpr_log(GPR_DEBUG, "%p create copying %p", out, in);
#endif
- out->ints = gpr_avl_ref(in->ints);
- out->strs = gpr_avl_ref(in->strs);
- out->errs = gpr_avl_ref(in->errs);
- out->times = gpr_avl_ref(in->times);
+ memcpy(out, in, sizeof(*in) + in->arena_size * sizeof(intptr_t));
+ out->arena_capacity = new_arena_capacity;
gpr_atm_no_barrier_store(&out->error_string, 0);
- out->next_err = in->next_err;
gpr_ref_init(&out->refs, 1);
+ ref_strs(out);
+ ref_errs(out);
GRPC_ERROR_UNREF(in);
}
GPR_TIMER_END("copy_error_and_unref", 0);
@@ -284,7 +398,7 @@ grpc_error *grpc_error_set_int(grpc_error *src, grpc_error_ints which,
intptr_t value) {
GPR_TIMER_BEGIN("grpc_error_set_int", 0);
grpc_error *new = copy_error_and_unref(src);
- new->ints = gpr_avl_add(new->ints, (void *)(uintptr_t)which, (void *)value);
+ internal_set_int(&new, which, value);
GPR_TIMER_END("grpc_error_set_int", 0);
return new;
}
@@ -302,7 +416,6 @@ static special_error_status_map error_status_map[] = {
bool grpc_error_get_int(grpc_error *err, grpc_error_ints which, intptr_t *p) {
GPR_TIMER_BEGIN("grpc_error_get_int", 0);
- void *pp;
if (grpc_error_is_special(err)) {
if (which == GRPC_ERROR_INT_GRPC_STATUS) {
for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
@@ -316,8 +429,9 @@ bool grpc_error_get_int(grpc_error *err, grpc_error_ints which, intptr_t *p) {
GPR_TIMER_END("grpc_error_get_int", 0);
return false;
}
- if (gpr_avl_maybe_get(err->ints, (void *)(uintptr_t)which, &pp)) {
- if (p != NULL) *p = (intptr_t)pp;
+ uint8_t slot = err->ints[which];
+ if (slot != UINT8_MAX) {
+ if (p != NULL) *p = err->arena[slot];
GPR_TIMER_END("grpc_error_get_int", 0);
return true;
}
@@ -329,8 +443,9 @@ grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which,
const char *value) {
GPR_TIMER_BEGIN("grpc_error_set_str", 0);
grpc_error *new = copy_error_and_unref(src);
- new->strs =
- gpr_avl_add(new->strs, (void *)(uintptr_t)which, gpr_strdup(value));
+ internal_set_str(&new, which,
+ grpc_slice_from_copied_buffer(
+ value, strlen(value) + 1)); // TODO, pull this up.
GPR_TIMER_END("grpc_error_set_str", 0);
return new;
}
@@ -346,13 +461,19 @@ const char *grpc_error_get_str(grpc_error *err, grpc_error_strs which) {
}
return NULL;
}
- return gpr_avl_get(err->strs, (void *)(uintptr_t)which);
+ uint8_t slot = err->strs[which];
+ if (slot != UINT8_MAX) {
+ return (const char *)GRPC_SLICE_START_PTR(
+ *(grpc_slice *)(err->arena + slot));
+ } else {
+ return NULL;
+ }
}
grpc_error *grpc_error_add_child(grpc_error *src, grpc_error *child) {
GPR_TIMER_BEGIN("grpc_error_add_child", 0);
grpc_error *new = copy_error_and_unref(src);
- new->errs = gpr_avl_add(new->errs, (void *)(new->next_err++), child);
+ internal_add_error(&new, child);
GPR_TIMER_END("grpc_error_add_child", 0);
return new;
}
@@ -372,42 +493,6 @@ typedef struct {
size_t cap_kvs;
} kv_pairs;
-static void append_kv(kv_pairs *kvs, char *key, char *value) {
- if (kvs->num_kvs == kvs->cap_kvs) {
- kvs->cap_kvs = GPR_MAX(3 * kvs->cap_kvs / 2, 4);
- kvs->kvs = gpr_realloc(kvs->kvs, sizeof(*kvs->kvs) * kvs->cap_kvs);
- }
- kvs->kvs[kvs->num_kvs].key = key;
- kvs->kvs[kvs->num_kvs].value = value;
- kvs->num_kvs++;
-}
-
-static void collect_kvs(gpr_avl_node *node, char *key(void *k),
- char *fmt(void *v), kv_pairs *kvs) {
- if (node == NULL) return;
- append_kv(kvs, key(node->key), fmt(node->value));
- collect_kvs(node->left, key, fmt, kvs);
- collect_kvs(node->right, key, fmt, kvs);
-}
-
-static char *key_int(void *p) {
- return gpr_strdup(error_int_name((grpc_error_ints)(uintptr_t)p));
-}
-
-static char *key_str(void *p) {
- return gpr_strdup(error_str_name((grpc_error_strs)(uintptr_t)p));
-}
-
-static char *key_time(void *p) {
- return gpr_strdup(error_time_name((grpc_error_times)(uintptr_t)p));
-}
-
-static char *fmt_int(void *p) {
- char *s;
- gpr_asprintf(&s, "%" PRIdPTR, (intptr_t)p);
- return s;
-}
-
static void append_chr(char c, char **s, size_t *sz, size_t *cap) {
if (*sz == *cap) {
*cap = GPR_MAX(8, 3 * *cap / 2);
@@ -459,6 +544,40 @@ static void append_esc_str(const char *str, char **s, size_t *sz, size_t *cap) {
append_chr('"', s, sz, cap);
}
+static void append_kv(kv_pairs *kvs, char *key, char *value) {
+ if (kvs->num_kvs == kvs->cap_kvs) {
+ kvs->cap_kvs = GPR_MAX(3 * kvs->cap_kvs / 2, 4);
+ kvs->kvs = gpr_realloc(kvs->kvs, sizeof(*kvs->kvs) * kvs->cap_kvs);
+ }
+ kvs->kvs[kvs->num_kvs].key = key;
+ kvs->kvs[kvs->num_kvs].value = value;
+ kvs->num_kvs++;
+}
+
+static char *key_int(grpc_error_ints which) {
+ return gpr_strdup(error_int_name(which));
+}
+
+static char *fmt_int(intptr_t p) {
+ char *s;
+ gpr_asprintf(&s, "%" PRIdPTR, p);
+ return s;
+}
+
+static void collect_ints_kvs(grpc_error *err, kv_pairs *kvs) {
+ for (size_t which = 0; which < GRPC_ERROR_INT_MAX; ++which) {
+ uint8_t slot = err->ints[which];
+ if (slot != UINT8_MAX) {
+ append_kv(kvs, key_int((grpc_error_ints)which),
+ fmt_int(err->arena[slot]));
+ }
+ }
+}
+
+static char *key_str(grpc_error_strs which) {
+ return gpr_strdup(error_str_name(which));
+}
+
static char *fmt_str(void *p) {
char *s = NULL;
size_t sz = 0;
@@ -468,8 +587,22 @@ static char *fmt_str(void *p) {
return s;
}
-static char *fmt_time(void *p) {
- gpr_timespec tm = *(gpr_timespec *)p;
+static void collect_strs_kvs(grpc_error *err, kv_pairs *kvs) {
+ for (size_t which = 0; which < GRPC_ERROR_STR_MAX; ++which) {
+ uint8_t slot = err->strs[which];
+ if (slot != UINT8_MAX) {
+ append_kv(
+ kvs, key_str((grpc_error_strs)which),
+ fmt_str(GRPC_SLICE_START_PTR(*(grpc_slice *)(err->arena + slot))));
+ }
+ }
+}
+
+static char *key_time(grpc_error_times which) {
+ return gpr_strdup(error_time_name(which));
+}
+
+static char *fmt_time(gpr_timespec tm) {
char *out;
char *pfx = "!!";
switch (tm.clock_type) {
@@ -490,24 +623,37 @@ static char *fmt_time(void *p) {
return out;
}
-static void add_errs(gpr_avl_node *n, char **s, size_t *sz, size_t *cap,
- bool *first) {
- if (n == NULL) return;
- add_errs(n->left, s, sz, cap, first);
- if (!*first) append_chr(',', s, sz, cap);
- *first = false;
- const char *e = grpc_error_string(n->value);
- append_str(e, s, sz, cap);
- add_errs(n->right, s, sz, cap, first);
+static void collect_times_kvs(grpc_error *err, kv_pairs *kvs) {
+ for (size_t which = 0; which < GRPC_ERROR_TIME_MAX; ++which) {
+ uint8_t slot = err->times[which];
+ if (slot != UINT8_MAX) {
+ append_kv(kvs, key_time((grpc_error_times)which),
+ fmt_time(*(gpr_timespec *)(err->arena + slot)));
+ }
+ }
+}
+
+static void add_errs(grpc_error *err, char **s, size_t *sz, size_t *cap) {
+ uint8_t slot = err->first_err;
+ bool first = true;
+ while (slot != UINT8_MAX) {
+ grpc_linked_error *lerr = (grpc_linked_error *)(err->arena + slot);
+ if (!first) append_chr(',', s, sz, cap);
+ first = false;
+ const char *e = grpc_error_string(lerr->err);
+ append_str(e, s, sz, cap);
+ GPR_ASSERT(err->last_err == slot ? lerr->next == UINT8_MAX
+ : lerr->next != UINT8_MAX);
+ slot = lerr->next;
+ }
}
static char *errs_string(grpc_error *err) {
char *s = NULL;
size_t sz = 0;
size_t cap = 0;
- bool first = true;
append_chr('[', &s, &sz, &cap);
- add_errs(err->errs.root, &s, &sz, &cap, &first);
+ add_errs(err, &s, &sz, &cap);
append_chr(']', &s, &sz, &cap);
append_chr(0, &s, &sz, &cap);
return s;
@@ -555,10 +701,10 @@ const char *grpc_error_string(grpc_error *err) {
kv_pairs kvs;
memset(&kvs, 0, sizeof(kvs));
- collect_kvs(err->ints.root, key_int, fmt_int, &kvs);
- collect_kvs(err->strs.root, key_str, fmt_str, &kvs);
- collect_kvs(err->times.root, key_time, fmt_time, &kvs);
- if (!gpr_avl_is_empty(err->errs)) {
+ collect_ints_kvs(err, &kvs);
+ collect_strs_kvs(err, &kvs);
+ collect_times_kvs(err, &kvs);
+ if (err->first_err != UINT8_MAX) {
append_kv(&kvs, gpr_strdup("referenced_errors"), errs_string(err));
}
diff --git a/src/core/lib/iomgr/error.h b/src/core/lib/iomgr/error.h
index ffacdac393..eb953947ae 100644
--- a/src/core/lib/iomgr/error.h
+++ b/src/core/lib/iomgr/error.h
@@ -102,6 +102,9 @@ typedef enum {
GRPC_ERROR_INT_LIMIT,
/// chttp2: did the error occur while a write was in progress
GRPC_ERROR_INT_OCCURRED_DURING_WRITE,
+
+ /// Must always be last
+ GRPC_ERROR_INT_MAX,
} grpc_error_ints;
typedef enum {
@@ -129,16 +132,22 @@ typedef enum {
GRPC_ERROR_STR_KEY,
/// value associated with the error
GRPC_ERROR_STR_VALUE,
+
+ /// Must always be last
+ GRPC_ERROR_STR_MAX,
} grpc_error_strs;
typedef enum {
/// timestamp of error creation
GRPC_ERROR_TIME_CREATED,
+
+ /// Must always be last
+ GRPC_ERROR_TIME_MAX,
} grpc_error_times;
/// The following "special" errors can be propagated without allocating memory.
-/// They are always even so that other code (particularly combiner locks) can
-/// safely use the lower bit for themselves.
+/// They are always even so that other code (particularly combiner locks,
+/// polling engines) can safely use the lower bit for themselves.
#define GRPC_ERROR_NONE ((grpc_error *)NULL)
#define GRPC_ERROR_OOM ((grpc_error *)2)
@@ -184,8 +193,6 @@ void grpc_error_unref(grpc_error *err);
grpc_error *grpc_error_set_int(grpc_error *src, grpc_error_ints which,
intptr_t value) GRPC_MUST_USE_RESULT;
bool grpc_error_get_int(grpc_error *error, grpc_error_ints which, intptr_t *p);
-grpc_error *grpc_error_set_time(grpc_error *src, grpc_error_times which,
- gpr_timespec value) GRPC_MUST_USE_RESULT;
grpc_error *grpc_error_set_str(grpc_error *src, grpc_error_strs which,
const char *value) GRPC_MUST_USE_RESULT;
/// Returns NULL if the specified string is not set.
diff --git a/src/core/lib/iomgr/error_internal.h b/src/core/lib/iomgr/error_internal.h
index 1c89ead4ed..fb4814e41f 100644
--- a/src/core/lib/iomgr/error_internal.h
+++ b/src/core/lib/iomgr/error_internal.h
@@ -35,18 +35,28 @@
#define GRPC_CORE_LIB_IOMGR_ERROR_INTERNAL_H
#include <inttypes.h>
-#include <stdbool.h>
+#include <stdbool.h> // TODO, do we need this?
-#include <grpc/support/avl.h>
+#include <grpc/support/sync.h>
+
+typedef struct grpc_linked_error grpc_linked_error;
+
+struct grpc_linked_error {
+ grpc_error *err;
+ uint8_t next;
+};
struct grpc_error {
gpr_refcount refs;
- gpr_avl ints;
- gpr_avl strs;
- gpr_avl times;
- gpr_avl errs;
- uintptr_t next_err;
+ uint8_t ints[GRPC_ERROR_INT_MAX];
+ uint8_t strs[GRPC_ERROR_STR_MAX];
+ uint8_t times[GRPC_ERROR_TIME_MAX];
+ uint8_t first_err;
+ uint8_t last_err;
gpr_atm error_string;
+ uint8_t arena_size;
+ uint8_t arena_capacity;
+ intptr_t arena[0];
};
bool grpc_error_is_special(grpc_error *err);
diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epoll_linux.c
index 51842fc208..11208b9ad1 100644
--- a/src/core/lib/iomgr/ev_epoll_linux.c
+++ b/src/core/lib/iomgr/ev_epoll_linux.c
@@ -68,7 +68,7 @@ static int grpc_polling_trace = 0; /* Disabled by default */
gpr_log(GPR_INFO, (fmt), __VA_ARGS__); \
}
-/* Uncomment the following enable extra checks on poll_object operations */
+/* Uncomment the following to enable extra checks on poll_object operations */
/* #define PO_DEBUG */
static int grpc_wakeup_signal = -1;
@@ -140,24 +140,61 @@ struct grpc_fd {
Ref/Unref by two to avoid altering the orphaned bit */
gpr_atm refst;
- /* Indicates that the fd is shutdown and that any pending read/write closures
- should fail */
- bool shutdown;
- grpc_error *shutdown_error; /* reason for shutdown: set iff shutdown==true */
+ /* Internally stores data of type (grpc_error *). If the FD is shutdown, this
+ contains reason for shutdown (i.e a pointer to grpc_error) ORed with
+ FD_SHUTDOWN_BIT. Since address allocations are word-aligned, the lower bit
+ of (grpc_error *) addresses is guaranteed to be zero. Even if the
+ (grpc_error *), is of special types like GRPC_ERROR_NONE, GRPC_ERROR_OOM
+ etc, the lower bit is guaranteed to be zero.
- /* The fd is either closed or we relinquished control of it. In either cases,
- this indicates that the 'fd' on this structure is no longer valid */
+ Once an fd is shutdown, any pending or future read/write closures on the
+ fd should fail */
+ gpr_atm shutdown_error;
+
+ /* The fd is either closed or we relinquished control of it. In either
+ cases, this indicates that the 'fd' on this structure is no longer
+ valid */
bool orphaned;
- /* TODO: sreek - Move this to a lockfree implementation */
- grpc_closure *read_closure;
- grpc_closure *write_closure;
+ /* Closures to call when the fd is readable or writable respectively. These
+ fields contain one of the following values:
+ CLOSURE_READY : The fd has an I/O event of interest but there is no
+ closure yet to execute
+
+ CLOSURE_NOT_READY : The fd has no I/O event of interest
+
+ closure ptr : The closure to be executed when the fd has an I/O
+ event of interest
+
+ shutdown_error | FD_SHUTDOWN_BIT :
+ 'shutdown_error' field ORed with FD_SHUTDOWN_BIT.
+ This indicates that the fd is shutdown. Since all
+ memory allocations are word-aligned, the lower two
+ bits of the shutdown_error pointer are always 0. So
+ it is safe to OR these with FD_SHUTDOWN_BIT
+
+ Valid state transitions:
+
+ <closure ptr> <-----3------ CLOSURE_NOT_READY ----1----> CLOSURE_READY
+ | | ^ | ^ | |
+ | | | | | | |
+ | +--------------4----------+ 6 +---------2---------------+ |
+ | | |
+ | v |
+ +-----5-------> [shutdown_error | FD_SHUTDOWN_BIT] <----7---------+
+
+ For 1, 4 : See set_ready() function
+ For 2, 3 : See notify_on() function
+ For 5,6,7: See set_shutdown() function */
+ gpr_atm read_closure;
+ gpr_atm write_closure;
struct grpc_fd *freelist_next;
grpc_closure *on_done_closure;
- /* The pollset that last noticed that the fd is readable */
- grpc_pollset *read_notifier_pollset;
+ /* The pollset that last noticed that the fd is readable. The actual type
+ * stored in this is (grpc_pollset *) */
+ gpr_atm read_notifier_pollset;
grpc_iomgr_object iomgr_object;
};
@@ -180,8 +217,10 @@ static void fd_unref(grpc_fd *fd);
static void fd_global_init(void);
static void fd_global_shutdown(void);
-#define CLOSURE_NOT_READY ((grpc_closure *)0)
-#define CLOSURE_READY ((grpc_closure *)1)
+#define CLOSURE_NOT_READY ((gpr_atm)0)
+#define CLOSURE_READY ((gpr_atm)2)
+
+#define FD_SHUTDOWN_BIT 1
/*******************************************************************************
* Polling island Declarations
@@ -908,7 +947,11 @@ static void unref_by(grpc_fd *fd, int n) {
fd->freelist_next = fd_freelist;
fd_freelist = fd;
grpc_iomgr_unregister_object(&fd->iomgr_object);
- if (fd->shutdown) GRPC_ERROR_UNREF(fd->shutdown_error);
+
+ grpc_error *err = (grpc_error *)gpr_atm_acq_load(&fd->shutdown_error);
+ /* Clear the least significant bit if it set (in case fd was shutdown) */
+ err = (grpc_error *)((intptr_t)err & ~FD_SHUTDOWN_BIT);
+ GRPC_ERROR_UNREF(err);
gpr_mu_unlock(&fd_freelist_mu);
} else {
@@ -972,13 +1015,14 @@ static grpc_fd *fd_create(int fd, const char *name) {
gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1);
new_fd->fd = fd;
- new_fd->shutdown = false;
+ gpr_atm_no_barrier_store(&new_fd->shutdown_error, (gpr_atm)GRPC_ERROR_NONE);
new_fd->orphaned = false;
- new_fd->read_closure = CLOSURE_NOT_READY;
- new_fd->write_closure = CLOSURE_NOT_READY;
+ gpr_atm_no_barrier_store(&new_fd->read_closure, CLOSURE_NOT_READY);
+ gpr_atm_no_barrier_store(&new_fd->write_closure, CLOSURE_NOT_READY);
+ gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL);
+
new_fd->freelist_next = NULL;
new_fd->on_done_closure = NULL;
- new_fd->read_notifier_pollset = NULL;
gpr_mu_unlock(&new_fd->po.mu);
@@ -1060,101 +1104,206 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
GRPC_ERROR_UNREF(error);
}
-static grpc_error *fd_shutdown_error(grpc_fd *fd) {
- if (!fd->shutdown) {
- return GRPC_ERROR_NONE;
- } else {
- return GRPC_ERROR_CREATE_REFERENCING("FD shutdown", &fd->shutdown_error, 1);
+static void notify_on(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *state,
+ grpc_closure *closure) {
+ while (true) {
+ /* Fast-path: CLOSURE_NOT_READY -> <closure>.
+ The 'release' cas here matches the 'acquire' load in set_ready and
+ set_shutdown ensuring that the closure (scheduled by set_ready or
+ set_shutdown) happens-after the I/O event on the fd */
+ if (gpr_atm_rel_cas(state, CLOSURE_NOT_READY, (gpr_atm)closure)) {
+ return; /* Fast-path successful. Return */
+ }
+
+ /* Slowpath. The 'acquire' load matches the 'release' cas in set_ready and
+ set_shutdown */
+ gpr_atm curr = gpr_atm_acq_load(state);
+ switch (curr) {
+ case CLOSURE_NOT_READY: {
+ break; /* retry */
+ }
+
+ case CLOSURE_READY: {
+ /* Change the state to CLOSURE_NOT_READY. Schedule the closure if
+ successful. If not, the state most likely transitioned to shutdown.
+ We should retry.
+
+ This can be a no-barrier cas since the state is being transitioned to
+ CLOSURE_NOT_READY; set_ready and set_shutdown do not schedule any
+ closure when transitioning out of CLOSURE_NO_READY state (i.e there
+ is no other code that needs to 'happen-after' this) */
+ if (gpr_atm_no_barrier_cas(state, CLOSURE_READY, CLOSURE_NOT_READY)) {
+ grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE);
+ return; /* Slow-path successful. Return */
+ }
+
+ break; /* retry */
+ }
+
+ default: {
+ /* 'curr' is either a closure or the fd is shutdown(in which case 'curr'
+ contains a pointer to the shutdown-error). If the fd is shutdown,
+ schedule the closure with the shutdown error */
+ if ((curr & FD_SHUTDOWN_BIT) > 0) {
+ grpc_error *shutdown_err = (grpc_error *)(curr & ~FD_SHUTDOWN_BIT);
+ grpc_closure_sched(
+ exec_ctx, closure,
+ GRPC_ERROR_CREATE_REFERENCING("FD Shutdown", &shutdown_err, 1));
+ return;
+ }
+
+ /* There is already a closure!. This indicates a bug in the code */
+ gpr_log(GPR_ERROR,
+ "notify_on called with a previous callback still pending");
+ abort();
+ }
+ }
}
+
+ GPR_UNREACHABLE_CODE(return );
}
-static void notify_on_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
- grpc_closure **st, grpc_closure *closure) {
- if (fd->shutdown) {
- grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_CREATE("FD shutdown"));
- } else if (*st == CLOSURE_NOT_READY) {
- /* not ready ==> switch to a waiting state by setting the closure */
- *st = closure;
- } else if (*st == CLOSURE_READY) {
- /* already ready ==> queue the closure to run immediately */
- *st = CLOSURE_NOT_READY;
- grpc_closure_sched(exec_ctx, closure, fd_shutdown_error(fd));
- } else {
- /* upcallptr was set to a different closure. This is an error! */
- gpr_log(GPR_ERROR,
- "User called a notify_on function with a previous callback still "
- "pending");
- abort();
+static void set_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *state,
+ grpc_error *shutdown_err) {
+ /* Try the fast-path first (i.e expect the current value to be
+ CLOSURE_NOT_READY */
+ gpr_atm curr = CLOSURE_NOT_READY;
+ gpr_atm new_state = (gpr_atm)shutdown_err | FD_SHUTDOWN_BIT;
+
+ while (true) {
+ /* The 'release' cas here matches the 'acquire' load in notify_on to ensure
+ that the closure it schedules 'happens-after' the set_shutdown is called
+ on the fd */
+ if (gpr_atm_rel_cas(state, curr, new_state)) {
+ return; /* Fast-path successful. Return */
+ }
+
+ /* Fallback to slowpath. This 'acquire' load matches the 'release' cas in
+ notify_on and set_ready */
+ curr = gpr_atm_acq_load(state);
+ switch (curr) {
+ case CLOSURE_READY: {
+ break; /* retry */
+ }
+
+ case CLOSURE_NOT_READY: {
+ break; /* retry */
+ }
+
+ default: {
+ /* 'curr' is either a closure or the fd is already shutdown */
+
+ /* If fd is already shutdown, we are done */
+ if ((curr & FD_SHUTDOWN_BIT) > 0) {
+ return;
+ }
+
+ /* Fd is not shutdown. Schedule the closure and move the state to
+ shutdown state. The 'release' cas here matches the 'acquire' load in
+ notify_on to ensure that the closure it schedules 'happens-after'
+ the set_shutdown is called on the fd */
+ if (gpr_atm_rel_cas(state, curr, new_state)) {
+ grpc_closure_sched(
+ exec_ctx, (grpc_closure *)curr,
+ GRPC_ERROR_CREATE_REFERENCING("FD Shutdown", &shutdown_err, 1));
+ return;
+ }
+
+ /* 'curr' was a closure but now changed to a different state. We will
+ have to retry */
+ break;
+ }
+ }
}
+
+ GPR_UNREACHABLE_CODE(return );
}
-/* returns 1 if state becomes not ready */
-static int set_ready_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
- grpc_closure **st) {
- if (*st == CLOSURE_READY) {
- /* duplicate ready ==> ignore */
- return 0;
- } else if (*st == CLOSURE_NOT_READY) {
- /* not ready, and not waiting ==> flag ready */
- *st = CLOSURE_READY;
- return 0;
- } else {
- /* waiting ==> queue closure */
- grpc_closure_sched(exec_ctx, *st, fd_shutdown_error(fd));
- *st = CLOSURE_NOT_READY;
- return 1;
+static void set_ready(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *state) {
+ /* Try an optimistic case first (i.e assume current state is
+ CLOSURE_NOT_READY).
+
+ This 'release' cas matches the 'acquire' load in notify_on ensuring that
+ any closure (scheduled by notify_on) 'happens-after' the return from
+ epoll_pwait */
+ if (gpr_atm_rel_cas(state, CLOSURE_NOT_READY, CLOSURE_READY)) {
+ return; /* early out */
+ }
+
+ /* The 'acquire' load here matches the 'release' cas in notify_on and
+ set_shutdown */
+ gpr_atm curr = gpr_atm_acq_load(state);
+ switch (curr) {
+ case CLOSURE_READY: {
+ /* Already ready. We are done here */
+ break;
+ }
+
+ case CLOSURE_NOT_READY: {
+ /* The state was not CLOSURE_NOT_READY when we checked initially at the
+ beginning of this function but now it is CLOSURE_NOT_READY again.
+ This is only possible if the state transitioned out of
+ CLOSURE_NOT_READY to either CLOSURE_READY or <some closure> and then
+ back to CLOSURE_NOT_READY again (i.e after we entered this function,
+ the fd became "ready" and the necessary actions were already done).
+ So there is no need to make the state CLOSURE_READY now */
+ break;
+ }
+
+ default: {
+ /* 'curr' is either a closure or the fd is shutdown */
+ if ((curr & FD_SHUTDOWN_BIT) > 0) {
+ /* The fd is shutdown. Do nothing */
+ } else if (gpr_atm_no_barrier_cas(state, curr, CLOSURE_NOT_READY)) {
+ /* The cas above was no-barrier since the state is being transitioned to
+ CLOSURE_NOT_READY; notify_on and set_shutdown do not schedule any
+ closures when transitioning out of CLOSURE_NO_READY state (i.e there
+ is no other code that needs to 'happen-after' this) */
+
+ grpc_closure_sched(exec_ctx, (grpc_closure *)curr, GRPC_ERROR_NONE);
+ }
+ /* else the state changed again (only possible by either a racing
+ set_ready or set_shutdown functions. In both these cases, the closure
+ would have been scheduled for execution. So we are done here */
+ break;
+ }
}
}
static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx,
grpc_fd *fd) {
- grpc_pollset *notifier = NULL;
-
- gpr_mu_lock(&fd->po.mu);
- notifier = fd->read_notifier_pollset;
- gpr_mu_unlock(&fd->po.mu);
-
- return notifier;
+ gpr_atm notifier = gpr_atm_acq_load(&fd->read_notifier_pollset);
+ return (grpc_pollset *)notifier;
}
static bool fd_is_shutdown(grpc_fd *fd) {
- gpr_mu_lock(&fd->po.mu);
- const bool r = fd->shutdown;
- gpr_mu_unlock(&fd->po.mu);
- return r;
+ grpc_error *err = (grpc_error *)gpr_atm_acq_load(&fd->shutdown_error);
+ return (((intptr_t)err & FD_SHUTDOWN_BIT) > 0);
}
/* Might be called multiple times */
static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) {
- gpr_mu_lock(&fd->po.mu);
- /* Do the actual shutdown only once */
- if (!fd->shutdown) {
- fd->shutdown = true;
- fd->shutdown_error = why;
-
+ /* Store the shutdown error ORed with FD_SHUTDOWN_BIT in fd->shutdown_error */
+ if (gpr_atm_rel_cas(&fd->shutdown_error, (gpr_atm)GRPC_ERROR_NONE,
+ (gpr_atm)why | FD_SHUTDOWN_BIT)) {
shutdown(fd->fd, SHUT_RDWR);
- /* Flush any pending read and write closures. Since fd->shutdown is 'true'
- at this point, the closures would be called with 'success = false' */
- set_ready_locked(exec_ctx, fd, &fd->read_closure);
- set_ready_locked(exec_ctx, fd, &fd->write_closure);
+
+ set_shutdown(exec_ctx, fd, &fd->read_closure, why);
+ set_shutdown(exec_ctx, fd, &fd->write_closure, why);
} else {
+ /* Shutdown already called */
GRPC_ERROR_UNREF(why);
}
- gpr_mu_unlock(&fd->po.mu);
}
static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
grpc_closure *closure) {
- gpr_mu_lock(&fd->po.mu);
- notify_on_locked(exec_ctx, fd, &fd->read_closure, closure);
- gpr_mu_unlock(&fd->po.mu);
+ notify_on(exec_ctx, fd, &fd->read_closure, closure);
}
static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
grpc_closure *closure) {
- gpr_mu_lock(&fd->po.mu);
- notify_on_locked(exec_ctx, fd, &fd->write_closure, closure);
- gpr_mu_unlock(&fd->po.mu);
+ notify_on(exec_ctx, fd, &fd->write_closure, closure);
}
static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) {
@@ -1343,18 +1492,19 @@ static int poll_deadline_to_millis_timeout(gpr_timespec deadline,
static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
grpc_pollset *notifier) {
- /* Need the fd->po.mu since we might be racing with fd_notify_on_read */
- gpr_mu_lock(&fd->po.mu);
- set_ready_locked(exec_ctx, fd, &fd->read_closure);
- fd->read_notifier_pollset = notifier;
- gpr_mu_unlock(&fd->po.mu);
+ set_ready(exec_ctx, fd, &fd->read_closure);
+
+ /* Note, it is possible that fd_become_readable might be called twice with
+ different 'notifier's when an fd becomes readable and it is in two epoll
+ sets (This can happen briefly during polling island merges). In such cases
+ it does not really matter which notifer is set as the read_notifier_pollset
+ (They would both point to the same polling island anyway) */
+ /* Use release store to match with acquire load in fd_get_read_notifier */
+ gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier);
}
static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
- /* Need the fd->po.mu since we might be racing with fd_notify_on_write */
- gpr_mu_lock(&fd->po.mu);
- set_ready_locked(exec_ctx, fd, &fd->write_closure);
- gpr_mu_unlock(&fd->po.mu);
+ set_ready(exec_ctx, fd, &fd->write_closure);
}
static void pollset_release_polling_island(grpc_exec_ctx *exec_ctx,
@@ -1405,16 +1555,6 @@ static void pollset_destroy(grpc_pollset *pollset) {
gpr_mu_destroy(&pollset->po.mu);
}
-static void pollset_reset(grpc_pollset *pollset) {
- GPR_ASSERT(pollset->shutting_down);
- GPR_ASSERT(!pollset_has_workers(pollset));
- pollset->shutting_down = false;
- pollset->finish_shutdown_called = false;
- pollset->kicked_without_pollers = false;
- pollset->shutdown_done = NULL;
- GPR_ASSERT(pollset->po.pi == NULL);
-}
-
static bool maybe_do_workqueue_work(grpc_exec_ctx *exec_ctx,
polling_island *pi) {
if (gpr_mu_trylock(&pi->workqueue_read_mu)) {
@@ -1747,7 +1887,7 @@ retry:
(void *)pi_new, FD_FROM_PO(item)->fd, poll_obj_string(bag_type),
(void *)bag);
/* No need to lock 'pi_new' here since this is a new polling island
- * and no one has a reference to it yet */
+ and no one has a reference to it yet */
polling_island_remove_all_fds_locked(pi_new, true, &error);
/* Ref and unref so that the polling island gets deleted during unref
@@ -1852,13 +1992,12 @@ static grpc_pollset_set *pollset_set_create(void) {
return pss;
}
-static void pollset_set_destroy(grpc_pollset_set *pss) {
+static void pollset_set_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_pollset_set *pss) {
gpr_mu_destroy(&pss->po.mu);
if (pss->po.pi != NULL) {
- grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- PI_UNREF(&exec_ctx, pss->po.pi, "pss_destroy");
- grpc_exec_ctx_finish(&exec_ctx);
+ PI_UNREF(exec_ctx, pss->po.pi, "pss_destroy");
}
gpr_free(pss);
@@ -1958,7 +2097,6 @@ static const grpc_event_engine_vtable vtable = {
.pollset_init = pollset_init,
.pollset_shutdown = pollset_shutdown,
- .pollset_reset = pollset_reset,
.pollset_destroy = pollset_destroy,
.pollset_work = pollset_work,
.pollset_kick = pollset_kick,
diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c
index ca12932219..5ddd5313e2 100644
--- a/src/core/lib/iomgr/ev_poll_posix.c
+++ b/src/core/lib/iomgr/ev_poll_posix.c
@@ -149,7 +149,7 @@ static void fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *rec,
static bool fd_is_orphaned(grpc_fd *fd);
/* Reference counting for fds */
-/*#define GRPC_FD_REF_COUNT_DEBUG*/
+//#define GRPC_FD_REF_COUNT_DEBUG
#ifdef GRPC_FD_REF_COUNT_DEBUG
static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line);
static void fd_unref(grpc_fd *fd, const char *reason, const char *file,
@@ -191,6 +191,7 @@ struct grpc_pollset {
int kicked_without_pollers;
grpc_closure *shutdown_done;
grpc_closure_list idle_jobs;
+ int pollset_set_count;
/* all polled fds */
size_t fd_count;
size_t fd_capacity;
@@ -228,7 +229,7 @@ static grpc_error *pollset_kick_ext(grpc_pollset *p,
/* Return 1 if the pollset has active threads in pollset_work (pollset must
* be locked) */
-static int pollset_has_workers(grpc_pollset *pollset);
+static bool pollset_has_workers(grpc_pollset *pollset);
/*******************************************************************************
* pollset_set definitions
@@ -282,8 +283,8 @@ cv_fd_table g_cvfds;
static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file,
int line) {
gpr_log(GPR_DEBUG, "FD %d %p ref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n,
- gpr_atm_no_barrier_load(&fd->refst),
- gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line);
+ (int)gpr_atm_no_barrier_load(&fd->refst),
+ (int)gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line);
#else
#define REF_BY(fd, n, reason) ref_by(fd, n)
#define UNREF_BY(fd, n, reason) unref_by(fd, n)
@@ -297,8 +298,8 @@ static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file,
int line) {
gpr_atm old;
gpr_log(GPR_DEBUG, "FD %d %p unref %d %d -> %d [%s; %s:%d]", fd->fd, fd, n,
- gpr_atm_no_barrier_load(&fd->refst),
- gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line);
+ (int)gpr_atm_no_barrier_load(&fd->refst),
+ (int)gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line);
#else
static void unref_by(grpc_fd *fd, int n) {
gpr_atm old;
@@ -658,10 +659,18 @@ static void remove_worker(grpc_pollset *p, grpc_pollset_worker *worker) {
worker->next->prev = worker->prev;
}
-static int pollset_has_workers(grpc_pollset *p) {
+static bool pollset_has_workers(grpc_pollset *p) {
return p->root_worker.next != &p->root_worker;
}
+static bool pollset_in_pollset_sets(grpc_pollset *p) {
+ return p->pollset_set_count;
+}
+
+static bool pollset_has_observers(grpc_pollset *p) {
+ return pollset_has_workers(p) || pollset_in_pollset_sets(p);
+}
+
static grpc_pollset_worker *pop_front_worker(grpc_pollset *p) {
if (pollset_has_workers(p)) {
grpc_pollset_worker *w = p->root_worker.next;
@@ -800,6 +809,7 @@ static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
pollset->fd_count = 0;
pollset->fd_capacity = 0;
pollset->fds = NULL;
+ pollset->pollset_set_count = 0;
}
static void pollset_destroy(grpc_pollset *pollset) {
@@ -815,16 +825,6 @@ static void pollset_destroy(grpc_pollset *pollset) {
gpr_mu_destroy(&pollset->mu);
}
-static void pollset_reset(grpc_pollset *pollset) {
- GPR_ASSERT(pollset->shutting_down);
- GPR_ASSERT(!pollset_has_workers(pollset));
- GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail);
- GPR_ASSERT(pollset->fd_count == 0);
- pollset->shutting_down = 0;
- pollset->called_shutdown = 0;
- pollset->kicked_without_pollers = 0;
-}
-
static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_fd *fd) {
gpr_mu_lock(&pollset->mu);
@@ -1071,7 +1071,7 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
if (pollset->shutting_down) {
if (pollset_has_workers(pollset)) {
pollset_kick(pollset, NULL);
- } else if (!pollset->called_shutdown) {
+ } else if (!pollset->called_shutdown && !pollset_has_observers(pollset)) {
pollset->called_shutdown = 1;
gpr_mu_unlock(&pollset->mu);
finish_shutdown(exec_ctx, pollset);
@@ -1103,7 +1103,7 @@ static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
if (!pollset_has_workers(pollset)) {
grpc_closure_list_sched(exec_ctx, &pollset->idle_jobs);
}
- if (!pollset->called_shutdown && !pollset_has_workers(pollset)) {
+ if (!pollset->called_shutdown && !pollset_has_observers(pollset)) {
pollset->called_shutdown = 1;
finish_shutdown(exec_ctx, pollset);
}
@@ -1131,18 +1131,32 @@ static int poll_deadline_to_millis_timeout(gpr_timespec deadline,
*/
static grpc_pollset_set *pollset_set_create(void) {
- grpc_pollset_set *pollset_set = gpr_malloc(sizeof(*pollset_set));
- memset(pollset_set, 0, sizeof(*pollset_set));
+ grpc_pollset_set *pollset_set = gpr_zalloc(sizeof(*pollset_set));
gpr_mu_init(&pollset_set->mu);
return pollset_set;
}
-static void pollset_set_destroy(grpc_pollset_set *pollset_set) {
+static void pollset_set_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_pollset_set *pollset_set) {
size_t i;
gpr_mu_destroy(&pollset_set->mu);
for (i = 0; i < pollset_set->fd_count; i++) {
GRPC_FD_UNREF(pollset_set->fds[i], "pollset_set");
}
+ for (i = 0; i < pollset_set->pollset_count; i++) {
+ grpc_pollset *pollset = pollset_set->pollsets[i];
+ gpr_mu_lock(&pollset->mu);
+ pollset->pollset_set_count--;
+ /* check shutdown */
+ if (pollset->shutting_down && !pollset->called_shutdown &&
+ !pollset_has_observers(pollset)) {
+ pollset->called_shutdown = 1;
+ gpr_mu_unlock(&pollset->mu);
+ finish_shutdown(exec_ctx, pollset);
+ } else {
+ gpr_mu_unlock(&pollset->mu);
+ }
+ }
gpr_free(pollset_set->pollsets);
gpr_free(pollset_set->pollset_sets);
gpr_free(pollset_set->fds);
@@ -1153,6 +1167,9 @@ static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set,
grpc_pollset *pollset) {
size_t i, j;
+ gpr_mu_lock(&pollset->mu);
+ pollset->pollset_set_count++;
+ gpr_mu_unlock(&pollset->mu);
gpr_mu_lock(&pollset_set->mu);
if (pollset_set->pollset_count == pollset_set->pollset_capacity) {
pollset_set->pollset_capacity =
@@ -1188,6 +1205,17 @@ static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
}
}
gpr_mu_unlock(&pollset_set->mu);
+ gpr_mu_lock(&pollset->mu);
+ pollset->pollset_set_count--;
+ /* check shutdown */
+ if (pollset->shutting_down && !pollset->called_shutdown &&
+ !pollset_has_observers(pollset)) {
+ pollset->called_shutdown = 1;
+ gpr_mu_unlock(&pollset->mu);
+ finish_shutdown(exec_ctx, pollset);
+ } else {
+ gpr_mu_unlock(&pollset->mu);
+ }
}
static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx,
@@ -1514,7 +1542,6 @@ static const grpc_event_engine_vtable vtable = {
.pollset_init = pollset_init,
.pollset_shutdown = pollset_shutdown,
- .pollset_reset = pollset_reset,
.pollset_destroy = pollset_destroy,
.pollset_work = pollset_work,
.pollset_kick = pollset_kick,
diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c
index 5bb55631d6..b5be5504b9 100644
--- a/src/core/lib/iomgr/ev_posix.c
+++ b/src/core/lib/iomgr/ev_posix.c
@@ -191,10 +191,6 @@ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
g_event_engine->pollset_shutdown(exec_ctx, pollset, closure);
}
-void grpc_pollset_reset(grpc_pollset *pollset) {
- g_event_engine->pollset_reset(pollset);
-}
-
void grpc_pollset_destroy(grpc_pollset *pollset) {
g_event_engine->pollset_destroy(pollset);
}
@@ -219,8 +215,9 @@ grpc_pollset_set *grpc_pollset_set_create(void) {
return g_event_engine->pollset_set_create();
}
-void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set) {
- g_event_engine->pollset_set_destroy(pollset_set);
+void grpc_pollset_set_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_pollset_set *pollset_set) {
+ g_event_engine->pollset_set_destroy(exec_ctx, pollset_set);
}
void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h
index a589efdeec..1a9e5c115a 100644
--- a/src/core/lib/iomgr/ev_posix.h
+++ b/src/core/lib/iomgr/ev_posix.h
@@ -64,7 +64,6 @@ typedef struct grpc_event_engine_vtable {
void (*pollset_init)(grpc_pollset *pollset, gpr_mu **mu);
void (*pollset_shutdown)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_closure *closure);
- void (*pollset_reset)(grpc_pollset *pollset);
void (*pollset_destroy)(grpc_pollset *pollset);
grpc_error *(*pollset_work)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker, gpr_timespec now,
@@ -75,7 +74,8 @@ typedef struct grpc_event_engine_vtable {
struct grpc_fd *fd);
grpc_pollset_set *(*pollset_set_create)(void);
- void (*pollset_set_destroy)(grpc_pollset_set *pollset_set);
+ void (*pollset_set_destroy)(grpc_exec_ctx *exec_ctx,
+ grpc_pollset_set *pollset_set);
void (*pollset_set_add_pollset)(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set,
grpc_pollset *pollset);
diff --git a/src/core/lib/iomgr/network_status_tracker.c b/src/core/lib/iomgr/network_status_tracker.c
index 1601a39002..4104bf927a 100644
--- a/src/core/lib/iomgr/network_status_tracker.c
+++ b/src/core/lib/iomgr/network_status_tracker.c
@@ -31,95 +31,18 @@
*
*/
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
#include "src/core/lib/iomgr/endpoint.h"
-typedef struct endpoint_ll_node {
- grpc_endpoint *ep;
- struct endpoint_ll_node *next;
-} endpoint_ll_node;
-
-static endpoint_ll_node *head = NULL;
-static gpr_mu g_endpoint_mutex;
-
-void grpc_network_status_shutdown(void) {
- if (head != NULL) {
- gpr_log(GPR_ERROR,
- "Memory leaked as not all network endpoints were shut down");
- }
- gpr_mu_destroy(&g_endpoint_mutex);
-}
+void grpc_network_status_shutdown(void) {}
void grpc_network_status_init(void) {
- gpr_mu_init(&g_endpoint_mutex);
// TODO(makarandd): Install callback with OS to monitor network status.
}
-void grpc_destroy_network_status_monitor() {
- for (endpoint_ll_node *curr = head; curr != NULL;) {
- endpoint_ll_node *next = curr->next;
- gpr_free(curr);
- curr = next;
- }
- gpr_mu_destroy(&g_endpoint_mutex);
-}
-
-void grpc_network_status_register_endpoint(grpc_endpoint *ep) {
- gpr_mu_lock(&g_endpoint_mutex);
- if (head == NULL) {
- head = (endpoint_ll_node *)gpr_malloc(sizeof(endpoint_ll_node));
- head->ep = ep;
- head->next = NULL;
- } else {
- endpoint_ll_node *prev_head = head;
- head = (endpoint_ll_node *)gpr_malloc(sizeof(endpoint_ll_node));
- head->ep = ep;
- head->next = prev_head;
- }
- gpr_mu_unlock(&g_endpoint_mutex);
-}
+void grpc_destroy_network_status_monitor() {}
-void grpc_network_status_unregister_endpoint(grpc_endpoint *ep) {
- gpr_mu_lock(&g_endpoint_mutex);
- GPR_ASSERT(head);
- bool found = false;
- endpoint_ll_node *prev = head;
- // if we're unregistering the head, just move head to the next
- if (ep == head->ep) {
- head = head->next;
- gpr_free(prev);
- found = true;
- } else {
- for (endpoint_ll_node *curr = head->next; curr != NULL; curr = curr->next) {
- if (ep == curr->ep) {
- prev->next = curr->next;
- gpr_free(curr);
- found = true;
- break;
- }
- prev = curr;
- }
- }
- gpr_mu_unlock(&g_endpoint_mutex);
- GPR_ASSERT(found);
-}
+void grpc_network_status_register_endpoint(grpc_endpoint *ep) { (void)ep; }
-// Walk the linked-list from head and execute shutdown. It is possible that
-// other threads might be in the process of shutdown as well, but that has
-// no side effect since endpoint shutdown is idempotent.
-void grpc_network_status_shutdown_all_endpoints() {
- gpr_mu_lock(&g_endpoint_mutex);
- if (head == NULL) {
- gpr_mu_unlock(&g_endpoint_mutex);
- return;
- }
- grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+void grpc_network_status_unregister_endpoint(grpc_endpoint *ep) { (void)ep; }
- for (endpoint_ll_node *curr = head; curr != NULL; curr = curr->next) {
- curr->ep->vtable->shutdown(&exec_ctx, curr->ep,
- GRPC_ERROR_CREATE("Network unavailable"));
- }
- gpr_mu_unlock(&g_endpoint_mutex);
- grpc_exec_ctx_finish(&exec_ctx);
-}
+void grpc_network_status_shutdown_all_endpoints() {}
diff --git a/src/core/lib/iomgr/pollset.h b/src/core/lib/iomgr/pollset.h
index 8d9edc8406..e19ce697b8 100644
--- a/src/core/lib/iomgr/pollset.h
+++ b/src/core/lib/iomgr/pollset.h
@@ -53,14 +53,12 @@ typedef struct grpc_pollset grpc_pollset;
typedef struct grpc_pollset_worker grpc_pollset_worker;
size_t grpc_pollset_size(void);
+/* Initialize a pollset: assumes *pollset contains all zeros */
void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu);
/* Begin shutting down the pollset, and call closure when done.
* pollset's mutex must be held */
void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_closure *closure);
-/** Reset the pollset to its initial state (perhaps with some cached objects);
- * must have been previously shutdown */
-void grpc_pollset_reset(grpc_pollset *pollset);
void grpc_pollset_destroy(grpc_pollset *pollset);
/* Do some work on a pollset.
diff --git a/src/core/lib/iomgr/pollset_set.h b/src/core/lib/iomgr/pollset_set.h
index 34bb728c41..d11801d63b 100644
--- a/src/core/lib/iomgr/pollset_set.h
+++ b/src/core/lib/iomgr/pollset_set.h
@@ -44,7 +44,8 @@
typedef struct grpc_pollset_set grpc_pollset_set;
grpc_pollset_set *grpc_pollset_set_create(void);
-void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set);
+void grpc_pollset_set_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_pollset_set *pollset_set);
void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set,
grpc_pollset *pollset);
diff --git a/src/core/lib/iomgr/pollset_set_uv.c b/src/core/lib/iomgr/pollset_set_uv.c
index e5ef8b29e0..836cfee4ef 100644
--- a/src/core/lib/iomgr/pollset_set_uv.c
+++ b/src/core/lib/iomgr/pollset_set_uv.c
@@ -41,7 +41,8 @@ grpc_pollset_set* grpc_pollset_set_create(void) {
return (grpc_pollset_set*)((intptr_t)0xdeafbeef);
}
-void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set) {}
+void grpc_pollset_set_destroy(grpc_exec_ctx* exec_ctx,
+ grpc_pollset_set* pollset_set) {}
void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx,
grpc_pollset_set* pollset_set,
diff --git a/src/core/lib/iomgr/pollset_set_windows.c b/src/core/lib/iomgr/pollset_set_windows.c
index 645650db9b..ae18c8a3ce 100644
--- a/src/core/lib/iomgr/pollset_set_windows.c
+++ b/src/core/lib/iomgr/pollset_set_windows.c
@@ -42,7 +42,8 @@ grpc_pollset_set* grpc_pollset_set_create(void) {
return (grpc_pollset_set*)((intptr_t)0xdeafbeef);
}
-void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set) {}
+void grpc_pollset_set_destroy(grpc_exec_ctx* exec_ctx,
+ grpc_pollset_set* pollset_set) {}
void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx,
grpc_pollset_set* pollset_set,
diff --git a/src/core/lib/iomgr/pollset_uv.c b/src/core/lib/iomgr/pollset_uv.c
index ed3edeee94..a2f81bcd78 100644
--- a/src/core/lib/iomgr/pollset_uv.c
+++ b/src/core/lib/iomgr/pollset_uv.c
@@ -39,6 +39,7 @@
#include <string.h>
+#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
@@ -57,24 +58,40 @@ int grpc_pollset_work_run_loop;
gpr_mu grpc_polling_mu;
+/* This is used solely to kick the uv loop, by setting a callback to be run
+ immediately in the next loop iteration.
+ Note: In the future, if there is a bug that involves missing wakeups in the
+ future, try adding a uv_async_t to kick the loop differently */
+uv_timer_t *dummy_uv_handle;
+
size_t grpc_pollset_size() { return sizeof(grpc_pollset); }
+void dummy_timer_cb(uv_timer_t *handle) {}
+
+void dummy_handle_close_cb(uv_handle_t *handle) { gpr_free(handle); }
+
void grpc_pollset_global_init(void) {
gpr_mu_init(&grpc_polling_mu);
+ dummy_uv_handle = gpr_malloc(sizeof(uv_timer_t));
+ uv_timer_init(uv_default_loop(), dummy_uv_handle);
grpc_pollset_work_run_loop = 1;
}
-void grpc_pollset_global_shutdown(void) { gpr_mu_destroy(&grpc_polling_mu); }
+void grpc_pollset_global_shutdown(void) {
+ gpr_mu_destroy(&grpc_polling_mu);
+ uv_close((uv_handle_t *)dummy_uv_handle, dummy_handle_close_cb);
+}
+
+static void timer_run_cb(uv_timer_t *timer) {}
+
+static void timer_close_cb(uv_handle_t *handle) { handle->data = (void *)1; }
void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
*mu = &grpc_polling_mu;
- memset(pollset, 0, sizeof(grpc_pollset));
uv_timer_init(uv_default_loop(), &pollset->timer);
pollset->shutting_down = 0;
}
-static void timer_close_cb(uv_handle_t *handle) { handle->data = (void *)1; }
-
void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_closure *closure) {
GPR_ASSERT(!pollset->shutting_down);
@@ -82,6 +99,9 @@ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
if (grpc_pollset_work_run_loop) {
// Drain any pending UV callbacks without blocking
uv_run(uv_default_loop(), UV_RUN_NOWAIT);
+ } else {
+ // kick the loop once
+ uv_timer_start(dummy_uv_handle, dummy_timer_cb, 0, 0);
}
grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE);
}
@@ -97,13 +117,6 @@ void grpc_pollset_destroy(grpc_pollset *pollset) {
}
}
-void grpc_pollset_reset(grpc_pollset *pollset) {
- GPR_ASSERT(pollset->shutting_down);
- pollset->shutting_down = 0;
-}
-
-static void timer_run_cb(uv_timer_t *timer) {}
-
grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker_hdl,
gpr_timespec now, gpr_timespec deadline) {
@@ -136,6 +149,7 @@ grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_error *grpc_pollset_kick(grpc_pollset *pollset,
grpc_pollset_worker *specific_worker) {
+ uv_timer_start(dummy_uv_handle, dummy_timer_cb, 0, 0);
return GRPC_ERROR_NONE;
}
diff --git a/src/core/lib/iomgr/pollset_windows.c b/src/core/lib/iomgr/pollset_windows.c
index 2a45e708df..17043c1ea1 100644
--- a/src/core/lib/iomgr/pollset_windows.c
+++ b/src/core/lib/iomgr/pollset_windows.c
@@ -98,7 +98,6 @@ size_t grpc_pollset_size(void) { return sizeof(grpc_pollset); }
void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
*mu = &grpc_polling_mu;
- memset(pollset, 0, sizeof(*pollset));
pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].next =
pollset->root_worker.links[GRPC_POLLSET_WORKER_LINK_POLLSET].prev =
&pollset->root_worker;
@@ -117,16 +116,6 @@ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
void grpc_pollset_destroy(grpc_pollset *pollset) {}
-void grpc_pollset_reset(grpc_pollset *pollset) {
- GPR_ASSERT(pollset->shutting_down);
- GPR_ASSERT(
- !has_workers(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET));
- pollset->shutting_down = 0;
- pollset->is_iocp_worker = 0;
- pollset->kicked_without_pollers = 0;
- pollset->on_shutdown = NULL;
-}
-
grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker **worker_hdl,
gpr_timespec now, gpr_timespec deadline) {
diff --git a/src/core/lib/iomgr/resolve_address_uv.c b/src/core/lib/iomgr/resolve_address_uv.c
index 9b5f3209f0..4d715be94c 100644
--- a/src/core/lib/iomgr/resolve_address_uv.c
+++ b/src/core/lib/iomgr/resolve_address_uv.c
@@ -40,6 +40,7 @@
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/error.h"
@@ -54,8 +55,36 @@ typedef struct request {
grpc_closure *on_done;
grpc_resolved_addresses **addresses;
struct addrinfo *hints;
+ char *host;
+ char *port;
} request;
+static int retry_named_port_failure(int status, request *r,
+ uv_getaddrinfo_cb getaddrinfo_cb) {
+ if (status != 0) {
+ // This loop is copied from resolve_address_posix.c
+ char *svc[][2] = {{"http", "80"}, {"https", "443"}};
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(svc); i++) {
+ if (strcmp(r->port, svc[i][0]) == 0) {
+ int retry_status;
+ uv_getaddrinfo_t *req = gpr_malloc(sizeof(uv_getaddrinfo_t));
+ req->data = r;
+ retry_status = uv_getaddrinfo(uv_default_loop(), req, getaddrinfo_cb,
+ r->host, svc[i][1], r->hints);
+ if (retry_status < 0 || getaddrinfo_cb == NULL) {
+ // The callback will not be called
+ gpr_free(req);
+ }
+ return retry_status;
+ }
+ }
+ }
+ /* If this function calls uv_getaddrinfo, it will return that function's
+ return value. That function only returns numbers <=0, so we can safely
+ return 1 to indicate that we never retried */
+ return 1;
+}
+
static grpc_error *handle_addrinfo_result(int status, struct addrinfo *result,
grpc_resolved_addresses **addresses) {
struct addrinfo *resp;
@@ -97,13 +126,21 @@ static void getaddrinfo_callback(uv_getaddrinfo_t *req, int status,
request *r = (request *)req->data;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_error *error;
+ int retry_status;
+
+ gpr_free(req);
+ retry_status = retry_named_port_failure(status, r, getaddrinfo_callback);
+ if (retry_status == 0) {
+ // The request is being retried. Nothing should be done here
+ return;
+ }
+ /* Either no retry was attempted, or the retry failed. Either way, the
+ original error probably has more interesting information */
error = handle_addrinfo_result(status, res, r->addresses);
grpc_closure_sched(&exec_ctx, r->on_done, error);
grpc_exec_ctx_finish(&exec_ctx);
-
gpr_free(r->hints);
gpr_free(r);
- gpr_free(req);
uv_freeaddrinfo(res);
}
@@ -113,14 +150,15 @@ static grpc_error *try_split_host_port(const char *name,
/* parse name, splitting it into host and port parts */
grpc_error *error;
gpr_split_host_port(name, host, port);
- if (host == NULL) {
+ if (*host == NULL) {
char *msg;
gpr_asprintf(&msg, "unparseable host:port: '%s'", name);
error = GRPC_ERROR_CREATE(msg);
gpr_free(msg);
return error;
}
- if (port == NULL) {
+ if (*port == NULL) {
+ // TODO(murgatroid99): add tests for this case
if (default_port == NULL) {
char *msg;
gpr_asprintf(&msg, "no port in name '%s'", name);
@@ -142,6 +180,7 @@ static grpc_error *blocking_resolve_address_impl(
uv_getaddrinfo_t req;
int s;
grpc_error *err;
+ int retry_status;
req.addrinfo = NULL;
@@ -157,6 +196,12 @@ static grpc_error *blocking_resolve_address_impl(
hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */
s = uv_getaddrinfo(uv_default_loop(), &req, NULL, host, port, &hints);
+ request r = {
+ .addresses = addresses, .hints = &hints, .host = host, .port = port};
+ retry_status = retry_named_port_failure(s, &r, NULL);
+ if (retry_status <= 0) {
+ s = retry_status;
+ }
err = handle_addrinfo_result(s, req.addrinfo, addresses);
done:
@@ -199,6 +244,8 @@ static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name,
r = gpr_malloc(sizeof(request));
r->on_done = on_done;
r->addresses = addrs;
+ r->host = host;
+ r->port = port;
req = gpr_malloc(sizeof(uv_getaddrinfo_t));
req->data = r;
@@ -221,6 +268,8 @@ static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name,
gpr_free(r);
gpr_free(req);
gpr_free(hints);
+ gpr_free(host);
+ gpr_free(port);
}
}
diff --git a/src/core/lib/iomgr/resource_quota.c b/src/core/lib/iomgr/resource_quota.c
index 2cc979467f..511ffdcdf1 100644
--- a/src/core/lib/iomgr/resource_quota.c
+++ b/src/core/lib/iomgr/resource_quota.c
@@ -599,7 +599,7 @@ grpc_resource_quota *grpc_resource_quota_create(const char *name) {
void grpc_resource_quota_unref_internal(grpc_exec_ctx *exec_ctx,
grpc_resource_quota *resource_quota) {
if (gpr_unref(&resource_quota->refs)) {
- grpc_combiner_destroy(exec_ctx, resource_quota->combiner);
+ GRPC_COMBINER_UNREF(exec_ctx, resource_quota->combiner, "resource_quota");
gpr_free(resource_quota->name);
gpr_free(resource_quota);
}
diff --git a/src/core/lib/iomgr/sockaddr_utils.c b/src/core/lib/iomgr/sockaddr_utils.c
index ffa62cb53c..9d2732666b 100644
--- a/src/core/lib/iomgr/sockaddr_utils.c
+++ b/src/core/lib/iomgr/sockaddr_utils.c
@@ -162,6 +162,7 @@ int grpc_sockaddr_to_string(char **out,
char ntop_buf[INET6_ADDRSTRLEN];
const void *ip = NULL;
int port;
+ uint32_t sin6_scope_id = 0;
int ret;
*out = NULL;
@@ -177,10 +178,19 @@ int grpc_sockaddr_to_string(char **out,
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
ip = &addr6->sin6_addr;
port = ntohs(addr6->sin6_port);
+ sin6_scope_id = addr6->sin6_scope_id;
}
if (ip != NULL &&
grpc_inet_ntop(addr->sa_family, ip, ntop_buf, sizeof(ntop_buf)) != NULL) {
- ret = gpr_join_host_port(out, ntop_buf, port);
+ if (sin6_scope_id != 0) {
+ char *host_with_scope;
+ /* Enclose sin6_scope_id with the format defined in RFC 6784 section 2. */
+ gpr_asprintf(&host_with_scope, "%s%%25%" PRIu32, ntop_buf, sin6_scope_id);
+ ret = gpr_join_host_port(out, host_with_scope, port);
+ gpr_free(host_with_scope);
+ } else {
+ ret = gpr_join_host_port(out, ntop_buf, port);
+ }
} else {
ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family);
}
diff --git a/src/core/lib/iomgr/socket_utils_windows.c b/src/core/lib/iomgr/socket_utils_windows.c
index 628ad4a45b..5bbe8fa34c 100644
--- a/src/core/lib/iomgr/socket_utils_windows.c
+++ b/src/core/lib/iomgr/socket_utils_windows.c
@@ -41,8 +41,12 @@
#include <grpc/support/log.h>
const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size) {
+#ifdef GPR_WIN_INET_NTOP
+ return inet_ntop(af, src, dst, size);
+#else
/* Windows InetNtopA wants a mutable ip pointer */
return InetNtopA(af, (void *)src, dst, size);
+#endif /* GPR_WIN_INET_NTOP */
}
#endif /* GRPC_WINDOWS_SOCKETUTILS */
diff --git a/src/core/lib/iomgr/tcp_client_uv.c b/src/core/lib/iomgr/tcp_client_uv.c
index 5225a5402b..618483d9cb 100644
--- a/src/core/lib/iomgr/tcp_client_uv.c
+++ b/src/core/lib/iomgr/tcp_client_uv.c
@@ -46,6 +46,8 @@
#include "src/core/lib/iomgr/tcp_uv.h"
#include "src/core/lib/iomgr/timer.h"
+extern int grpc_tcp_trace;
+
typedef struct grpc_uv_tcp_connect {
uv_connect_t connect_req;
grpc_timer alarm;
@@ -70,6 +72,11 @@ static void uv_tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp,
grpc_error *error) {
int done;
grpc_uv_tcp_connect *connect = acp;
+ if (grpc_tcp_trace) {
+ const char *str = grpc_error_string(error);
+ gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s",
+ connect->addr_name, str);
+ }
if (error == GRPC_ERROR_NONE) {
/* error == NONE implies that the timer ran out, and wasn't cancelled. If
it was cancelled, then the handler that cancelled it also should close
@@ -136,8 +143,7 @@ static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
}
}
- connect = gpr_malloc(sizeof(grpc_uv_tcp_connect));
- memset(connect, 0, sizeof(grpc_uv_tcp_connect));
+ connect = gpr_zalloc(sizeof(grpc_uv_tcp_connect));
connect->closure = closure;
connect->endpoint = ep;
connect->tcp_handle = gpr_malloc(sizeof(uv_tcp_t));
@@ -145,6 +151,12 @@ static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
connect->resource_quota = resource_quota;
uv_tcp_init(uv_default_loop(), connect->tcp_handle);
connect->connect_req.data = connect;
+
+ if (grpc_tcp_trace) {
+ gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting",
+ connect->addr_name);
+ }
+
// TODO(murgatroid99): figure out what the return value here means
uv_tcp_connect(&connect->connect_req, connect->tcp_handle,
(const struct sockaddr *)resolved_addr->addr,
diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c
index e9e7511c9c..5f286a6723 100644
--- a/src/core/lib/iomgr/tcp_server_posix.c
+++ b/src/core/lib/iomgr/tcp_server_posix.c
@@ -44,6 +44,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <ifaddrs.h>
#include <limits.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
@@ -113,8 +114,12 @@ struct grpc_tcp_server {
/* is this server shutting down? */
bool shutdown;
+ /* have listeners been shutdown? */
+ bool shutdown_listeners;
/* use SO_REUSEPORT */
bool so_reuseport;
+ /* expand wildcard addresses to a list of all local addresses */
+ bool expand_wildcard_addrs;
/* linked list of server ports */
grpc_tcp_listener *head;
@@ -158,9 +163,10 @@ grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx,
grpc_tcp_server **server) {
gpr_once_init(&check_init, init);
- grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
+ grpc_tcp_server *s = gpr_zalloc(sizeof(grpc_tcp_server));
s->so_reuseport = has_so_reuseport;
s->resource_quota = grpc_resource_quota_create(NULL);
+ s->expand_wildcard_addrs = false;
for (size_t i = 0; i < (args == NULL ? 0 : args->num_args); i++) {
if (0 == strcmp(GRPC_ARG_ALLOW_REUSEPORT, args->args[i].key)) {
if (args->args[i].type == GRPC_ARG_INTEGER) {
@@ -183,6 +189,15 @@ grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx,
return GRPC_ERROR_CREATE(GRPC_ARG_RESOURCE_QUOTA
" must be a pointer to a buffer pool");
}
+ } else if (0 == strcmp(GRPC_ARG_EXPAND_WILDCARD_ADDRS, args->args[i].key)) {
+ if (args->args[i].type == GRPC_ARG_INTEGER) {
+ s->expand_wildcard_addrs = (args->args[i].value.integer != 0);
+ } else {
+ grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
+ gpr_free(s);
+ return GRPC_ERROR_CREATE(GRPC_ARG_EXPAND_WILDCARD_ADDRS
+ " must be an integer");
+ }
}
}
gpr_ref_init(&s->refs, 1);
@@ -409,7 +424,14 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) {
grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
return;
default:
- gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
+ gpr_mu_lock(&sp->server->mu);
+ if (!sp->server->shutdown_listeners) {
+ gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
+ } else {
+ /* if we have shutdown listeners, accept4 could fail, and we
+ needn't notify users */
+ }
+ gpr_mu_unlock(&sp->server->mu);
goto error;
}
}
@@ -425,11 +447,6 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) {
grpc_fd *fdobj = grpc_fd_create(fd, name);
- if (read_notifier_pollset == NULL) {
- gpr_log(GPR_ERROR, "Read notifier pollset is not set on the fd");
- goto error;
- }
-
grpc_pollset_add_fd(exec_ctx, read_notifier_pollset, fdobj);
// Create acceptor.
@@ -504,9 +521,224 @@ static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd,
return err;
}
-/* Insert count new listeners after listener. Every new listener will have the
- same listen address as listener (SO_REUSEPORT must be enabled). Every new
- listener is a sibling of listener. */
+/* If successful, add a listener to s for addr, set *dsmode for the socket, and
+ return the *listener. */
+static grpc_error *add_addr_to_server(grpc_tcp_server *s,
+ const grpc_resolved_address *addr,
+ unsigned port_index, unsigned fd_index,
+ grpc_dualstack_mode *dsmode,
+ grpc_tcp_listener **listener) {
+ grpc_resolved_address addr4_copy;
+ int fd;
+ grpc_error *err =
+ grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, dsmode, &fd);
+ if (err != GRPC_ERROR_NONE) {
+ return err;
+ }
+ if (*dsmode == GRPC_DSMODE_IPV4 &&
+ grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
+ addr = &addr4_copy;
+ }
+ return add_socket_to_server(s, fd, addr, port_index, fd_index, listener);
+}
+
+/* Bind to "::" to get a port number not used by any address. */
+static grpc_error *get_unused_port(int *port) {
+ grpc_resolved_address wild;
+ grpc_sockaddr_make_wildcard6(0, &wild);
+ grpc_dualstack_mode dsmode;
+ int fd;
+ grpc_error *err =
+ grpc_create_dualstack_socket(&wild, SOCK_STREAM, 0, &dsmode, &fd);
+ if (err != GRPC_ERROR_NONE) {
+ return err;
+ }
+ if (dsmode == GRPC_DSMODE_IPV4) {
+ grpc_sockaddr_make_wildcard4(0, &wild);
+ }
+ if (bind(fd, (const struct sockaddr *)wild.addr, (socklen_t)wild.len) != 0) {
+ err = GRPC_OS_ERROR(errno, "bind");
+ close(fd);
+ return err;
+ }
+ if (getsockname(fd, (struct sockaddr *)wild.addr, (socklen_t *)&wild.len) !=
+ 0) {
+ err = GRPC_OS_ERROR(errno, "getsockname");
+ close(fd);
+ return err;
+ }
+ close(fd);
+ *port = grpc_sockaddr_get_port(&wild);
+ return *port <= 0 ? GRPC_ERROR_CREATE("Bad port") : GRPC_ERROR_NONE;
+}
+
+/* Return the listener in s with address addr or NULL. */
+static grpc_tcp_listener *find_listener_with_addr(grpc_tcp_server *s,
+ grpc_resolved_address *addr) {
+ grpc_tcp_listener *l;
+ gpr_mu_lock(&s->mu);
+ for (l = s->head; l != NULL; l = l->next) {
+ if (l->addr.len != addr->len) {
+ continue;
+ }
+ if (memcmp(l->addr.addr, addr->addr, addr->len) == 0) {
+ break;
+ }
+ }
+ gpr_mu_unlock(&s->mu);
+ return l;
+}
+
+/* Get all addresses assigned to network interfaces on the machine and create a
+ listener for each. requested_port is the port to use for every listener, or 0
+ to select one random port that will be used for every listener. Set *out_port
+ to the port selected. Return GRPC_ERROR_NONE only if all listeners were
+ added. */
+static grpc_error *add_all_local_addrs_to_server(grpc_tcp_server *s,
+ unsigned port_index,
+ int requested_port,
+ int *out_port) {
+ struct ifaddrs *ifa = NULL;
+ struct ifaddrs *ifa_it;
+ unsigned fd_index = 0;
+ grpc_tcp_listener *sp = NULL;
+ grpc_error *err = GRPC_ERROR_NONE;
+ if (requested_port == 0) {
+ /* Note: There could be a race where some local addrs can listen on the
+ selected port and some can't. The sane way to handle this would be to
+ retry by recreating the whole grpc_tcp_server. Backing out individual
+ listeners and orphaning the FDs looks like too much trouble. */
+ if ((err = get_unused_port(&requested_port)) != GRPC_ERROR_NONE) {
+ return err;
+ } else if (requested_port <= 0) {
+ return GRPC_ERROR_CREATE("Bad get_unused_port()");
+ }
+ gpr_log(GPR_DEBUG, "Picked unused port %d", requested_port);
+ }
+ if (getifaddrs(&ifa) != 0 || ifa == NULL) {
+ return GRPC_OS_ERROR(errno, "getifaddrs");
+ }
+ for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) {
+ grpc_resolved_address addr;
+ char *addr_str = NULL;
+ grpc_dualstack_mode dsmode;
+ grpc_tcp_listener *new_sp = NULL;
+ const char *ifa_name = (ifa_it->ifa_name ? ifa_it->ifa_name : "<unknown>");
+ if (ifa_it->ifa_addr == NULL) {
+ continue;
+ } else if (ifa_it->ifa_addr->sa_family == AF_INET) {
+ addr.len = sizeof(struct sockaddr_in);
+ } else if (ifa_it->ifa_addr->sa_family == AF_INET6) {
+ addr.len = sizeof(struct sockaddr_in6);
+ } else {
+ continue;
+ }
+ memcpy(addr.addr, ifa_it->ifa_addr, addr.len);
+ if (!grpc_sockaddr_set_port(&addr, requested_port)) {
+ /* Should never happen, because we check sa_family above. */
+ err = GRPC_ERROR_CREATE("Failed to set port");
+ break;
+ }
+ if (grpc_sockaddr_to_string(&addr_str, &addr, 0) < 0) {
+ addr_str = gpr_strdup("<error>");
+ }
+ gpr_log(GPR_DEBUG,
+ "Adding local addr from interface %s flags 0x%x to server: %s",
+ ifa_name, ifa_it->ifa_flags, addr_str);
+ /* We could have multiple interfaces with the same address (e.g., bonding),
+ so look for duplicates. */
+ if (find_listener_with_addr(s, &addr) != NULL) {
+ gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str,
+ ifa_name);
+ gpr_free(addr_str);
+ continue;
+ }
+ if ((err = add_addr_to_server(s, &addr, port_index, fd_index, &dsmode,
+ &new_sp)) != GRPC_ERROR_NONE) {
+ char *err_str = NULL;
+ grpc_error *root_err;
+ if (gpr_asprintf(&err_str, "Failed to add listener: %s", addr_str) < 0) {
+ err_str = gpr_strdup("Failed to add listener");
+ }
+ root_err = GRPC_ERROR_CREATE(err_str);
+ gpr_free(err_str);
+ gpr_free(addr_str);
+ err = grpc_error_add_child(root_err, err);
+ break;
+ } else {
+ GPR_ASSERT(requested_port == new_sp->port);
+ ++fd_index;
+ if (sp != NULL) {
+ new_sp->is_sibling = 1;
+ sp->sibling = new_sp;
+ }
+ sp = new_sp;
+ }
+ gpr_free(addr_str);
+ }
+ freeifaddrs(ifa);
+ if (err != GRPC_ERROR_NONE) {
+ return err;
+ } else if (sp == NULL) {
+ return GRPC_ERROR_CREATE("No local addresses");
+ } else {
+ *out_port = sp->port;
+ return GRPC_ERROR_NONE;
+ }
+}
+
+/* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
+static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s,
+ unsigned port_index,
+ int requested_port,
+ int *out_port) {
+ grpc_resolved_address wild4;
+ grpc_resolved_address wild6;
+ unsigned fd_index = 0;
+ grpc_dualstack_mode dsmode;
+ grpc_tcp_listener *sp = NULL;
+ grpc_tcp_listener *sp2 = NULL;
+ grpc_error *v6_err = GRPC_ERROR_NONE;
+ grpc_error *v4_err = GRPC_ERROR_NONE;
+ *out_port = -1;
+ if (s->expand_wildcard_addrs) {
+ return add_all_local_addrs_to_server(s, port_index, requested_port,
+ out_port);
+ }
+ grpc_sockaddr_make_wildcards(requested_port, &wild4, &wild6);
+ /* Try listening on IPv6 first. */
+ if ((v6_err = add_addr_to_server(s, &wild6, port_index, fd_index, &dsmode,
+ &sp)) == GRPC_ERROR_NONE) {
+ ++fd_index;
+ requested_port = *out_port = sp->port;
+ if (dsmode == GRPC_DSMODE_DUALSTACK || dsmode == GRPC_DSMODE_IPV4) {
+ return GRPC_ERROR_NONE;
+ }
+ }
+ /* If we got a v6-only socket or nothing, try adding 0.0.0.0. */
+ grpc_sockaddr_set_port(&wild4, requested_port);
+ if ((v4_err = add_addr_to_server(s, &wild4, port_index, fd_index, &dsmode,
+ &sp2)) == GRPC_ERROR_NONE) {
+ *out_port = sp2->port;
+ if (sp != NULL) {
+ sp2->is_sibling = 1;
+ sp->sibling = sp2;
+ }
+ }
+ if (*out_port > 0) {
+ GRPC_LOG_IF_ERROR("Failed to add :: listener", v6_err);
+ GRPC_LOG_IF_ERROR("Failed to add 0.0.0.0 listener", v4_err);
+ return GRPC_ERROR_NONE;
+ } else {
+ grpc_error *root_err =
+ GRPC_ERROR_CREATE("Failed to add any wildcard listeners");
+ GPR_ASSERT(v6_err != GRPC_ERROR_NONE && v4_err != GRPC_ERROR_NONE);
+ root_err = grpc_error_add_child(root_err, v6_err);
+ root_err = grpc_error_add_child(root_err, v4_err);
+ return root_err;
+ }
+}
+
static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
grpc_tcp_listener *sp = NULL;
char *addr_str;
@@ -559,19 +791,13 @@ grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s,
const grpc_resolved_address *addr,
int *out_port) {
grpc_tcp_listener *sp;
- grpc_tcp_listener *sp2 = NULL;
- int fd;
- grpc_dualstack_mode dsmode;
- grpc_resolved_address addr6_v4mapped;
- grpc_resolved_address wild4;
- grpc_resolved_address wild6;
- grpc_resolved_address addr4_copy;
- grpc_resolved_address *allocated_addr = NULL;
grpc_resolved_address sockname_temp;
- int port;
+ grpc_resolved_address addr6_v4mapped;
+ int requested_port = grpc_sockaddr_get_port(addr);
unsigned port_index = 0;
- unsigned fd_index = 0;
- grpc_error *errs[2] = {GRPC_ERROR_NONE, GRPC_ERROR_NONE};
+ grpc_dualstack_mode dsmode;
+ grpc_error *err;
+ *out_port = -1;
if (s->tail != NULL) {
port_index = s->tail->port_index + 1;
}
@@ -579,85 +805,34 @@ grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s,
/* Check if this is a wildcard port, and if so, try to keep the port the same
as some previously created listener. */
- if (grpc_sockaddr_get_port(addr) == 0) {
+ if (requested_port == 0) {
for (sp = s->head; sp; sp = sp->next) {
sockname_temp.len = sizeof(struct sockaddr_storage);
- if (0 == getsockname(sp->fd, (struct sockaddr *)sockname_temp.addr,
+ if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp.addr,
(socklen_t *)&sockname_temp.len)) {
- port = grpc_sockaddr_get_port(&sockname_temp);
- if (port > 0) {
- allocated_addr = gpr_malloc(sizeof(grpc_resolved_address));
- memcpy(allocated_addr, addr, addr->len);
- grpc_sockaddr_set_port(allocated_addr, port);
- addr = allocated_addr;
+ int used_port = grpc_sockaddr_get_port(&sockname_temp);
+ if (used_port > 0) {
+ memcpy(&sockname_temp, addr, sizeof(grpc_resolved_address));
+ grpc_sockaddr_set_port(&sockname_temp, used_port);
+ requested_port = used_port;
+ addr = &sockname_temp;
break;
}
}
}
}
-
- sp = NULL;
-
+ if (grpc_sockaddr_is_wildcard(addr, &requested_port)) {
+ return add_wildcard_addrs_to_server(s, port_index, requested_port,
+ out_port);
+ }
if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
addr = &addr6_v4mapped;
}
-
- /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
- if (grpc_sockaddr_is_wildcard(addr, &port)) {
- grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
-
- /* Try listening on IPv6 first. */
- addr = &wild6;
- errs[0] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
- if (errs[0] == GRPC_ERROR_NONE) {
- errs[0] = add_socket_to_server(s, fd, addr, port_index, fd_index, &sp);
- if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
- goto done;
- }
- if (sp != NULL) {
- ++fd_index;
- }
- /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
- if (port == 0 && sp != NULL) {
- grpc_sockaddr_set_port(&wild4, sp->port);
- }
- }
- addr = &wild4;
- }
-
- errs[1] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
- if (errs[1] == GRPC_ERROR_NONE) {
- if (dsmode == GRPC_DSMODE_IPV4 &&
- grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
- addr = &addr4_copy;
- }
- sp2 = sp;
- errs[1] = add_socket_to_server(s, fd, addr, port_index, fd_index, &sp);
- if (sp2 != NULL && sp != NULL) {
- sp2->sibling = sp;
- sp->is_sibling = 1;
- }
- }
-
-done:
- gpr_free(allocated_addr);
- if (sp != NULL) {
+ if ((err = add_addr_to_server(s, addr, port_index, 0, &dsmode, &sp)) ==
+ GRPC_ERROR_NONE) {
*out_port = sp->port;
- GRPC_ERROR_UNREF(errs[0]);
- GRPC_ERROR_UNREF(errs[1]);
- return GRPC_ERROR_NONE;
- } else {
- *out_port = -1;
- char *addr_str = grpc_sockaddr_to_uri(addr);
- grpc_error *err = grpc_error_set_str(
- GRPC_ERROR_CREATE_REFERENCING("Failed to add port to server", errs,
- GPR_ARRAY_SIZE(errs)),
- GRPC_ERROR_STR_TARGET_ADDRESS, addr_str);
- GRPC_ERROR_UNREF(errs[0]);
- GRPC_ERROR_UNREF(errs[1]);
- gpr_free(addr_str);
- return err;
}
+ return err;
}
/* Return listener at port_index or NULL. Should only be called with s->mu
@@ -770,6 +945,7 @@ void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx,
grpc_tcp_server *s) {
gpr_mu_lock(&s->mu);
+ s->shutdown_listeners = true;
/* shutdown all fd's */
if (s->active_ports) {
grpc_tcp_listener *sp;
diff --git a/src/core/lib/iomgr/tcp_uv.c b/src/core/lib/iomgr/tcp_uv.c
index 5fb398c50b..5541c62068 100644
--- a/src/core/lib/iomgr/tcp_uv.c
+++ b/src/core/lib/iomgr/tcp_uv.c
@@ -79,8 +79,6 @@ typedef struct {
grpc_pollset *pollset;
} grpc_tcp;
-static void uv_close_callback(uv_handle_t *handle) { gpr_free(handle); }
-
static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
grpc_resource_user_unref(exec_ctx, tcp->resource_user);
gpr_free(tcp);
@@ -119,6 +117,13 @@ static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); }
#endif
+static void uv_close_callback(uv_handle_t *handle) {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_tcp *tcp = handle->data;
+ TCP_UNREF(&exec_ctx, tcp, "destroy");
+ grpc_exec_ctx_finish(&exec_ctx);
+}
+
static void alloc_uv_buf(uv_handle_t *handle, size_t suggested_size,
uv_buf_t *buf) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -313,7 +318,6 @@ static void uv_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
grpc_network_status_unregister_endpoint(ep);
grpc_tcp *tcp = (grpc_tcp *)ep;
uv_close((uv_handle_t *)tcp->handle, uv_close_callback);
- TCP_UNREF(exec_ctx, tcp, "destroy");
}
static char *uv_get_peer(grpc_endpoint *ep) {
diff --git a/src/core/lib/iomgr/timer_generic.c b/src/core/lib/iomgr/timer_generic.c
index 40c8351472..d4df96c214 100644
--- a/src/core/lib/iomgr/timer_generic.c
+++ b/src/core/lib/iomgr/timer_generic.c
@@ -42,6 +42,7 @@
#include <grpc/support/useful.h>
#include "src/core/lib/iomgr/time_averaged_stats.h"
#include "src/core/lib/iomgr/timer_heap.h"
+#include "src/core/lib/support/spinlock.h"
#define INVALID_HEAP_INDEX 0xffffffffu
@@ -69,7 +70,7 @@ typedef struct {
/* Protects g_shard_queue */
static gpr_mu g_mu;
/* Allow only one run_some_expired_timers at once */
-static gpr_mu g_checker_mu;
+static gpr_spinlock g_checker_mu = GPR_SPINLOCK_STATIC_INITIALIZER;
static gpr_clock_type g_clock_type;
static shard_type g_shards[NUM_SHARDS];
/* Protected by g_mu */
@@ -90,7 +91,6 @@ void grpc_timer_list_init(gpr_timespec now) {
g_initialized = true;
gpr_mu_init(&g_mu);
- gpr_mu_init(&g_checker_mu);
g_clock_type = now.clock_type;
for (i = 0; i < NUM_SHARDS; i++) {
@@ -117,16 +117,9 @@ void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx) {
grpc_timer_heap_destroy(&shard->heap);
}
gpr_mu_destroy(&g_mu);
- gpr_mu_destroy(&g_checker_mu);
g_initialized = false;
}
-/* This is a cheap, but good enough, pointer hash for sharding the tasks: */
-static size_t shard_idx(const grpc_timer *info) {
- size_t x = (size_t)info;
- return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) & (NUM_SHARDS - 1);
-}
-
static double ts_to_dbl(gpr_timespec ts) {
return (double)ts.tv_sec + 1e-9 * ts.tv_nsec;
}
@@ -181,30 +174,30 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
gpr_timespec deadline, grpc_closure *closure,
gpr_timespec now) {
int is_first_timer = 0;
- shard_type *shard = &g_shards[shard_idx(timer)];
+ shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)];
GPR_ASSERT(deadline.clock_type == g_clock_type);
GPR_ASSERT(now.clock_type == g_clock_type);
timer->closure = closure;
timer->deadline = deadline;
- timer->triggered = 0;
if (!g_initialized) {
- timer->triggered = 1;
+ timer->pending = false;
grpc_closure_sched(
exec_ctx, timer->closure,
GRPC_ERROR_CREATE("Attempt to create timer before initialization"));
return;
}
+ gpr_mu_lock(&shard->mu);
+ timer->pending = true;
if (gpr_time_cmp(deadline, now) <= 0) {
- timer->triggered = 1;
+ timer->pending = false;
grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE);
+ gpr_mu_unlock(&shard->mu);
+ /* early out */
return;
}
- /* TODO(ctiller): check deadline expired */
-
- gpr_mu_lock(&shard->mu);
grpc_time_averaged_stats_add_sample(&shard->stats,
ts_to_dbl(gpr_time_sub(deadline, now)));
if (gpr_time_cmp(deadline, shard->queue_deadline_cap) < 0) {
@@ -247,11 +240,11 @@ void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
return;
}
- shard_type *shard = &g_shards[shard_idx(timer)];
+ shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)];
gpr_mu_lock(&shard->mu);
- if (!timer->triggered) {
+ if (timer->pending) {
grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED);
- timer->triggered = 1;
+ timer->pending = false;
if (timer->heap_index == INVALID_HEAP_INDEX) {
list_remove(timer);
} else {
@@ -302,7 +295,7 @@ static grpc_timer *pop_one(shard_type *shard, gpr_timespec now) {
}
timer = grpc_timer_heap_top(&shard->heap);
if (gpr_time_cmp(timer->deadline, now) > 0) return NULL;
- timer->triggered = 1;
+ timer->pending = false;
grpc_timer_heap_pop(&shard->heap);
return timer;
}
@@ -330,7 +323,7 @@ static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
/* TODO(ctiller): verify that there are any timers (atomically) here */
- if (gpr_mu_trylock(&g_checker_mu)) {
+ if (gpr_spinlock_trylock(&g_checker_mu)) {
gpr_mu_lock(&g_mu);
while (gpr_time_cmp(g_shard_queue[0]->min_deadline, now) < 0) {
@@ -356,7 +349,7 @@ static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
}
gpr_mu_unlock(&g_mu);
- gpr_mu_unlock(&g_checker_mu);
+ gpr_spinlock_unlock(&g_checker_mu);
} else if (next != NULL) {
/* TODO(ctiller): this forces calling code to do an short poll, and
then retry the timer check (because this time through the timer list was
diff --git a/src/core/lib/iomgr/timer_generic.h b/src/core/lib/iomgr/timer_generic.h
index 9d901c7e68..1608dce9fb 100644
--- a/src/core/lib/iomgr/timer_generic.h
+++ b/src/core/lib/iomgr/timer_generic.h
@@ -40,7 +40,7 @@
struct grpc_timer {
gpr_timespec deadline;
uint32_t heap_index; /* INVALID_HEAP_INDEX if not in heap */
- int triggered;
+ bool pending;
struct grpc_timer *next;
struct grpc_timer *prev;
grpc_closure *closure;
diff --git a/src/core/lib/iomgr/timer_uv.c b/src/core/lib/iomgr/timer_uv.c
index fa2cdee964..f28a14405d 100644
--- a/src/core/lib/iomgr/timer_uv.c
+++ b/src/core/lib/iomgr/timer_uv.c
@@ -53,8 +53,8 @@ static void stop_uv_timer(uv_timer_t *handle) {
void run_expired_timer(uv_timer_t *handle) {
grpc_timer *timer = (grpc_timer *)handle->data;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- GPR_ASSERT(!timer->triggered);
- timer->triggered = 1;
+ GPR_ASSERT(timer->pending);
+ timer->pending = 0;
grpc_closure_sched(&exec_ctx, timer->closure, GRPC_ERROR_NONE);
stop_uv_timer(handle);
grpc_exec_ctx_finish(&exec_ctx);
@@ -67,11 +67,11 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
uv_timer_t *uv_timer;
timer->closure = closure;
if (gpr_time_cmp(deadline, now) <= 0) {
- timer->triggered = 1;
+ timer->pending = 0;
grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE);
return;
}
- timer->triggered = 0;
+ timer->pending = 1;
timeout = (uint64_t)gpr_time_to_millis(gpr_time_sub(deadline, now));
uv_timer = gpr_malloc(sizeof(uv_timer_t));
uv_timer_init(uv_default_loop(), uv_timer);
@@ -81,8 +81,8 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
}
void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
- if (!timer->triggered) {
- timer->triggered = 1;
+ if (timer->pending) {
+ timer->pending = 0;
grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED);
stop_uv_timer((uv_timer_t *)timer->uv_timer);
}
diff --git a/src/core/lib/iomgr/timer_uv.h b/src/core/lib/iomgr/timer_uv.h
index 13cf8bd4fa..9870cd4a5c 100644
--- a/src/core/lib/iomgr/timer_uv.h
+++ b/src/core/lib/iomgr/timer_uv.h
@@ -41,7 +41,7 @@ struct grpc_timer {
/* This is actually a uv_timer_t*, but we want to keep platform-specific
types out of headers */
void *uv_timer;
- int triggered;
+ int pending;
};
#endif /* GRPC_CORE_LIB_IOMGR_TIMER_UV_H */
diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c
index 2a1c8d39fa..d1bcd89af1 100644
--- a/src/core/lib/iomgr/udp_server.c
+++ b/src/core/lib/iomgr/udp_server.c
@@ -485,7 +485,11 @@ void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
grpc_schedule_on_exec_ctx);
grpc_fd_notify_on_write(exec_ctx, sp->emfd, &sp->write_closure);
- s->active_ports++;
+ /* Registered for both read and write callbacks: increment active_ports
+ * twice to account for this, and delay free-ing of memory until both
+ * on_read and on_write have fired. */
+ s->active_ports += 2;
+
sp = sp->next;
}
diff --git a/src/core/lib/iomgr/wakeup_fd_posix.h b/src/core/lib/iomgr/wakeup_fd_posix.h
index 71d32d97ba..c8dd242c75 100644
--- a/src/core/lib/iomgr/wakeup_fd_posix.h
+++ b/src/core/lib/iomgr/wakeup_fd_posix.h
@@ -46,7 +46,7 @@
*
* Setup:
* 1. Before calling anything, call global_init() at least once.
- * 1. Call grpc_wakeup_fd_create() to get a wakeup_fd.
+ * 1. Call grpc_wakeup_fd_init() to set up a wakeup_fd.
* 2. Add the result of GRPC_WAKEUP_FD_FD to the set of monitored file
* descriptors for the poll() style API you are using. Monitor the file
* descriptor for readability.
diff --git a/src/core/lib/json/json.c b/src/core/lib/json/json.c
index 48b13686d7..5f7e4ec042 100644
--- a/src/core/lib/json/json.c
+++ b/src/core/lib/json/json.c
@@ -38,8 +38,7 @@
#include "src/core/lib/json/json.h"
grpc_json* grpc_json_create(grpc_json_type type) {
- grpc_json* json = gpr_malloc(sizeof(*json));
- memset(json, 0, sizeof(*json));
+ grpc_json* json = gpr_zalloc(sizeof(*json));
json->type = type;
return json;
diff --git a/src/core/lib/security/context/security_context.c b/src/core/lib/security/context/security_context.c
index fe82fabc31..d29fc55ea0 100644
--- a/src/core/lib/security/context/security_context.c
+++ b/src/core/lib/security/context/security_context.c
@@ -91,10 +91,7 @@ void grpc_auth_context_release(grpc_auth_context *context) {
/* --- grpc_client_security_context --- */
grpc_client_security_context *grpc_client_security_context_create(void) {
- grpc_client_security_context *ctx =
- gpr_malloc(sizeof(grpc_client_security_context));
- memset(ctx, 0, sizeof(grpc_client_security_context));
- return ctx;
+ return gpr_zalloc(sizeof(grpc_client_security_context));
}
void grpc_client_security_context_destroy(void *ctx) {
@@ -112,10 +109,7 @@ void grpc_client_security_context_destroy(void *ctx) {
/* --- grpc_server_security_context --- */
grpc_server_security_context *grpc_server_security_context_create(void) {
- grpc_server_security_context *ctx =
- gpr_malloc(sizeof(grpc_server_security_context));
- memset(ctx, 0, sizeof(grpc_server_security_context));
- return ctx;
+ return gpr_zalloc(sizeof(grpc_server_security_context));
}
void grpc_server_security_context_destroy(void *ctx) {
@@ -132,8 +126,7 @@ void grpc_server_security_context_destroy(void *ctx) {
static grpc_auth_property_iterator empty_iterator = {NULL, 0, NULL};
grpc_auth_context *grpc_auth_context_create(grpc_auth_context *chained) {
- grpc_auth_context *ctx = gpr_malloc(sizeof(grpc_auth_context));
- memset(ctx, 0, sizeof(grpc_auth_context));
+ grpc_auth_context *ctx = gpr_zalloc(sizeof(grpc_auth_context));
gpr_ref_init(&ctx->refcount, 1);
if (chained != NULL) {
ctx->chained = GRPC_AUTH_CONTEXT_REF(chained, "chained");
diff --git a/src/core/lib/security/credentials/composite/composite_credentials.c b/src/core/lib/security/credentials/composite/composite_credentials.c
index be1588dd8b..e497b9f657 100644
--- a/src/core/lib/security/credentials/composite/composite_credentials.c
+++ b/src/core/lib/security/credentials/composite/composite_credentials.c
@@ -115,8 +115,7 @@ static void composite_call_get_request_metadata(
grpc_composite_call_credentials *c = (grpc_composite_call_credentials *)creds;
grpc_composite_call_credentials_metadata_context *ctx;
- ctx = gpr_malloc(sizeof(grpc_composite_call_credentials_metadata_context));
- memset(ctx, 0, sizeof(grpc_composite_call_credentials_metadata_context));
+ ctx = gpr_zalloc(sizeof(grpc_composite_call_credentials_metadata_context));
ctx->auth_md_context = auth_md_context;
ctx->user_data = user_data;
ctx->cb = cb;
@@ -158,8 +157,7 @@ grpc_call_credentials *grpc_composite_call_credentials_create(
GPR_ASSERT(reserved == NULL);
GPR_ASSERT(creds1 != NULL);
GPR_ASSERT(creds2 != NULL);
- c = gpr_malloc(sizeof(grpc_composite_call_credentials));
- memset(c, 0, sizeof(grpc_composite_call_credentials));
+ c = gpr_zalloc(sizeof(grpc_composite_call_credentials));
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_COMPOSITE;
c->base.vtable = &composite_call_credentials_vtable;
gpr_ref_init(&c->base.refcount, 1);
@@ -167,8 +165,7 @@ grpc_call_credentials *grpc_composite_call_credentials_create(
creds2_array = get_creds_array(&creds2);
c->inner.num_creds = creds1_array.num_creds + creds2_array.num_creds;
creds_array_byte_size = c->inner.num_creds * sizeof(grpc_call_credentials *);
- c->inner.creds_array = gpr_malloc(creds_array_byte_size);
- memset(c->inner.creds_array, 0, creds_array_byte_size);
+ c->inner.creds_array = gpr_zalloc(creds_array_byte_size);
for (i = 0; i < creds1_array.num_creds; i++) {
grpc_call_credentials *cur_creds = creds1_array.creds_array[i];
c->inner.creds_array[i] = grpc_call_credentials_ref(cur_creds);
@@ -262,8 +259,7 @@ static grpc_channel_credentials_vtable composite_channel_credentials_vtable = {
grpc_channel_credentials *grpc_composite_channel_credentials_create(
grpc_channel_credentials *channel_creds, grpc_call_credentials *call_creds,
void *reserved) {
- grpc_composite_channel_credentials *c = gpr_malloc(sizeof(*c));
- memset(c, 0, sizeof(*c));
+ grpc_composite_channel_credentials *c = gpr_zalloc(sizeof(*c));
GPR_ASSERT(channel_creds != NULL && call_creds != NULL && reserved == NULL);
GRPC_API_TRACE(
"grpc_composite_channel_credentials_create(channel_creds=%p, "
diff --git a/src/core/lib/security/credentials/credentials.c b/src/core/lib/security/credentials/credentials.c
index b24697ce54..52b80141d1 100644
--- a/src/core/lib/security/credentials/credentials.c
+++ b/src/core/lib/security/credentials/credentials.c
@@ -57,8 +57,7 @@ grpc_credentials_metadata_request *grpc_credentials_metadata_request_create(
grpc_call_credentials *creds, grpc_credentials_metadata_cb cb,
void *user_data) {
grpc_credentials_metadata_request *r =
- gpr_malloc(sizeof(grpc_credentials_metadata_request));
- memset(&r->response, 0, sizeof(r->response));
+ gpr_zalloc(sizeof(grpc_credentials_metadata_request));
r->creds = grpc_call_credentials_ref(creds);
r->cb = cb;
r->user_data = user_data;
diff --git a/src/core/lib/security/credentials/credentials_metadata.c b/src/core/lib/security/credentials/credentials_metadata.c
index 68da5fb4a8..f11cc58786 100644
--- a/src/core/lib/security/credentials/credentials_metadata.c
+++ b/src/core/lib/security/credentials/credentials_metadata.c
@@ -50,8 +50,7 @@ static void store_ensure_capacity(grpc_credentials_md_store *store) {
grpc_credentials_md_store *grpc_credentials_md_store_create(
size_t initial_capacity) {
grpc_credentials_md_store *store =
- gpr_malloc(sizeof(grpc_credentials_md_store));
- memset(store, 0, sizeof(grpc_credentials_md_store));
+ gpr_zalloc(sizeof(grpc_credentials_md_store));
if (initial_capacity > 0) {
store->entries = gpr_malloc(initial_capacity * sizeof(grpc_credentials_md));
store->allocated = initial_capacity;
diff --git a/src/core/lib/security/credentials/fake/fake_credentials.c b/src/core/lib/security/credentials/fake/fake_credentials.c
index a0629f76ce..68636ba208 100644
--- a/src/core/lib/security/credentials/fake/fake_credentials.c
+++ b/src/core/lib/security/credentials/fake/fake_credentials.c
@@ -71,8 +71,7 @@ static grpc_server_credentials_vtable
grpc_channel_credentials *grpc_fake_transport_security_credentials_create(
void) {
- grpc_channel_credentials *c = gpr_malloc(sizeof(grpc_channel_credentials));
- memset(c, 0, sizeof(grpc_channel_credentials));
+ grpc_channel_credentials *c = gpr_zalloc(sizeof(grpc_channel_credentials));
c->type = GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
c->vtable = &fake_transport_security_credentials_vtable;
gpr_ref_init(&c->refcount, 1);
@@ -131,8 +130,7 @@ static grpc_call_credentials_vtable md_only_test_vtable = {
grpc_call_credentials *grpc_md_only_test_credentials_create(
const char *md_key, const char *md_value, int is_async) {
grpc_md_only_test_credentials *c =
- gpr_malloc(sizeof(grpc_md_only_test_credentials));
- memset(c, 0, sizeof(grpc_md_only_test_credentials));
+ gpr_zalloc(sizeof(grpc_md_only_test_credentials));
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
c->base.vtable = &md_only_test_vtable;
gpr_ref_init(&c->base.refcount, 1);
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.c b/src/core/lib/security/credentials/google_default/google_default_credentials.c
index a098741b70..dd44621347 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.c
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.c
@@ -112,7 +112,7 @@ static int is_stack_running_on_compute_engine(grpc_exec_ctx *exec_ctx) {
on compute engine. */
gpr_timespec max_detection_delay = gpr_time_from_seconds(1, GPR_TIMESPAN);
- grpc_pollset *pollset = gpr_malloc(grpc_pollset_size());
+ grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size());
grpc_pollset_init(pollset, &g_polling_mu);
detector.pollent = grpc_polling_entity_create_from_pollset(pollset);
detector.is_done = 0;
@@ -154,7 +154,7 @@ static int is_stack_running_on_compute_engine(grpc_exec_ctx *exec_ctx) {
}
gpr_mu_unlock(g_polling_mu);
- grpc_httpcli_context_destroy(&context);
+ grpc_httpcli_context_destroy(exec_ctx, &context);
grpc_closure_init(&destroy_closure, destroy_pollset,
grpc_polling_entity_pollset(&detector.pollent),
grpc_schedule_on_exec_ctx);
diff --git a/src/core/lib/security/credentials/iam/iam_credentials.c b/src/core/lib/security/credentials/iam/iam_credentials.c
index abd69a9670..393a433f2e 100644
--- a/src/core/lib/security/credentials/iam/iam_credentials.c
+++ b/src/core/lib/security/credentials/iam/iam_credentials.c
@@ -72,8 +72,7 @@ grpc_call_credentials *grpc_google_iam_credentials_create(
GPR_ASSERT(reserved == NULL);
GPR_ASSERT(token != NULL);
GPR_ASSERT(authority_selector != NULL);
- c = gpr_malloc(sizeof(grpc_google_iam_credentials));
- memset(c, 0, sizeof(grpc_google_iam_credentials));
+ c = gpr_zalloc(sizeof(grpc_google_iam_credentials));
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_IAM;
c->base.vtable = &iam_vtable;
gpr_ref_init(&c->base.refcount, 1);
diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.c b/src/core/lib/security/credentials/jwt/jwt_credentials.c
index 616be64a54..178ce89aa6 100644
--- a/src/core/lib/security/credentials/jwt/jwt_credentials.c
+++ b/src/core/lib/security/credentials/jwt/jwt_credentials.c
@@ -135,8 +135,7 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key(
gpr_log(GPR_ERROR, "Invalid input for jwt credentials creation");
return NULL;
}
- c = gpr_malloc(sizeof(grpc_service_account_jwt_access_credentials));
- memset(c, 0, sizeof(grpc_service_account_jwt_access_credentials));
+ c = gpr_zalloc(sizeof(grpc_service_account_jwt_access_credentials));
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_JWT;
gpr_ref_init(&c->base.refcount, 1);
c->base.vtable = &jwt_vtable;
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.c b/src/core/lib/security/credentials/jwt/jwt_verifier.c
index 2270be8f44..5c59cf0f4a 100644
--- a/src/core/lib/security/credentials/jwt/jwt_verifier.c
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.c
@@ -144,8 +144,7 @@ static void jose_header_destroy(grpc_exec_ctx *exec_ctx, jose_header *h) {
static jose_header *jose_header_from_json(grpc_exec_ctx *exec_ctx,
grpc_json *json, grpc_slice buffer) {
grpc_json *cur;
- jose_header *h = gpr_malloc(sizeof(jose_header));
- memset(h, 0, sizeof(jose_header));
+ jose_header *h = gpr_zalloc(sizeof(jose_header));
h->buffer = buffer;
for (cur = json->child; cur != NULL; cur = cur->next) {
if (strcmp(cur->key, "alg") == 0) {
@@ -363,8 +362,7 @@ static verifier_cb_ctx *verifier_cb_ctx_create(
const char *signed_jwt, size_t signed_jwt_len, void *user_data,
grpc_jwt_verification_done_cb cb) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- verifier_cb_ctx *ctx = gpr_malloc(sizeof(verifier_cb_ctx));
- memset(ctx, 0, sizeof(verifier_cb_ctx));
+ verifier_cb_ctx *ctx = gpr_zalloc(sizeof(verifier_cb_ctx));
ctx->verifier = verifier;
ctx->pollent = grpc_polling_entity_create_from_pollset(pollset);
ctx->header = header;
@@ -878,8 +876,7 @@ error:
grpc_jwt_verifier *grpc_jwt_verifier_create(
const grpc_jwt_verifier_email_domain_key_url_mapping *mappings,
size_t num_mappings) {
- grpc_jwt_verifier *v = gpr_malloc(sizeof(grpc_jwt_verifier));
- memset(v, 0, sizeof(grpc_jwt_verifier));
+ grpc_jwt_verifier *v = gpr_zalloc(sizeof(grpc_jwt_verifier));
grpc_httpcli_context_init(&v->http_ctx);
/* We know at least of one mapping. */
@@ -898,10 +895,10 @@ grpc_jwt_verifier *grpc_jwt_verifier_create(
return v;
}
-void grpc_jwt_verifier_destroy(grpc_jwt_verifier *v) {
+void grpc_jwt_verifier_destroy(grpc_exec_ctx *exec_ctx, grpc_jwt_verifier *v) {
size_t i;
if (v == NULL) return;
- grpc_httpcli_context_destroy(&v->http_ctx);
+ grpc_httpcli_context_destroy(exec_ctx, &v->http_ctx);
if (v->mappings != NULL) {
for (i = 0; i < v->num_mappings; i++) {
gpr_free(v->mappings[i].email_domain);
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.h b/src/core/lib/security/credentials/jwt/jwt_verifier.h
index 4fa320a415..5c3d2a7788 100644
--- a/src/core/lib/security/credentials/jwt/jwt_verifier.h
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.h
@@ -109,7 +109,8 @@ grpc_jwt_verifier *grpc_jwt_verifier_create(
size_t num_mappings);
/*The verifier must not be destroyed if there are still outstanding callbacks.*/
-void grpc_jwt_verifier_destroy(grpc_jwt_verifier *verifier);
+void grpc_jwt_verifier_destroy(grpc_exec_ctx *exec_ctx,
+ grpc_jwt_verifier *verifier);
/* User provided callback that will be called when the verification of the JWT
is done (maybe in another thread).
diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
index 1b0e43a1e4..ccfb3566c1 100644
--- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
+++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c
@@ -124,7 +124,7 @@ static void oauth2_token_fetcher_destruct(grpc_exec_ctx *exec_ctx,
(grpc_oauth2_token_fetcher_credentials *)creds;
grpc_credentials_md_store_unref(exec_ctx, c->access_token_md);
gpr_mu_destroy(&c->mu);
- grpc_httpcli_context_destroy(&c->httpcli_context);
+ grpc_httpcli_context_destroy(exec_ctx, &c->httpcli_context);
}
grpc_credentials_status
@@ -389,8 +389,7 @@ grpc_refresh_token_credentials_create_from_auth_refresh_token(
gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation");
return NULL;
}
- c = gpr_malloc(sizeof(grpc_google_refresh_token_credentials));
- memset(c, 0, sizeof(grpc_google_refresh_token_credentials));
+ c = gpr_zalloc(sizeof(grpc_google_refresh_token_credentials));
init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2);
c->base.base.vtable = &refresh_token_vtable;
c->refresh_token = refresh_token;
@@ -450,14 +449,13 @@ static grpc_call_credentials_vtable access_token_vtable = {
grpc_call_credentials *grpc_access_token_credentials_create(
const char *access_token, void *reserved) {
grpc_access_token_credentials *c =
- gpr_malloc(sizeof(grpc_access_token_credentials));
+ gpr_zalloc(sizeof(grpc_access_token_credentials));
char *token_md_value;
GRPC_API_TRACE(
"grpc_access_token_credentials_create(access_token=<redacted>, "
"reserved=%p)",
1, (reserved));
GPR_ASSERT(reserved == NULL);
- memset(c, 0, sizeof(grpc_access_token_credentials));
c->base.type = GRPC_CALL_CREDENTIALS_TYPE_OAUTH2;
c->base.vtable = &access_token_vtable;
gpr_ref_init(&c->base.refcount, 1);
diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.c b/src/core/lib/security/credentials/plugin/plugin_credentials.c
index 7bc5dfb403..8416bfa5a8 100644
--- a/src/core/lib/security/credentials/plugin/plugin_credentials.c
+++ b/src/core/lib/security/credentials/plugin/plugin_credentials.c
@@ -126,8 +126,7 @@ static void plugin_get_request_metadata(grpc_exec_ctx *exec_ctx,
void *user_data) {
grpc_plugin_credentials *c = (grpc_plugin_credentials *)creds;
if (c->plugin.get_metadata != NULL) {
- grpc_metadata_plugin_request *request = gpr_malloc(sizeof(*request));
- memset(request, 0, sizeof(*request));
+ grpc_metadata_plugin_request *request = gpr_zalloc(sizeof(*request));
request->user_data = user_data;
request->cb = cb;
c->plugin.get_metadata(c->plugin.state, context,
@@ -142,11 +141,10 @@ static grpc_call_credentials_vtable plugin_vtable = {
grpc_call_credentials *grpc_metadata_credentials_create_from_plugin(
grpc_metadata_credentials_plugin plugin, void *reserved) {
- grpc_plugin_credentials *c = gpr_malloc(sizeof(*c));
+ grpc_plugin_credentials *c = gpr_zalloc(sizeof(*c));
GRPC_API_TRACE("grpc_metadata_credentials_create_from_plugin(reserved=%p)", 1,
(reserved));
GPR_ASSERT(reserved == NULL);
- memset(c, 0, sizeof(*c));
c->base.type = plugin.type;
c->base.vtable = &plugin_vtable;
gpr_ref_init(&c->base.refcount, 1);
diff --git a/src/core/lib/security/credentials/ssl/ssl_credentials.c b/src/core/lib/security/credentials/ssl/ssl_credentials.c
index 4eebb7d613..4b17ac8098 100644
--- a/src/core/lib/security/credentials/ssl/ssl_credentials.c
+++ b/src/core/lib/security/credentials/ssl/ssl_credentials.c
@@ -121,14 +121,13 @@ static void ssl_build_config(const char *pem_root_certs,
grpc_channel_credentials *grpc_ssl_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
void *reserved) {
- grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials));
+ grpc_ssl_credentials *c = gpr_zalloc(sizeof(grpc_ssl_credentials));
GRPC_API_TRACE(
"grpc_ssl_credentials_create(pem_root_certs=%s, "
"pem_key_cert_pair=%p, "
"reserved=%p)",
3, (pem_root_certs, pem_key_cert_pair, reserved));
GPR_ASSERT(reserved == NULL);
- memset(c, 0, sizeof(grpc_ssl_credentials));
c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
c->base.vtable = &ssl_vtable;
gpr_ref_init(&c->base.refcount, 1);
@@ -225,7 +224,7 @@ grpc_server_credentials *grpc_ssl_server_credentials_create_ex(
grpc_ssl_client_certificate_request_type client_certificate_request,
void *reserved) {
grpc_ssl_server_credentials *c =
- gpr_malloc(sizeof(grpc_ssl_server_credentials));
+ gpr_zalloc(sizeof(grpc_ssl_server_credentials));
GRPC_API_TRACE(
"grpc_ssl_server_credentials_create_ex("
"pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, "
@@ -233,7 +232,6 @@ grpc_server_credentials *grpc_ssl_server_credentials_create_ex(
5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs,
client_certificate_request, reserved));
GPR_ASSERT(reserved == NULL);
- memset(c, 0, sizeof(grpc_ssl_server_credentials));
c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
gpr_ref_init(&c->base.refcount, 1);
c->base.vtable = &ssl_server_vtable;
diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c
index b9bbe1b304..a23082a866 100644
--- a/src/core/lib/security/transport/client_auth_filter.c
+++ b/src/core/lib/security/transport/client_auth_filter.c
@@ -302,7 +302,7 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
/* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- grpc_call_element_args *args) {
+ const grpc_call_element_args *args) {
call_data *calld = elem->call_data;
memset(calld, 0, sizeof(*calld));
return GRPC_ERROR_NONE;
diff --git a/src/core/lib/security/transport/security_connector.c b/src/core/lib/security/transport/security_connector.c
index aeb04e33a3..ad083a730f 100644
--- a/src/core/lib/security/transport/security_connector.c
+++ b/src/core/lib/security/transport/security_connector.c
@@ -412,8 +412,7 @@ static grpc_security_connector_vtable fake_server_vtable = {
grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
grpc_call_credentials *request_metadata_creds, const char *target,
const grpc_channel_args *args) {
- grpc_fake_channel_security_connector *c = gpr_malloc(sizeof(*c));
- memset(c, 0, sizeof(*c));
+ grpc_fake_channel_security_connector *c = gpr_zalloc(sizeof(*c));
gpr_ref_init(&c->base.base.refcount, 1);
c->base.base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
c->base.base.vtable = &fake_channel_vtable;
@@ -435,8 +434,7 @@ grpc_channel_security_connector *grpc_fake_channel_security_connector_create(
grpc_server_security_connector *grpc_fake_server_security_connector_create(
void) {
grpc_server_security_connector *c =
- gpr_malloc(sizeof(grpc_server_security_connector));
- memset(c, 0, sizeof(*c));
+ gpr_zalloc(sizeof(grpc_server_security_connector));
gpr_ref_init(&c->base.refcount, 1);
c->base.vtable = &fake_server_vtable;
c->base.url_scheme = GRPC_FAKE_SECURITY_URL_SCHEME;
@@ -815,8 +813,7 @@ grpc_security_status grpc_ssl_channel_security_connector_create(
pem_root_certs_size = config->pem_root_certs_size;
}
- c = gpr_malloc(sizeof(grpc_ssl_channel_security_connector));
- memset(c, 0, sizeof(grpc_ssl_channel_security_connector));
+ c = gpr_zalloc(sizeof(grpc_ssl_channel_security_connector));
gpr_ref_init(&c->base.base.refcount, 1);
c->base.base.vtable = &ssl_channel_vtable;
@@ -877,8 +874,7 @@ grpc_security_status grpc_ssl_server_security_connector_create(
gpr_log(GPR_ERROR, "An SSL server needs a key and a cert.");
goto error;
}
- c = gpr_malloc(sizeof(grpc_ssl_server_security_connector));
- memset(c, 0, sizeof(grpc_ssl_server_security_connector));
+ c = gpr_zalloc(sizeof(grpc_ssl_server_security_connector));
gpr_ref_init(&c->base.base.refcount, 1);
c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
diff --git a/src/core/lib/security/transport/security_handshaker.c b/src/core/lib/security/transport/security_handshaker.c
index 5d57543ac5..7065d261ba 100644
--- a/src/core/lib/security/transport/security_handshaker.c
+++ b/src/core/lib/security/transport/security_handshaker.c
@@ -387,8 +387,7 @@ static const grpc_handshaker_vtable security_handshaker_vtable = {
static grpc_handshaker *security_handshaker_create(
grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker,
grpc_security_connector *connector) {
- security_handshaker *h = gpr_malloc(sizeof(security_handshaker));
- memset(h, 0, sizeof(security_handshaker));
+ security_handshaker *h = gpr_zalloc(sizeof(security_handshaker));
grpc_handshaker_init(&security_handshaker_vtable, &h->base);
h->handshaker = handshaker;
h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake");
diff --git a/src/core/lib/security/transport/server_auth_filter.c b/src/core/lib/security/transport/server_auth_filter.c
index 36e81d6501..14619d97ca 100644
--- a/src/core/lib/security/transport/server_auth_filter.c
+++ b/src/core/lib/security/transport/server_auth_filter.c
@@ -197,7 +197,7 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
/* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- grpc_call_element_args *args) {
+ const grpc_call_element_args *args) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
diff --git a/src/core/lib/slice/slice_hash_table.c b/src/core/lib/slice/slice_hash_table.c
index 46f807f4a5..219567f36f 100644
--- a/src/core/lib/slice/slice_hash_table.c
+++ b/src/core/lib/slice/slice_hash_table.c
@@ -82,15 +82,13 @@ static void grpc_slice_hash_table_add(
grpc_slice_hash_table* grpc_slice_hash_table_create(
size_t num_entries, grpc_slice_hash_table_entry* entries) {
- grpc_slice_hash_table* table = gpr_malloc(sizeof(*table));
- memset(table, 0, sizeof(*table));
+ grpc_slice_hash_table* table = gpr_zalloc(sizeof(*table));
gpr_ref_init(&table->refs, 1);
// Quadratic probing gets best performance when the table is no more
// than half full.
table->size = num_entries * 2;
const size_t entry_size = sizeof(grpc_slice_hash_table_entry) * table->size;
- table->entries = gpr_malloc(entry_size);
- memset(table->entries, 0, entry_size);
+ table->entries = gpr_zalloc(entry_size);
for (size_t i = 0; i < num_entries; ++i) {
grpc_slice_hash_table_entry* entry = &entries[i];
grpc_slice_hash_table_add(table, entry->key, entry->value, entry->vtable);
diff --git a/src/core/lib/slice/slice_intern.c b/src/core/lib/slice/slice_intern.c
index 32adc4df97..1c00a2d88e 100644
--- a/src/core/lib/slice/slice_intern.c
+++ b/src/core/lib/slice/slice_intern.c
@@ -144,8 +144,7 @@ static void grow_shard(slice_shard *shard) {
GPR_TIMER_BEGIN("grow_strtab", 0);
- strtab = gpr_malloc(sizeof(interned_slice_refcount *) * capacity);
- memset(strtab, 0, sizeof(interned_slice_refcount *) * capacity);
+ strtab = gpr_zalloc(sizeof(interned_slice_refcount *) * capacity);
for (i = 0; i < shard->capacity; i++) {
for (s = shard->strs[i]; s; s = next) {
@@ -296,8 +295,7 @@ void grpc_slice_intern_init(void) {
gpr_mu_init(&shard->mu);
shard->count = 0;
shard->capacity = INITIAL_SHARD_CAPACITY;
- shard->strs = gpr_malloc(sizeof(*shard->strs) * shard->capacity);
- memset(shard->strs, 0, sizeof(*shard->strs) * shard->capacity);
+ shard->strs = gpr_zalloc(sizeof(*shard->strs) * shard->capacity);
}
for (size_t i = 0; i < GPR_ARRAY_SIZE(static_metadata_hash); i++) {
static_metadata_hash[i].hash = 0;
diff --git a/src/core/lib/support/alloc.c b/src/core/lib/support/alloc.c
index 618c3f6acd..9973166217 100644
--- a/src/core/lib/support/alloc.c
+++ b/src/core/lib/support/alloc.c
@@ -36,9 +36,19 @@
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
#include <stdlib.h>
+#include <string.h>
#include "src/core/lib/profiling/timers.h"
-static gpr_allocation_functions g_alloc_functions = {malloc, realloc, free};
+static void *zalloc_with_calloc(size_t sz) { return calloc(sz, 1); }
+
+static void *zalloc_with_gpr_malloc(size_t sz) {
+ void *p = gpr_malloc(sz);
+ memset(p, 0, sz);
+ return p;
+}
+
+static gpr_allocation_functions g_alloc_functions = {malloc, zalloc_with_calloc,
+ realloc, free};
gpr_allocation_functions gpr_get_allocation_functions() {
return g_alloc_functions;
@@ -48,6 +58,9 @@ void gpr_set_allocation_functions(gpr_allocation_functions functions) {
GPR_ASSERT(functions.malloc_fn != NULL);
GPR_ASSERT(functions.realloc_fn != NULL);
GPR_ASSERT(functions.free_fn != NULL);
+ if (functions.zalloc_fn == NULL) {
+ functions.zalloc_fn = zalloc_with_gpr_malloc;
+ }
g_alloc_functions = functions;
}
@@ -63,6 +76,18 @@ void *gpr_malloc(size_t size) {
return p;
}
+void *gpr_zalloc(size_t size) {
+ void *p;
+ if (size == 0) return NULL;
+ GPR_TIMER_BEGIN("gpr_zalloc", 0);
+ p = g_alloc_functions.zalloc_fn(size);
+ if (!p) {
+ abort();
+ }
+ GPR_TIMER_END("gpr_zalloc", 0);
+ return p;
+}
+
void gpr_free(void *p) {
GPR_TIMER_BEGIN("gpr_free", 0);
g_alloc_functions.free_fn(p);
diff --git a/src/core/lib/support/cmdline.c b/src/core/lib/support/cmdline.c
index d47498676d..88a65a8e2e 100644
--- a/src/core/lib/support/cmdline.c
+++ b/src/core/lib/support/cmdline.c
@@ -71,8 +71,7 @@ struct gpr_cmdline {
static int normal_state(gpr_cmdline *cl, char *arg);
gpr_cmdline *gpr_cmdline_create(const char *description) {
- gpr_cmdline *cl = gpr_malloc(sizeof(gpr_cmdline));
- memset(cl, 0, sizeof(gpr_cmdline));
+ gpr_cmdline *cl = gpr_zalloc(sizeof(gpr_cmdline));
cl->description = description;
cl->state = normal_state;
@@ -101,8 +100,7 @@ static void add_arg(gpr_cmdline *cl, const char *name, const char *help,
GPR_ASSERT(0 != strcmp(a->name, name));
}
- a = gpr_malloc(sizeof(arg));
- memset(a, 0, sizeof(arg));
+ a = gpr_zalloc(sizeof(arg));
a->name = name;
a->help = help;
a->type = type;
diff --git a/src/core/lib/support/cpu_posix.c b/src/core/lib/support/cpu_posix.c
index 667bde7cad..245f12f06d 100644
--- a/src/core/lib/support/cpu_posix.c
+++ b/src/core/lib/support/cpu_posix.c
@@ -41,6 +41,7 @@
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
+#include <grpc/support/useful.h>
static __thread char magic_thread_local;
@@ -60,18 +61,12 @@ unsigned gpr_cpu_num_cores(void) {
return (unsigned)ncpus;
}
-/* This is a cheap, but good enough, pointer hash for sharding things: */
-static size_t shard_ptr(const void *info) {
- size_t x = (size_t)info;
- return ((x >> 4) ^ (x >> 9) ^ (x >> 14)) % gpr_cpu_num_cores();
-}
-
unsigned gpr_cpu_current_cpu(void) {
/* NOTE: there's no way I know to return the actual cpu index portably...
most code that's using this is using it to shard across work queues though,
so here we use thread identity instead to achieve a similar though not
identical effect */
- return (unsigned)shard_ptr(&magic_thread_local);
+ return (unsigned)GPR_HASH_POINTER(&magic_thread_local, gpr_cpu_num_cores());
}
#endif /* GPR_CPU_POSIX */
diff --git a/src/core/lib/support/histogram.c b/src/core/lib/support/histogram.c
index 7b016bbc78..ba8176bb05 100644
--- a/src/core/lib/support/histogram.c
+++ b/src/core/lib/support/histogram.c
@@ -102,8 +102,7 @@ gpr_histogram *gpr_histogram_create(double resolution,
h->num_buckets = bucket_for_unchecked(h, max_bucket_start) + 1;
GPR_ASSERT(h->num_buckets > 1);
GPR_ASSERT(h->num_buckets < 100000000);
- h->buckets = gpr_malloc(sizeof(uint32_t) * h->num_buckets);
- memset(h->buckets, 0, sizeof(uint32_t) * h->num_buckets);
+ h->buckets = gpr_zalloc(sizeof(uint32_t) * h->num_buckets);
return h;
}
diff --git a/src/core/lib/support/spinlock.h b/src/core/lib/support/spinlock.h
new file mode 100644
index 0000000000..d8c7c5ffde
--- /dev/null
+++ b/src/core/lib/support/spinlock.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_SUPPORT_SPINLOCK_H
+#define GRPC_CORE_LIB_SUPPORT_SPINLOCK_H
+
+#include <grpc/support/atm.h>
+
+/* Simple spinlock. No backoff strategy, gpr_spinlock_lock is almost always
+ a concurrency code smell. */
+typedef struct { gpr_atm atm; } gpr_spinlock;
+
+#define GPR_SPINLOCK_INITIALIZER ((gpr_spinlock){0})
+#define GPR_SPINLOCK_STATIC_INITIALIZER \
+ { 0 }
+#define gpr_spinlock_trylock(lock) (gpr_atm_acq_cas(&(lock)->atm, 0, 1))
+#define gpr_spinlock_unlock(lock) (gpr_atm_rel_store(&(lock)->atm, 0))
+#define gpr_spinlock_lock(lock) \
+ do { \
+ } while (!gpr_spinlock_trylock((lock)))
+
+#endif /* GRPC_CORE_LIB_SUPPORT_SPINLOCK_H */
diff --git a/src/core/lib/support/subprocess_posix.c b/src/core/lib/support/subprocess_posix.c
index 4247a1c12b..ed653b9c2e 100644
--- a/src/core/lib/support/subprocess_posix.c
+++ b/src/core/lib/support/subprocess_posix.c
@@ -76,8 +76,7 @@ gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
_exit(1);
return NULL;
} else {
- r = gpr_malloc(sizeof(gpr_subprocess));
- memset(r, 0, sizeof(*r));
+ r = gpr_zalloc(sizeof(gpr_subprocess));
r->pid = pid;
return r;
}
diff --git a/src/core/lib/support/sync.c b/src/core/lib/support/sync.c
index 44b83f8175..b52f004f74 100644
--- a/src/core/lib/support/sync.c
+++ b/src/core/lib/support/sync.c
@@ -37,6 +37,8 @@
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
+#include <assert.h>
+
/* Number of mutexes to allocate for events, to avoid lock contention.
Should be a prime. */
enum { event_sync_partitions = 31 };
@@ -99,8 +101,12 @@ void gpr_ref_init(gpr_refcount *r, int n) { gpr_atm_rel_store(&r->count, n); }
void gpr_ref(gpr_refcount *r) { gpr_atm_no_barrier_fetch_add(&r->count, 1); }
void gpr_ref_non_zero(gpr_refcount *r) {
+#ifndef NDEBUG
gpr_atm prior = gpr_atm_no_barrier_fetch_add(&r->count, 1);
- GPR_ASSERT(prior > 0);
+ assert(prior > 0);
+#else
+ gpr_ref(r);
+#endif
}
void gpr_refn(gpr_refcount *r, int n) {
@@ -113,6 +119,10 @@ int gpr_unref(gpr_refcount *r) {
return prior == 1;
}
+int gpr_ref_is_unique(gpr_refcount *r) {
+ return gpr_atm_acq_load(&r->count) == 1;
+}
+
void gpr_stats_init(gpr_stats_counter *c, intptr_t n) {
gpr_atm_rel_store(&c->value, n);
}
diff --git a/src/core/lib/support/sync_posix.c b/src/core/lib/support/sync_posix.c
index de0f0484b5..16e7d6e12a 100644
--- a/src/core/lib/support/sync_posix.c
+++ b/src/core/lib/support/sync_posix.c
@@ -42,8 +42,10 @@
#include <time.h>
#include "src/core/lib/profiling/timers.h"
-#ifdef GPR_MU_COUNTERS
-gpr_atm grpc_mu_locks = 0;
+#ifdef GPR_LOW_LEVEL_COUNTERS
+gpr_atm gpr_mu_locks = 0;
+gpr_atm gpr_counter_atm_cas = 0;
+gpr_atm gpr_counter_atm_add = 0;
#endif
void gpr_mu_init(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_init(mu, NULL) == 0); }
@@ -51,8 +53,8 @@ void gpr_mu_init(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_init(mu, NULL) == 0); }
void gpr_mu_destroy(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_destroy(mu) == 0); }
void gpr_mu_lock(gpr_mu* mu) {
-#ifdef GPR_MU_COUNTERS
- gpr_atm_no_barrier_fetch_add(&grpc_mu_locks, 1);
+#ifdef GPR_LOW_LEVEL_COUNTERS
+ GPR_ATM_INC_COUNTER(gpr_mu_locks);
#endif
GPR_TIMER_BEGIN("gpr_mu_lock", 0);
GPR_ASSERT(pthread_mutex_lock(mu) == 0);
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index 3352e427cd..c2547c5147 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -101,7 +101,18 @@ typedef struct {
grpc_error *error;
} received_status;
-#define MAX_ERRORS_PER_BATCH 3
+static gpr_atm pack_received_status(received_status r) {
+ return r.is_set ? (1 | (gpr_atm)r.error) : 0;
+}
+
+static received_status unpack_received_status(gpr_atm atm) {
+ return (atm & 1) == 0
+ ? (received_status){.is_set = false, .error = GRPC_ERROR_NONE}
+ : (received_status){.is_set = true,
+ .error = (grpc_error *)(atm & ~(gpr_atm)1)};
+}
+
+#define MAX_ERRORS_PER_BATCH 4
typedef struct batch_control {
grpc_call *call;
@@ -142,8 +153,6 @@ struct grpc_call {
bool destroy_called;
/** flag indicating that cancellation is inherited */
bool cancellation_is_inherited;
- /** bitmask of live batches */
- uint8_t used_batches;
/** which ops are in-flight */
bool sent_initial_metadata;
bool sending_message;
@@ -152,6 +161,7 @@ struct grpc_call {
bool receiving_message;
bool requested_final_op;
bool received_final_op;
+ bool sent_any_op;
/* have we received initial metadata */
bool has_initial_md_been_received;
@@ -165,8 +175,8 @@ struct grpc_call {
Element 0 is initial metadata, element 1 is trailing metadata. */
grpc_metadata_array *buffered_metadata[2];
- /* Received call statuses from various sources */
- received_status status[STATUS_SOURCE_COUNT];
+ /* Packed received call statuses from various sources */
+ gpr_atm status[STATUS_SOURCE_COUNT];
/* Call data useful used for reporting. Only valid after the call has
* completed */
@@ -245,7 +255,7 @@ static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call,
static void process_data_after_md(grpc_exec_ctx *exec_ctx, batch_control *bctl);
static void post_batch_completion(grpc_exec_ctx *exec_ctx, batch_control *bctl);
static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl,
- grpc_error *error);
+ grpc_error *error, bool has_cancelled);
static void add_init_error(grpc_error **composite, grpc_error *new) {
if (new == GRPC_ERROR_NONE) return;
@@ -263,9 +273,8 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
grpc_channel_get_channel_stack(args->channel);
grpc_call *call;
GPR_TIMER_BEGIN("grpc_call_create", 0);
- call = gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size);
+ call = gpr_zalloc(sizeof(grpc_call) + channel_stack->call_stack_size);
*out_call = call;
- memset(call, 0, sizeof(grpc_call));
gpr_mu_init(&call->mu);
call->channel = args->channel;
call->cq = args->cq;
@@ -446,7 +455,8 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time);
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
- GRPC_ERROR_UNREF(c->status[i].error);
+ GRPC_ERROR_UNREF(
+ unpack_received_status(gpr_atm_no_barrier_load(&c->status[i])).error);
}
grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info, c);
@@ -479,9 +489,12 @@ void grpc_call_destroy(grpc_call *c) {
gpr_mu_lock(&c->mu);
GPR_ASSERT(!c->destroy_called);
c->destroy_called = 1;
- cancel = !c->received_final_op;
+ cancel = c->sent_any_op && !c->received_final_op;
gpr_mu_unlock(&c->mu);
- if (cancel) grpc_call_cancel(c, NULL);
+ if (cancel) {
+ cancel_with_error(&exec_ctx, c, STATUS_FROM_API_OVERRIDE,
+ GRPC_ERROR_CANCELLED);
+ }
GRPC_CALL_INTERNAL_UNREF(&exec_ctx, c, "destroy");
grpc_exec_ctx_finish(&exec_ctx);
GPR_TIMER_END("grpc_call_destroy", 0);
@@ -490,8 +503,11 @@ void grpc_call_destroy(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);
- return grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED, "Cancelled",
- NULL);
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ cancel_with_error(&exec_ctx, call, STATUS_FROM_API_OVERRIDE,
+ GRPC_ERROR_CANCELLED);
+ grpc_exec_ctx_finish(&exec_ctx);
+ return GRPC_CALL_OK;
}
static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
@@ -608,13 +624,12 @@ static void cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
*/
static bool get_final_status_from(
- grpc_call *call, status_source from_source, bool allow_ok_status,
+ grpc_call *call, grpc_error *error, bool allow_ok_status,
void (*set_value)(grpc_status_code code, void *user_data),
void *set_value_user_data, grpc_slice *details) {
grpc_status_code code;
const char *msg = NULL;
- grpc_error_get_status(call->status[from_source].error, call->send_deadline,
- &code, &msg, NULL);
+ grpc_error_get_status(error, call->send_deadline, &code, &msg, NULL);
if (code == GRPC_STATUS_OK && !allow_ok_status) {
return false;
}
@@ -632,12 +647,15 @@ static void get_final_status(grpc_call *call,
void *user_data),
void *set_value_user_data, grpc_slice *details) {
int i;
+ received_status status[STATUS_SOURCE_COUNT];
+ for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
+ status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i]));
+ }
if (grpc_call_error_trace) {
gpr_log(GPR_DEBUG, "get_final_status %s", call->is_client ? "CLI" : "SVR");
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
- if (call->status[i].is_set) {
- gpr_log(GPR_DEBUG, " %d: %s", i,
- grpc_error_string(call->status[i].error));
+ if (status[i].is_set) {
+ gpr_log(GPR_DEBUG, " %d: %s", i, grpc_error_string(status[i].error));
}
}
}
@@ -647,9 +665,9 @@ static void get_final_status(grpc_call *call,
/* search for the best status we can present: ideally the error we use has a
clearly defined grpc-status, and we'll prefer that. */
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
- if (call->status[i].is_set &&
- grpc_error_has_clear_grpc_status(call->status[i].error)) {
- if (get_final_status_from(call, (status_source)i, allow_ok_status != 0,
+ if (status[i].is_set &&
+ grpc_error_has_clear_grpc_status(status[i].error)) {
+ if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
set_value, set_value_user_data, details)) {
return;
}
@@ -657,8 +675,8 @@ static void get_final_status(grpc_call *call,
}
/* If no clearly defined status exists, search for 'anything' */
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
- if (call->status[i].is_set) {
- if (get_final_status_from(call, (status_source)i, allow_ok_status != 0,
+ if (status[i].is_set) {
+ if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
set_value, set_value_user_data, details)) {
return;
}
@@ -675,12 +693,13 @@ static void get_final_status(grpc_call *call,
static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call,
status_source source, grpc_error *error) {
- if (call->status[source].is_set) {
+ if (!gpr_atm_rel_cas(&call->status[source],
+ pack_received_status((received_status){
+ .is_set = false, .error = GRPC_ERROR_NONE}),
+ pack_received_status((received_status){
+ .is_set = true, .error = error}))) {
GRPC_ERROR_UNREF(error);
- return;
}
- call->status[source].is_set = true;
- call->status[source].error = error;
}
/*******************************************************************************
@@ -991,25 +1010,48 @@ static bool are_initial_metadata_flags_valid(uint32_t flags, bool is_client) {
return !(flags & invalid_positions);
}
-static batch_control *allocate_batch_control(grpc_call *call) {
- size_t i;
- for (i = 0; i < MAX_CONCURRENT_BATCHES; i++) {
- if ((call->used_batches & (1 << i)) == 0) {
- call->used_batches = (uint8_t)(call->used_batches | (uint8_t)(1 << i));
- return &call->active_batches[i];
- }
+static int batch_slot_for_op(grpc_op_type type) {
+ switch (type) {
+ case GRPC_OP_SEND_INITIAL_METADATA:
+ return 0;
+ case GRPC_OP_SEND_MESSAGE:
+ return 1;
+ case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
+ case GRPC_OP_SEND_STATUS_FROM_SERVER:
+ return 2;
+ case GRPC_OP_RECV_INITIAL_METADATA:
+ return 3;
+ case GRPC_OP_RECV_MESSAGE:
+ return 4;
+ case GRPC_OP_RECV_CLOSE_ON_SERVER:
+ case GRPC_OP_RECV_STATUS_ON_CLIENT:
+ return 5;
+ }
+ GPR_UNREACHABLE_CODE(return 123456789);
+}
+
+static batch_control *allocate_batch_control(grpc_call *call,
+ const grpc_op *ops,
+ size_t num_ops) {
+ int slot = batch_slot_for_op(ops[0].op);
+ for (size_t i = 1; i < num_ops; i++) {
+ int op_slot = batch_slot_for_op(ops[i].op);
+ slot = GPR_MIN(slot, op_slot);
+ }
+ batch_control *bctl = &call->active_batches[slot];
+ if (bctl->call != NULL) {
+ return NULL;
}
- return NULL;
+ memset(bctl, 0, sizeof(*bctl));
+ bctl->call = call;
+ return bctl;
}
static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_cq_completion *storage) {
batch_control *bctl = user_data;
grpc_call *call = bctl->call;
- gpr_mu_lock(&call->mu);
- call->used_batches = (uint8_t)(
- call->used_batches & ~(uint8_t)(1 << (bctl - call->active_batches)));
- gpr_mu_unlock(&call->mu);
+ bctl->call = NULL;
GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
}
@@ -1092,12 +1134,8 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx,
if (bctl->is_notify_tag_closure) {
/* unrefs bctl->error */
+ bctl->call = NULL;
grpc_closure_run(exec_ctx, bctl->notify_tag, error);
- gpr_mu_lock(&call->mu);
- bctl->call->used_batches =
- (uint8_t)(bctl->call->used_batches &
- ~(uint8_t)(1 << (bctl - bctl->call->active_batches)));
- gpr_mu_unlock(&call->mu);
GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
} else {
/* unrefs bctl->error */
@@ -1185,6 +1223,11 @@ static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
grpc_call *call = bctl->call;
gpr_mu_lock(&bctl->call->mu);
if (error != GRPC_ERROR_NONE) {
+ if (call->receiving_stream != NULL) {
+ grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
+ call->receiving_stream = NULL;
+ }
+ add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), true);
cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE,
GRPC_ERROR_REF(error));
}
@@ -1251,10 +1294,10 @@ static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx,
}
static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl,
- grpc_error *error) {
+ grpc_error *error, bool has_cancelled) {
if (error == GRPC_ERROR_NONE) return;
int idx = (int)gpr_atm_no_barrier_fetch_add(&bctl->num_errors, 1);
- if (idx == 0) {
+ if (idx == 0 && !has_cancelled) {
cancel_with_error(exec_ctx, bctl->call, STATUS_FROM_CORE,
GRPC_ERROR_REF(error));
}
@@ -1268,7 +1311,7 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
gpr_mu_lock(&call->mu);
- add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error));
+ add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false);
if (error == GRPC_ERROR_NONE) {
grpc_metadata_batch *md =
&call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
@@ -1305,10 +1348,15 @@ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp,
grpc_error *error) {
batch_control *bctl = bctlp;
- add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error));
+ add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false);
finish_batch_step(exec_ctx, bctl);
}
+static void free_no_op_completion(grpc_exec_ctx *exec_ctx, void *p,
+ grpc_cq_completion *completion) {
+ gpr_free(completion);
+}
+
static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
grpc_call *call, const grpc_op *ops,
size_t nops, void *notify_tag,
@@ -1323,32 +1371,33 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
grpc_metadata compression_md;
GPR_TIMER_BEGIN("grpc_call_start_batch", 0);
-
GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag);
- /* TODO(ctiller): this feels like it could be made lock-free */
- gpr_mu_lock(&call->mu);
- bctl = allocate_batch_control(call);
- memset(bctl, 0, sizeof(*bctl));
- bctl->call = call;
- bctl->notify_tag = notify_tag;
- bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0);
-
- grpc_transport_stream_op *stream_op = &bctl->op;
- memset(stream_op, 0, sizeof(*stream_op));
- stream_op->covered_by_poller = true;
-
if (nops == 0) {
- GRPC_CALL_INTERNAL_REF(call, "completion");
if (!is_notify_tag_closure) {
grpc_cq_begin_op(call->cq, notify_tag);
+ grpc_cq_end_op(exec_ctx, call->cq, notify_tag, GRPC_ERROR_NONE,
+ free_no_op_completion, NULL,
+ gpr_malloc(sizeof(grpc_cq_completion)));
+ } else {
+ grpc_closure_sched(exec_ctx, notify_tag, GRPC_ERROR_NONE);
}
- gpr_mu_unlock(&call->mu);
- post_batch_completion(exec_ctx, bctl);
error = GRPC_CALL_OK;
goto done;
}
+ bctl = allocate_batch_control(call, ops, nops);
+ if (bctl == NULL) {
+ return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
+ }
+ bctl->notify_tag = notify_tag;
+ bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0);
+
+ gpr_mu_lock(&call->mu);
+ grpc_transport_stream_op *stream_op = &bctl->op;
+ memset(stream_op, 0, sizeof(*stream_op));
+ stream_op->covered_by_poller = true;
+
/* rewrite batch ops into a transport op */
for (i = 0; i < nops; i++) {
op = &ops[i];
@@ -1630,6 +1679,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
grpc_closure_init(&bctl->finish_batch, finish_batch, bctl,
grpc_schedule_on_exec_ctx);
stream_op->on_complete = &bctl->finish_batch;
+ call->sent_any_op = true;
gpr_mu_unlock(&call->mu);
execute_op(exec_ctx, call, stream_op);
diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h
index b70343ddf1..7d4d0db28d 100644
--- a/src/core/lib/surface/call.h
+++ b/src/core/lib/surface/call.h
@@ -110,6 +110,7 @@ void grpc_call_log_batch(char *file, int line, gpr_log_severity severity,
/* Set a context pointer.
No thread safety guarantees are made wrt this value. */
+/* TODO(#9731): add exec_ctx to destroy */
void grpc_call_context_set(grpc_call *call, grpc_context_index elem,
void *value, void (*destroy)(void *value));
/* Get a context pointer. */
diff --git a/src/core/lib/surface/channel.c b/src/core/lib/surface/channel.c
index 429dbad7c7..d6acd392c1 100644
--- a/src/core/lib/surface/channel.c
+++ b/src/core/lib/surface/channel.c
@@ -128,7 +128,8 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
}
channel->default_authority = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_AUTHORITY,
- grpc_slice_from_copied_string(args->args[i].value.string));
+ grpc_slice_intern(
+ grpc_slice_from_static_string(args->args[i].value.string)));
}
} else if (0 ==
strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
@@ -144,7 +145,8 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
} else {
channel->default_authority = grpc_mdelem_from_slices(
exec_ctx, GRPC_MDSTR_AUTHORITY,
- grpc_slice_from_copied_string(args->args[i].value.string));
+ grpc_slice_intern(
+ grpc_slice_from_static_string(args->args[i].value.string)));
}
}
} else if (0 == strcmp(args->args[i].key,
diff --git a/src/core/lib/surface/completion_queue.c b/src/core/lib/surface/completion_queue.c
index 1830842d00..b4594817e4 100644
--- a/src/core/lib/surface/completion_queue.c
+++ b/src/core/lib/surface/completion_queue.c
@@ -96,9 +96,6 @@ struct grpc_completion_queue {
#define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1))
#define CQ_FROM_POLLSET(ps) (((grpc_completion_queue *)ps) - 1)
-static gpr_mu g_freelist_mu;
-static grpc_completion_queue *g_freelist;
-
int grpc_cq_pluck_trace;
int grpc_cq_event_timeout_trace;
@@ -113,21 +110,6 @@ int grpc_cq_event_timeout_trace;
static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc,
grpc_error *error);
-void grpc_cq_global_init(void) { gpr_mu_init(&g_freelist_mu); }
-
-void grpc_cq_global_shutdown(void) {
- gpr_mu_destroy(&g_freelist_mu);
- while (g_freelist) {
- grpc_completion_queue *next = g_freelist->next_free;
- grpc_pollset_destroy(POLLSET_FROM_CQ(g_freelist));
-#ifndef NDEBUG
- gpr_free(g_freelist->outstanding_tags);
-#endif
- gpr_free(g_freelist);
- g_freelist = next;
- }
-}
-
grpc_completion_queue *grpc_completion_queue_create(void *reserved) {
grpc_completion_queue *cc;
GPR_ASSERT(!reserved);
@@ -136,22 +118,12 @@ grpc_completion_queue *grpc_completion_queue_create(void *reserved) {
GRPC_API_TRACE("grpc_completion_queue_create(reserved=%p)", 1, (reserved));
- gpr_mu_lock(&g_freelist_mu);
- if (g_freelist == NULL) {
- gpr_mu_unlock(&g_freelist_mu);
-
- cc = gpr_malloc(sizeof(grpc_completion_queue) + grpc_pollset_size());
- grpc_pollset_init(POLLSET_FROM_CQ(cc), &cc->mu);
+ cc = gpr_zalloc(sizeof(grpc_completion_queue) + grpc_pollset_size());
+ grpc_pollset_init(POLLSET_FROM_CQ(cc), &cc->mu);
#ifndef NDEBUG
- cc->outstanding_tags = NULL;
- cc->outstanding_tag_capacity = 0;
+ cc->outstanding_tags = NULL;
+ cc->outstanding_tag_capacity = 0;
#endif
- } else {
- cc = g_freelist;
- g_freelist = g_freelist->next_free;
- gpr_mu_unlock(&g_freelist_mu);
- /* pollset already initialized */
- }
/* Initial ref is dropped by grpc_completion_queue_shutdown */
gpr_ref_init(&cc->pending_events, 1);
@@ -203,11 +175,11 @@ void grpc_cq_internal_unref(grpc_completion_queue *cc) {
#endif
if (gpr_unref(&cc->owning_refs)) {
GPR_ASSERT(cc->completed_head.next == (uintptr_t)&cc->completed_head);
- grpc_pollset_reset(POLLSET_FROM_CQ(cc));
- gpr_mu_lock(&g_freelist_mu);
- cc->next_free = g_freelist;
- g_freelist = cc;
- gpr_mu_unlock(&g_freelist_mu);
+ grpc_pollset_destroy(POLLSET_FROM_CQ(cc));
+#ifndef NDEBUG
+ gpr_free(cc->outstanding_tags);
+#endif
+ gpr_free(cc);
}
}
diff --git a/src/core/lib/surface/completion_queue.h b/src/core/lib/surface/completion_queue.h
index c1cafba5f2..5d73dd7216 100644
--- a/src/core/lib/surface/completion_queue.h
+++ b/src/core/lib/surface/completion_queue.h
@@ -99,7 +99,4 @@ bool grpc_cq_is_non_listening_server_cq(grpc_completion_queue *cc);
void grpc_cq_mark_server_cq(grpc_completion_queue *cc);
int grpc_cq_is_server_cq(grpc_completion_queue *cc);
-void grpc_cq_global_init(void);
-void grpc_cq_global_shutdown(void);
-
#endif /* GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_H */
diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c
index b338ac4c48..91bd014a0e 100644
--- a/src/core/lib/surface/init.c
+++ b/src/core/lib/surface/init.c
@@ -209,7 +209,6 @@ void grpc_init(void) {
grpc_iomgr_init();
grpc_executor_init();
gpr_timers_global_init();
- grpc_cq_global_init();
grpc_handshaker_factory_registry_init();
grpc_security_init();
for (i = 0; i < g_number_of_plugins; i++) {
@@ -236,7 +235,6 @@ void grpc_shutdown(void) {
gpr_mu_lock(&g_init_mu);
if (--g_initializations == 0) {
grpc_executor_shutdown(&exec_ctx);
- grpc_cq_global_shutdown();
grpc_iomgr_shutdown(&exec_ctx);
gpr_timers_global_destroy();
grpc_tracer_shutdown();
diff --git a/src/core/lib/surface/lame_client.c b/src/core/lib/surface/lame_client.c
index 48de0e1d5b..49bc4c114b 100644
--- a/src/core/lib/surface/lame_client.c
+++ b/src/core/lib/surface/lame_client.c
@@ -122,7 +122,7 @@ static void lame_start_transport_op(grpc_exec_ctx *exec_ctx,
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- grpc_call_element_args *args) {
+ const grpc_call_element_args *args) {
call_data *calld = elem->call_data;
gpr_atm_no_barrier_store(&calld->filled_metadata, 0);
return GRPC_ERROR_NONE;
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index 6ab1c0d94d..b360579553 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -540,7 +540,8 @@ static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *arg,
&calld->kill_zombie_closure, kill_zombie,
grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0),
grpc_schedule_on_exec_ctx);
- grpc_closure_sched(exec_ctx, &calld->kill_zombie_closure, error);
+ grpc_closure_sched(exec_ctx, &calld->kill_zombie_closure,
+ GRPC_ERROR_REF(error));
return;
}
@@ -879,7 +880,7 @@ static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd,
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- grpc_call_element_args *args) {
+ const grpc_call_element_args *args) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
memset(calld, 0, sizeof(call_data));
@@ -1015,12 +1016,10 @@ void grpc_server_register_non_listening_completion_queue(
grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved) {
GRPC_API_TRACE("grpc_server_create(%p, %p)", 2, (args, reserved));
- grpc_server *server = gpr_malloc(sizeof(grpc_server));
+ grpc_server *server = gpr_zalloc(sizeof(grpc_server));
GPR_ASSERT(grpc_is_initialized() && "call grpc_init()");
- memset(server, 0, sizeof(grpc_server));
-
gpr_mu_init(&server->mu_global);
gpr_mu_init(&server->mu_call);
@@ -1069,8 +1068,7 @@ void *grpc_server_register_method(
flags);
return NULL;
}
- m = gpr_malloc(sizeof(registered_method));
- memset(m, 0, sizeof(*m));
+ m = gpr_zalloc(sizeof(registered_method));
m->method = gpr_strdup(method);
m->host = gpr_strdup(host);
m->next = server->registered_methods;
@@ -1174,8 +1172,7 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
if (num_registered_methods > 0) {
slots = 2 * num_registered_methods;
alloc = sizeof(channel_registered_method) * slots;
- chand->registered_methods = gpr_malloc(alloc);
- memset(chand->registered_methods, 0, alloc);
+ chand->registered_methods = gpr_zalloc(alloc);
for (rm = s->registered_methods; rm; rm = rm->next) {
grpc_slice host;
bool has_host;
@@ -1198,7 +1195,9 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
crm->server_registered_method = rm;
crm->flags = rm->flags;
crm->has_host = has_host;
- crm->host = host;
+ if (has_host) {
+ crm->host = host;
+ }
crm->method = method;
}
GPR_ASSERT(slots <= UINT32_MAX);
diff --git a/src/core/lib/transport/connectivity_state.c b/src/core/lib/transport/connectivity_state.c
index 8fc5bf3e9a..afe1f6164d 100644
--- a/src/core/lib/transport/connectivity_state.c
+++ b/src/core/lib/transport/connectivity_state.c
@@ -62,7 +62,7 @@ const char *grpc_connectivity_state_name(grpc_connectivity_state state) {
void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state init_state,
const char *name) {
- tracker->current_state = init_state;
+ gpr_atm_no_barrier_store(&tracker->current_state_atm, init_state);
tracker->current_error = GRPC_ERROR_NONE;
tracker->watchers = NULL;
tracker->name = gpr_strdup(name);
@@ -89,15 +89,30 @@ void grpc_connectivity_state_destroy(grpc_exec_ctx *exec_ctx,
}
grpc_connectivity_state grpc_connectivity_state_check(
+ grpc_connectivity_state_tracker *tracker) {
+ grpc_connectivity_state cur =
+ (grpc_connectivity_state)gpr_atm_no_barrier_load(
+ &tracker->current_state_atm);
+ if (grpc_connectivity_state_trace) {
+ gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
+ grpc_connectivity_state_name(cur));
+ }
+ return cur;
+}
+
+grpc_connectivity_state grpc_connectivity_state_get(
grpc_connectivity_state_tracker *tracker, grpc_error **error) {
+ grpc_connectivity_state cur =
+ (grpc_connectivity_state)gpr_atm_no_barrier_load(
+ &tracker->current_state_atm);
if (grpc_connectivity_state_trace) {
gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
- grpc_connectivity_state_name(tracker->current_state));
+ grpc_connectivity_state_name(cur));
}
if (error != NULL) {
*error = GRPC_ERROR_REF(tracker->current_error);
}
- return tracker->current_state;
+ return cur;
}
bool grpc_connectivity_state_has_watchers(
@@ -108,6 +123,9 @@ bool grpc_connectivity_state_has_watchers(
bool grpc_connectivity_state_notify_on_state_change(
grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state *current, grpc_closure *notify) {
+ grpc_connectivity_state cur =
+ (grpc_connectivity_state)gpr_atm_no_barrier_load(
+ &tracker->current_state_atm);
if (grpc_connectivity_state_trace) {
if (current == NULL) {
gpr_log(GPR_DEBUG, "CONWATCH: %p %s: unsubscribe notify=%p", tracker,
@@ -115,7 +133,7 @@ bool grpc_connectivity_state_notify_on_state_change(
} else {
gpr_log(GPR_DEBUG, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker,
tracker->name, grpc_connectivity_state_name(*current),
- grpc_connectivity_state_name(tracker->current_state), notify);
+ grpc_connectivity_state_name(cur), notify);
}
}
if (current == NULL) {
@@ -138,8 +156,8 @@ bool grpc_connectivity_state_notify_on_state_change(
}
return false;
} else {
- if (tracker->current_state != *current) {
- *current = tracker->current_state;
+ if (cur != *current) {
+ *current = cur;
grpc_closure_sched(exec_ctx, notify,
GRPC_ERROR_REF(tracker->current_error));
} else {
@@ -149,7 +167,7 @@ bool grpc_connectivity_state_notify_on_state_change(
w->next = tracker->watchers;
tracker->watchers = w;
}
- return tracker->current_state == GRPC_CHANNEL_IDLE;
+ return cur == GRPC_CHANNEL_IDLE;
}
}
@@ -157,11 +175,14 @@ void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state state,
grpc_error *error, const char *reason) {
+ grpc_connectivity_state cur =
+ (grpc_connectivity_state)gpr_atm_no_barrier_load(
+ &tracker->current_state_atm);
grpc_connectivity_state_watcher *w;
if (grpc_connectivity_state_trace) {
const char *error_string = grpc_error_string(error);
gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s] error=%p %s", tracker,
- tracker->name, grpc_connectivity_state_name(tracker->current_state),
+ tracker->name, grpc_connectivity_state_name(cur),
grpc_connectivity_state_name(state), reason, error, error_string);
}
switch (state) {
@@ -178,13 +199,13 @@ void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
}
GRPC_ERROR_UNREF(tracker->current_error);
tracker->current_error = error;
- if (tracker->current_state == state) {
+ if (cur == state) {
return;
}
- GPR_ASSERT(tracker->current_state != GRPC_CHANNEL_SHUTDOWN);
- tracker->current_state = state;
+ GPR_ASSERT(cur != GRPC_CHANNEL_SHUTDOWN);
+ gpr_atm_no_barrier_store(&tracker->current_state_atm, state);
while ((w = tracker->watchers) != NULL) {
- *w->current = tracker->current_state;
+ *w->current = state;
tracker->watchers = w->next;
if (grpc_connectivity_state_trace) {
gpr_log(GPR_DEBUG, "NOTIFY: %p %s: %p", tracker, tracker->name,
diff --git a/src/core/lib/transport/connectivity_state.h b/src/core/lib/transport/connectivity_state.h
index 769c675b79..c9604c34dd 100644
--- a/src/core/lib/transport/connectivity_state.h
+++ b/src/core/lib/transport/connectivity_state.h
@@ -47,8 +47,8 @@ typedef struct grpc_connectivity_state_watcher {
} grpc_connectivity_state_watcher;
typedef struct {
- /** current connectivity state */
- grpc_connectivity_state current_state;
+ /** current grpc_connectivity_state */
+ gpr_atm current_state_atm;
/** error associated with state */
grpc_error *current_error;
/** all our watchers */
@@ -59,6 +59,7 @@ typedef struct {
extern int grpc_connectivity_state_trace;
+/** enum --> string conversion */
const char *grpc_connectivity_state_name(grpc_connectivity_state state);
void grpc_connectivity_state_init(grpc_connectivity_state_tracker *tracker,
@@ -68,22 +69,31 @@ void grpc_connectivity_state_destroy(grpc_exec_ctx *exec_ctx,
grpc_connectivity_state_tracker *tracker);
/** Set connectivity state; not thread safe; access must be serialized with an
- * external lock */
+ * external lock */
void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state state,
grpc_error *associated_error,
const char *reason);
+/** Return true if this connectivity state has watchers.
+ Access must be serialized with an external lock. */
bool grpc_connectivity_state_has_watchers(
grpc_connectivity_state_tracker *tracker);
+/** Return the last seen connectivity state. No need to synchronize access. */
grpc_connectivity_state grpc_connectivity_state_check(
- grpc_connectivity_state_tracker *tracker, grpc_error **current_error);
+ grpc_connectivity_state_tracker *tracker);
+
+/** Return the last seen connectivity state, and the associated error.
+ Access must be serialized with an external lock. */
+grpc_connectivity_state grpc_connectivity_state_get(
+ grpc_connectivity_state_tracker *tracker, grpc_error **error);
/** Return 1 if the channel should start connecting, 0 otherwise.
If current==NULL cancel notify if it is already queued (success==0 in that
- case) */
+ case).
+ Access must be serialized with an external lock. */
bool grpc_connectivity_state_notify_on_state_change(
grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state *current, grpc_closure *notify);
diff --git a/src/core/lib/transport/error_utils.c b/src/core/lib/transport/error_utils.c
index da77828d9c..ef55e561fb 100644
--- a/src/core/lib/transport/error_utils.c
+++ b/src/core/lib/transport/error_utils.c
@@ -44,12 +44,12 @@ static grpc_error *recursively_find_error_with_field(grpc_error *error,
}
if (grpc_error_is_special(error)) return NULL;
// Otherwise, search through its children.
- intptr_t key = 0;
- while (true) {
- grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++);
- if (child_error == NULL) break;
- grpc_error *result = recursively_find_error_with_field(child_error, which);
- if (result != NULL) return result;
+ uint8_t slot = error->first_err;
+ while (slot != UINT8_MAX) {
+ grpc_linked_error *lerr = (grpc_linked_error *)(error->arena + slot);
+ grpc_error *result = recursively_find_error_with_field(lerr->err, which);
+ if (result) return result;
+ slot = lerr->next;
}
return NULL;
}
@@ -112,13 +112,13 @@ bool grpc_error_has_clear_grpc_status(grpc_error *error) {
if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) {
return true;
}
- intptr_t key = 0;
- while (true) {
- grpc_error *child_error = gpr_avl_get(error->errs, (void *)key++);
- if (child_error == NULL) break;
- if (grpc_error_has_clear_grpc_status(child_error)) {
+ uint8_t slot = error->first_err;
+ while (slot != UINT8_MAX) {
+ grpc_linked_error *lerr = (grpc_linked_error *)(error->arena + slot);
+ if (grpc_error_has_clear_grpc_status(lerr->err)) {
return true;
}
+ slot = lerr->next;
}
return false;
}
diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c
index 489c20cbc8..f2417d8c4e 100644
--- a/src/core/lib/transport/metadata.c
+++ b/src/core/lib/transport/metadata.c
@@ -130,8 +130,7 @@ void grpc_mdctx_global_init(void) {
shard->count = 0;
gpr_atm_no_barrier_store(&shard->free_estimate, 0);
shard->capacity = INITIAL_SHARD_CAPACITY;
- shard->elems = gpr_malloc(sizeof(*shard->elems) * shard->capacity);
- memset(shard->elems, 0, sizeof(*shard->elems) * shard->capacity);
+ shard->elems = gpr_zalloc(sizeof(*shard->elems) * shard->capacity);
}
}
@@ -216,8 +215,7 @@ static void grow_mdtab(mdtab_shard *shard) {
GPR_TIMER_BEGIN("grow_mdtab", 0);
- mdtab = gpr_malloc(sizeof(interned_metadata *) * capacity);
- memset(mdtab, 0, sizeof(interned_metadata *) * capacity);
+ mdtab = gpr_zalloc(sizeof(interned_metadata *) * capacity);
for (i = 0; i < shard->capacity; i++) {
for (md = shard->elems[i]; md; md = next) {
diff --git a/src/core/lib/transport/static_metadata.c b/src/core/lib/transport/static_metadata.c
index 750711befd..c13ba230b3 100644
--- a/src/core/lib/transport/static_metadata.c
+++ b/src/core/lib/transport/static_metadata.c
@@ -55,64 +55,63 @@ static uint8_t g_bytes[] = {
112, 101, 103, 114, 112, 99, 45, 105, 110, 116, 101, 114, 110, 97, 108,
45, 101, 110, 99, 111, 100, 105, 110, 103, 45, 114, 101, 113, 117, 101,
115, 116, 117, 115, 101, 114, 45, 97, 103, 101, 110, 116, 104, 111, 115,
- 116, 108, 98, 45, 116, 111, 107, 101, 110, 108, 98, 45, 99, 111, 115,
- 116, 45, 98, 105, 110, 103, 114, 112, 99, 45, 116, 105, 109, 101, 111,
- 117, 116, 103, 114, 112, 99, 45, 116, 114, 97, 99, 105, 110, 103, 45,
- 98, 105, 110, 103, 114, 112, 99, 45, 115, 116, 97, 116, 115, 45, 98,
- 105, 110, 103, 114, 112, 99, 46, 119, 97, 105, 116, 95, 102, 111, 114,
- 95, 114, 101, 97, 100, 121, 103, 114, 112, 99, 46, 116, 105, 109, 101,
- 111, 117, 116, 103, 114, 112, 99, 46, 109, 97, 120, 95, 114, 101, 113,
- 117, 101, 115, 116, 95, 109, 101, 115, 115, 97, 103, 101, 95, 98, 121,
- 116, 101, 115, 103, 114, 112, 99, 46, 109, 97, 120, 95, 114, 101, 115,
- 112, 111, 110, 115, 101, 95, 109, 101, 115, 115, 97, 103, 101, 95, 98,
- 121, 116, 101, 115, 47, 103, 114, 112, 99, 46, 108, 98, 46, 118, 49,
- 46, 76, 111, 97, 100, 66, 97, 108, 97, 110, 99, 101, 114, 47, 66,
- 97, 108, 97, 110, 99, 101, 76, 111, 97, 100, 48, 49, 50, 105, 100,
- 101, 110, 116, 105, 116, 121, 103, 122, 105, 112, 100, 101, 102, 108, 97,
- 116, 101, 116, 114, 97, 105, 108, 101, 114, 115, 97, 112, 112, 108, 105,
- 99, 97, 116, 105, 111, 110, 47, 103, 114, 112, 99, 80, 79, 83, 84,
- 50, 48, 48, 52, 48, 52, 104, 116, 116, 112, 104, 116, 116, 112, 115,
- 103, 114, 112, 99, 71, 69, 84, 80, 85, 84, 47, 47, 105, 110, 100,
- 101, 120, 46, 104, 116, 109, 108, 50, 48, 52, 50, 48, 54, 51, 48,
- 52, 52, 48, 48, 53, 48, 48, 97, 99, 99, 101, 112, 116, 45, 99,
- 104, 97, 114, 115, 101, 116, 97, 99, 99, 101, 112, 116, 45, 101, 110,
- 99, 111, 100, 105, 110, 103, 103, 122, 105, 112, 44, 32, 100, 101, 102,
- 108, 97, 116, 101, 97, 99, 99, 101, 112, 116, 45, 108, 97, 110, 103,
- 117, 97, 103, 101, 97, 99, 99, 101, 112, 116, 45, 114, 97, 110, 103,
- 101, 115, 97, 99, 99, 101, 112, 116, 97, 99, 99, 101, 115, 115, 45,
- 99, 111, 110, 116, 114, 111, 108, 45, 97, 108, 108, 111, 119, 45, 111,
- 114, 105, 103, 105, 110, 97, 103, 101, 97, 108, 108, 111, 119, 97, 117,
- 116, 104, 111, 114, 105, 122, 97, 116, 105, 111, 110, 99, 97, 99, 104,
- 101, 45, 99, 111, 110, 116, 114, 111, 108, 99, 111, 110, 116, 101, 110,
- 116, 45, 100, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 99, 111,
- 110, 116, 101, 110, 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 99,
- 111, 110, 116, 101, 110, 116, 45, 108, 97, 110, 103, 117, 97, 103, 101,
- 99, 111, 110, 116, 101, 110, 116, 45, 108, 101, 110, 103, 116, 104, 99,
- 111, 110, 116, 101, 110, 116, 45, 108, 111, 99, 97, 116, 105, 111, 110,
- 99, 111, 110, 116, 101, 110, 116, 45, 114, 97, 110, 103, 101, 99, 111,
- 111, 107, 105, 101, 100, 97, 116, 101, 101, 116, 97, 103, 101, 120, 112,
- 101, 99, 116, 101, 120, 112, 105, 114, 101, 115, 102, 114, 111, 109, 105,
- 102, 45, 109, 97, 116, 99, 104, 105, 102, 45, 109, 111, 100, 105, 102,
- 105, 101, 100, 45, 115, 105, 110, 99, 101, 105, 102, 45, 110, 111, 110,
- 101, 45, 109, 97, 116, 99, 104, 105, 102, 45, 114, 97, 110, 103, 101,
- 105, 102, 45, 117, 110, 109, 111, 100, 105, 102, 105, 101, 100, 45, 115,
- 105, 110, 99, 101, 108, 97, 115, 116, 45, 109, 111, 100, 105, 102, 105,
- 101, 100, 108, 105, 110, 107, 108, 111, 99, 97, 116, 105, 111, 110, 109,
- 97, 120, 45, 102, 111, 114, 119, 97, 114, 100, 115, 112, 114, 111, 120,
- 121, 45, 97, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 101, 112,
- 114, 111, 120, 121, 45, 97, 117, 116, 104, 111, 114, 105, 122, 97, 116,
- 105, 111, 110, 114, 97, 110, 103, 101, 114, 101, 102, 101, 114, 101, 114,
- 114, 101, 102, 114, 101, 115, 104, 114, 101, 116, 114, 121, 45, 97, 102,
- 116, 101, 114, 115, 101, 114, 118, 101, 114, 115, 101, 116, 45, 99, 111,
- 111, 107, 105, 101, 115, 116, 114, 105, 99, 116, 45, 116, 114, 97, 110,
- 115, 112, 111, 114, 116, 45, 115, 101, 99, 117, 114, 105, 116, 121, 116,
- 114, 97, 110, 115, 102, 101, 114, 45, 101, 110, 99, 111, 100, 105, 110,
- 103, 118, 97, 114, 121, 118, 105, 97, 119, 119, 119, 45, 97, 117, 116,
- 104, 101, 110, 116, 105, 99, 97, 116, 101, 105, 100, 101, 110, 116, 105,
- 116, 121, 44, 100, 101, 102, 108, 97, 116, 101, 105, 100, 101, 110, 116,
- 105, 116, 121, 44, 103, 122, 105, 112, 100, 101, 102, 108, 97, 116, 101,
- 44, 103, 122, 105, 112, 105, 100, 101, 110, 116, 105, 116, 121, 44, 100,
- 101, 102, 108, 97, 116, 101, 44, 103, 122, 105, 112};
+ 116, 108, 98, 45, 116, 111, 107, 101, 110, 103, 114, 112, 99, 45, 116,
+ 105, 109, 101, 111, 117, 116, 103, 114, 112, 99, 45, 116, 114, 97, 99,
+ 105, 110, 103, 45, 98, 105, 110, 103, 114, 112, 99, 45, 115, 116, 97,
+ 116, 115, 45, 98, 105, 110, 103, 114, 112, 99, 46, 119, 97, 105, 116,
+ 95, 102, 111, 114, 95, 114, 101, 97, 100, 121, 103, 114, 112, 99, 46,
+ 116, 105, 109, 101, 111, 117, 116, 103, 114, 112, 99, 46, 109, 97, 120,
+ 95, 114, 101, 113, 117, 101, 115, 116, 95, 109, 101, 115, 115, 97, 103,
+ 101, 95, 98, 121, 116, 101, 115, 103, 114, 112, 99, 46, 109, 97, 120,
+ 95, 114, 101, 115, 112, 111, 110, 115, 101, 95, 109, 101, 115, 115, 97,
+ 103, 101, 95, 98, 121, 116, 101, 115, 47, 103, 114, 112, 99, 46, 108,
+ 98, 46, 118, 49, 46, 76, 111, 97, 100, 66, 97, 108, 97, 110, 99,
+ 101, 114, 47, 66, 97, 108, 97, 110, 99, 101, 76, 111, 97, 100, 48,
+ 49, 50, 105, 100, 101, 110, 116, 105, 116, 121, 103, 122, 105, 112, 100,
+ 101, 102, 108, 97, 116, 101, 116, 114, 97, 105, 108, 101, 114, 115, 97,
+ 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 103, 114, 112, 99,
+ 80, 79, 83, 84, 50, 48, 48, 52, 48, 52, 104, 116, 116, 112, 104,
+ 116, 116, 112, 115, 103, 114, 112, 99, 71, 69, 84, 80, 85, 84, 47,
+ 47, 105, 110, 100, 101, 120, 46, 104, 116, 109, 108, 50, 48, 52, 50,
+ 48, 54, 51, 48, 52, 52, 48, 48, 53, 48, 48, 97, 99, 99, 101,
+ 112, 116, 45, 99, 104, 97, 114, 115, 101, 116, 97, 99, 99, 101, 112,
+ 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 103, 122, 105, 112, 44,
+ 32, 100, 101, 102, 108, 97, 116, 101, 97, 99, 99, 101, 112, 116, 45,
+ 108, 97, 110, 103, 117, 97, 103, 101, 97, 99, 99, 101, 112, 116, 45,
+ 114, 97, 110, 103, 101, 115, 97, 99, 99, 101, 112, 116, 97, 99, 99,
+ 101, 115, 115, 45, 99, 111, 110, 116, 114, 111, 108, 45, 97, 108, 108,
+ 111, 119, 45, 111, 114, 105, 103, 105, 110, 97, 103, 101, 97, 108, 108,
+ 111, 119, 97, 117, 116, 104, 111, 114, 105, 122, 97, 116, 105, 111, 110,
+ 99, 97, 99, 104, 101, 45, 99, 111, 110, 116, 114, 111, 108, 99, 111,
+ 110, 116, 101, 110, 116, 45, 100, 105, 115, 112, 111, 115, 105, 116, 105,
+ 111, 110, 99, 111, 110, 116, 101, 110, 116, 45, 101, 110, 99, 111, 100,
+ 105, 110, 103, 99, 111, 110, 116, 101, 110, 116, 45, 108, 97, 110, 103,
+ 117, 97, 103, 101, 99, 111, 110, 116, 101, 110, 116, 45, 108, 101, 110,
+ 103, 116, 104, 99, 111, 110, 116, 101, 110, 116, 45, 108, 111, 99, 97,
+ 116, 105, 111, 110, 99, 111, 110, 116, 101, 110, 116, 45, 114, 97, 110,
+ 103, 101, 99, 111, 111, 107, 105, 101, 100, 97, 116, 101, 101, 116, 97,
+ 103, 101, 120, 112, 101, 99, 116, 101, 120, 112, 105, 114, 101, 115, 102,
+ 114, 111, 109, 105, 102, 45, 109, 97, 116, 99, 104, 105, 102, 45, 109,
+ 111, 100, 105, 102, 105, 101, 100, 45, 115, 105, 110, 99, 101, 105, 102,
+ 45, 110, 111, 110, 101, 45, 109, 97, 116, 99, 104, 105, 102, 45, 114,
+ 97, 110, 103, 101, 105, 102, 45, 117, 110, 109, 111, 100, 105, 102, 105,
+ 101, 100, 45, 115, 105, 110, 99, 101, 108, 97, 115, 116, 45, 109, 111,
+ 100, 105, 102, 105, 101, 100, 108, 105, 110, 107, 108, 111, 99, 97, 116,
+ 105, 111, 110, 109, 97, 120, 45, 102, 111, 114, 119, 97, 114, 100, 115,
+ 112, 114, 111, 120, 121, 45, 97, 117, 116, 104, 101, 110, 116, 105, 99,
+ 97, 116, 101, 112, 114, 111, 120, 121, 45, 97, 117, 116, 104, 111, 114,
+ 105, 122, 97, 116, 105, 111, 110, 114, 97, 110, 103, 101, 114, 101, 102,
+ 101, 114, 101, 114, 114, 101, 102, 114, 101, 115, 104, 114, 101, 116, 114,
+ 121, 45, 97, 102, 116, 101, 114, 115, 101, 114, 118, 101, 114, 115, 101,
+ 116, 45, 99, 111, 111, 107, 105, 101, 115, 116, 114, 105, 99, 116, 45,
+ 116, 114, 97, 110, 115, 112, 111, 114, 116, 45, 115, 101, 99, 117, 114,
+ 105, 116, 121, 116, 114, 97, 110, 115, 102, 101, 114, 45, 101, 110, 99,
+ 111, 100, 105, 110, 103, 118, 97, 114, 121, 118, 105, 97, 119, 119, 119,
+ 45, 97, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 101, 105, 100,
+ 101, 110, 116, 105, 116, 121, 44, 100, 101, 102, 108, 97, 116, 101, 105,
+ 100, 101, 110, 116, 105, 116, 121, 44, 103, 122, 105, 112, 100, 101, 102,
+ 108, 97, 116, 101, 44, 103, 122, 105, 112, 105, 100, 101, 110, 116, 105,
+ 116, 121, 44, 100, 101, 102, 108, 97, 116, 101, 44, 103, 122, 105, 112};
static void static_ref(void *unused) {}
static void static_unref(grpc_exec_ctx *exec_ctx, void *unused) {}
@@ -221,7 +220,6 @@ grpc_slice_refcount grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT] = {
{&grpc_static_metadata_vtable, &static_sub_refcnt},
{&grpc_static_metadata_vtable, &static_sub_refcnt},
{&grpc_static_metadata_vtable, &static_sub_refcnt},
- {&grpc_static_metadata_vtable, &static_sub_refcnt},
};
const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = {
@@ -258,188 +256,186 @@ const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = {
{.refcount = &grpc_static_metadata_refcounts[15],
.data.refcounted = {g_bytes + 166, 8}},
{.refcount = &grpc_static_metadata_refcounts[16],
- .data.refcounted = {g_bytes + 174, 11}},
+ .data.refcounted = {g_bytes + 174, 12}},
{.refcount = &grpc_static_metadata_refcounts[17],
- .data.refcounted = {g_bytes + 185, 12}},
+ .data.refcounted = {g_bytes + 186, 16}},
{.refcount = &grpc_static_metadata_refcounts[18],
- .data.refcounted = {g_bytes + 197, 16}},
+ .data.refcounted = {g_bytes + 202, 14}},
{.refcount = &grpc_static_metadata_refcounts[19],
- .data.refcounted = {g_bytes + 213, 14}},
+ .data.refcounted = {g_bytes + 216, 0}},
{.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}},
+ .data.refcounted = {g_bytes + 216, 19}},
{.refcount = &grpc_static_metadata_refcounts[21],
- .data.refcounted = {g_bytes + 227, 19}},
+ .data.refcounted = {g_bytes + 235, 12}},
{.refcount = &grpc_static_metadata_refcounts[22],
- .data.refcounted = {g_bytes + 246, 12}},
+ .data.refcounted = {g_bytes + 247, 30}},
{.refcount = &grpc_static_metadata_refcounts[23],
- .data.refcounted = {g_bytes + 258, 30}},
+ .data.refcounted = {g_bytes + 277, 31}},
{.refcount = &grpc_static_metadata_refcounts[24],
- .data.refcounted = {g_bytes + 288, 31}},
+ .data.refcounted = {g_bytes + 308, 36}},
{.refcount = &grpc_static_metadata_refcounts[25],
- .data.refcounted = {g_bytes + 319, 36}},
+ .data.refcounted = {g_bytes + 344, 1}},
{.refcount = &grpc_static_metadata_refcounts[26],
- .data.refcounted = {g_bytes + 355, 1}},
+ .data.refcounted = {g_bytes + 345, 1}},
{.refcount = &grpc_static_metadata_refcounts[27],
- .data.refcounted = {g_bytes + 356, 1}},
+ .data.refcounted = {g_bytes + 346, 1}},
{.refcount = &grpc_static_metadata_refcounts[28],
- .data.refcounted = {g_bytes + 357, 1}},
+ .data.refcounted = {g_bytes + 347, 8}},
{.refcount = &grpc_static_metadata_refcounts[29],
- .data.refcounted = {g_bytes + 358, 8}},
+ .data.refcounted = {g_bytes + 355, 4}},
{.refcount = &grpc_static_metadata_refcounts[30],
- .data.refcounted = {g_bytes + 366, 4}},
+ .data.refcounted = {g_bytes + 359, 7}},
{.refcount = &grpc_static_metadata_refcounts[31],
- .data.refcounted = {g_bytes + 370, 7}},
+ .data.refcounted = {g_bytes + 366, 8}},
{.refcount = &grpc_static_metadata_refcounts[32],
- .data.refcounted = {g_bytes + 377, 8}},
+ .data.refcounted = {g_bytes + 374, 16}},
{.refcount = &grpc_static_metadata_refcounts[33],
- .data.refcounted = {g_bytes + 385, 16}},
+ .data.refcounted = {g_bytes + 390, 4}},
{.refcount = &grpc_static_metadata_refcounts[34],
- .data.refcounted = {g_bytes + 401, 4}},
+ .data.refcounted = {g_bytes + 394, 3}},
{.refcount = &grpc_static_metadata_refcounts[35],
- .data.refcounted = {g_bytes + 405, 3}},
+ .data.refcounted = {g_bytes + 397, 3}},
{.refcount = &grpc_static_metadata_refcounts[36],
- .data.refcounted = {g_bytes + 408, 3}},
+ .data.refcounted = {g_bytes + 400, 4}},
{.refcount = &grpc_static_metadata_refcounts[37],
- .data.refcounted = {g_bytes + 411, 4}},
+ .data.refcounted = {g_bytes + 404, 5}},
{.refcount = &grpc_static_metadata_refcounts[38],
- .data.refcounted = {g_bytes + 415, 5}},
+ .data.refcounted = {g_bytes + 409, 4}},
{.refcount = &grpc_static_metadata_refcounts[39],
- .data.refcounted = {g_bytes + 420, 4}},
+ .data.refcounted = {g_bytes + 413, 3}},
{.refcount = &grpc_static_metadata_refcounts[40],
- .data.refcounted = {g_bytes + 424, 3}},
+ .data.refcounted = {g_bytes + 416, 3}},
{.refcount = &grpc_static_metadata_refcounts[41],
- .data.refcounted = {g_bytes + 427, 3}},
+ .data.refcounted = {g_bytes + 419, 1}},
{.refcount = &grpc_static_metadata_refcounts[42],
- .data.refcounted = {g_bytes + 430, 1}},
+ .data.refcounted = {g_bytes + 420, 11}},
{.refcount = &grpc_static_metadata_refcounts[43],
- .data.refcounted = {g_bytes + 431, 11}},
+ .data.refcounted = {g_bytes + 431, 3}},
{.refcount = &grpc_static_metadata_refcounts[44],
- .data.refcounted = {g_bytes + 442, 3}},
+ .data.refcounted = {g_bytes + 434, 3}},
{.refcount = &grpc_static_metadata_refcounts[45],
- .data.refcounted = {g_bytes + 445, 3}},
+ .data.refcounted = {g_bytes + 437, 3}},
{.refcount = &grpc_static_metadata_refcounts[46],
- .data.refcounted = {g_bytes + 448, 3}},
+ .data.refcounted = {g_bytes + 440, 3}},
{.refcount = &grpc_static_metadata_refcounts[47],
- .data.refcounted = {g_bytes + 451, 3}},
+ .data.refcounted = {g_bytes + 443, 3}},
{.refcount = &grpc_static_metadata_refcounts[48],
- .data.refcounted = {g_bytes + 454, 3}},
+ .data.refcounted = {g_bytes + 446, 14}},
{.refcount = &grpc_static_metadata_refcounts[49],
- .data.refcounted = {g_bytes + 457, 14}},
+ .data.refcounted = {g_bytes + 460, 15}},
{.refcount = &grpc_static_metadata_refcounts[50],
- .data.refcounted = {g_bytes + 471, 15}},
+ .data.refcounted = {g_bytes + 475, 13}},
{.refcount = &grpc_static_metadata_refcounts[51],
- .data.refcounted = {g_bytes + 486, 13}},
+ .data.refcounted = {g_bytes + 488, 15}},
{.refcount = &grpc_static_metadata_refcounts[52],
- .data.refcounted = {g_bytes + 499, 15}},
+ .data.refcounted = {g_bytes + 503, 13}},
{.refcount = &grpc_static_metadata_refcounts[53],
- .data.refcounted = {g_bytes + 514, 13}},
+ .data.refcounted = {g_bytes + 516, 6}},
{.refcount = &grpc_static_metadata_refcounts[54],
- .data.refcounted = {g_bytes + 527, 6}},
+ .data.refcounted = {g_bytes + 522, 27}},
{.refcount = &grpc_static_metadata_refcounts[55],
- .data.refcounted = {g_bytes + 533, 27}},
+ .data.refcounted = {g_bytes + 549, 3}},
{.refcount = &grpc_static_metadata_refcounts[56],
- .data.refcounted = {g_bytes + 560, 3}},
+ .data.refcounted = {g_bytes + 552, 5}},
{.refcount = &grpc_static_metadata_refcounts[57],
- .data.refcounted = {g_bytes + 563, 5}},
+ .data.refcounted = {g_bytes + 557, 13}},
{.refcount = &grpc_static_metadata_refcounts[58],
- .data.refcounted = {g_bytes + 568, 13}},
+ .data.refcounted = {g_bytes + 570, 13}},
{.refcount = &grpc_static_metadata_refcounts[59],
- .data.refcounted = {g_bytes + 581, 13}},
+ .data.refcounted = {g_bytes + 583, 19}},
{.refcount = &grpc_static_metadata_refcounts[60],
- .data.refcounted = {g_bytes + 594, 19}},
+ .data.refcounted = {g_bytes + 602, 16}},
{.refcount = &grpc_static_metadata_refcounts[61],
- .data.refcounted = {g_bytes + 613, 16}},
+ .data.refcounted = {g_bytes + 618, 16}},
{.refcount = &grpc_static_metadata_refcounts[62],
- .data.refcounted = {g_bytes + 629, 16}},
+ .data.refcounted = {g_bytes + 634, 14}},
{.refcount = &grpc_static_metadata_refcounts[63],
- .data.refcounted = {g_bytes + 645, 14}},
+ .data.refcounted = {g_bytes + 648, 16}},
{.refcount = &grpc_static_metadata_refcounts[64],
- .data.refcounted = {g_bytes + 659, 16}},
+ .data.refcounted = {g_bytes + 664, 13}},
{.refcount = &grpc_static_metadata_refcounts[65],
- .data.refcounted = {g_bytes + 675, 13}},
+ .data.refcounted = {g_bytes + 677, 6}},
{.refcount = &grpc_static_metadata_refcounts[66],
- .data.refcounted = {g_bytes + 688, 6}},
+ .data.refcounted = {g_bytes + 683, 4}},
{.refcount = &grpc_static_metadata_refcounts[67],
- .data.refcounted = {g_bytes + 694, 4}},
+ .data.refcounted = {g_bytes + 687, 4}},
{.refcount = &grpc_static_metadata_refcounts[68],
- .data.refcounted = {g_bytes + 698, 4}},
+ .data.refcounted = {g_bytes + 691, 6}},
{.refcount = &grpc_static_metadata_refcounts[69],
- .data.refcounted = {g_bytes + 702, 6}},
+ .data.refcounted = {g_bytes + 697, 7}},
{.refcount = &grpc_static_metadata_refcounts[70],
- .data.refcounted = {g_bytes + 708, 7}},
+ .data.refcounted = {g_bytes + 704, 4}},
{.refcount = &grpc_static_metadata_refcounts[71],
- .data.refcounted = {g_bytes + 715, 4}},
+ .data.refcounted = {g_bytes + 708, 8}},
{.refcount = &grpc_static_metadata_refcounts[72],
- .data.refcounted = {g_bytes + 719, 8}},
+ .data.refcounted = {g_bytes + 716, 17}},
{.refcount = &grpc_static_metadata_refcounts[73],
- .data.refcounted = {g_bytes + 727, 17}},
+ .data.refcounted = {g_bytes + 733, 13}},
{.refcount = &grpc_static_metadata_refcounts[74],
- .data.refcounted = {g_bytes + 744, 13}},
+ .data.refcounted = {g_bytes + 746, 8}},
{.refcount = &grpc_static_metadata_refcounts[75],
- .data.refcounted = {g_bytes + 757, 8}},
+ .data.refcounted = {g_bytes + 754, 19}},
{.refcount = &grpc_static_metadata_refcounts[76],
- .data.refcounted = {g_bytes + 765, 19}},
+ .data.refcounted = {g_bytes + 773, 13}},
{.refcount = &grpc_static_metadata_refcounts[77],
- .data.refcounted = {g_bytes + 784, 13}},
+ .data.refcounted = {g_bytes + 786, 4}},
{.refcount = &grpc_static_metadata_refcounts[78],
- .data.refcounted = {g_bytes + 797, 4}},
+ .data.refcounted = {g_bytes + 790, 8}},
{.refcount = &grpc_static_metadata_refcounts[79],
- .data.refcounted = {g_bytes + 801, 8}},
+ .data.refcounted = {g_bytes + 798, 12}},
{.refcount = &grpc_static_metadata_refcounts[80],
- .data.refcounted = {g_bytes + 809, 12}},
+ .data.refcounted = {g_bytes + 810, 18}},
{.refcount = &grpc_static_metadata_refcounts[81],
- .data.refcounted = {g_bytes + 821, 18}},
+ .data.refcounted = {g_bytes + 828, 19}},
{.refcount = &grpc_static_metadata_refcounts[82],
- .data.refcounted = {g_bytes + 839, 19}},
+ .data.refcounted = {g_bytes + 847, 5}},
{.refcount = &grpc_static_metadata_refcounts[83],
- .data.refcounted = {g_bytes + 858, 5}},
+ .data.refcounted = {g_bytes + 852, 7}},
{.refcount = &grpc_static_metadata_refcounts[84],
- .data.refcounted = {g_bytes + 863, 7}},
+ .data.refcounted = {g_bytes + 859, 7}},
{.refcount = &grpc_static_metadata_refcounts[85],
- .data.refcounted = {g_bytes + 870, 7}},
+ .data.refcounted = {g_bytes + 866, 11}},
{.refcount = &grpc_static_metadata_refcounts[86],
- .data.refcounted = {g_bytes + 877, 11}},
+ .data.refcounted = {g_bytes + 877, 6}},
{.refcount = &grpc_static_metadata_refcounts[87],
- .data.refcounted = {g_bytes + 888, 6}},
+ .data.refcounted = {g_bytes + 883, 10}},
{.refcount = &grpc_static_metadata_refcounts[88],
- .data.refcounted = {g_bytes + 894, 10}},
+ .data.refcounted = {g_bytes + 893, 25}},
{.refcount = &grpc_static_metadata_refcounts[89],
- .data.refcounted = {g_bytes + 904, 25}},
+ .data.refcounted = {g_bytes + 918, 17}},
{.refcount = &grpc_static_metadata_refcounts[90],
- .data.refcounted = {g_bytes + 929, 17}},
+ .data.refcounted = {g_bytes + 935, 4}},
{.refcount = &grpc_static_metadata_refcounts[91],
- .data.refcounted = {g_bytes + 946, 4}},
+ .data.refcounted = {g_bytes + 939, 3}},
{.refcount = &grpc_static_metadata_refcounts[92],
- .data.refcounted = {g_bytes + 950, 3}},
+ .data.refcounted = {g_bytes + 942, 16}},
{.refcount = &grpc_static_metadata_refcounts[93],
- .data.refcounted = {g_bytes + 953, 16}},
+ .data.refcounted = {g_bytes + 958, 16}},
{.refcount = &grpc_static_metadata_refcounts[94],
- .data.refcounted = {g_bytes + 969, 16}},
+ .data.refcounted = {g_bytes + 974, 13}},
{.refcount = &grpc_static_metadata_refcounts[95],
- .data.refcounted = {g_bytes + 985, 13}},
+ .data.refcounted = {g_bytes + 987, 12}},
{.refcount = &grpc_static_metadata_refcounts[96],
- .data.refcounted = {g_bytes + 998, 12}},
- {.refcount = &grpc_static_metadata_refcounts[97],
- .data.refcounted = {g_bytes + 1010, 21}},
+ .data.refcounted = {g_bytes + 999, 21}},
};
uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 6, 6, 8, 8};
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 6, 6, 8, 8};
static const int8_t elems_r[] = {
- 10, 8, -3, 0, 9, 21, -76, 22, 0, 10, -7, 20, 0, 19, 18, 17,
- 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, -49, -50, 16, -52, -53, -54, -54, -55, -56, -57, 0, 38, 37, 36, 35,
- 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19,
- 18, 17, 16, 15, 14, 13, 12, 15, 14, 13, 12, 11, 10, 9, 8, 0};
+ 10, 8, -3, 0, 9, 21, -75, 22, 0, 10, -7, 20, 0, 19, 18, 17,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -48, -49, 16, -51, -52, -53, -54, -54, -55, -56, -57, 0, 37, 36, 35, 34,
+ 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18,
+ 17, 16, 15, 14, 13, 12, 11, 14, 13, 12, 11, 10, 9, 8, 0};
static uint32_t elems_phash(uint32_t i) {
- i -= 42;
- uint32_t x = i % 96;
- uint32_t y = i / 96;
+ i -= 41;
+ uint32_t x = i % 95;
+ uint32_t y = i / 95;
uint32_t h = x;
if (y < GPR_ARRAY_SIZE(elems_r)) {
uint32_t delta = (uint32_t)elems_r[y];
@@ -449,30 +445,29 @@ static uint32_t elems_phash(uint32_t i) {
}
static const uint16_t elem_keys[] = {
- 1009, 1010, 1011, 240, 241, 242, 243, 244, 138, 139, 42, 43,
- 429, 430, 431, 911, 912, 913, 712, 713, 1098, 522, 714, 1294,
- 1392, 1490, 1588, 4822, 4920, 4951, 5116, 5214, 5312, 1111, 5410, 5508,
- 5606, 5704, 5802, 5900, 5998, 6096, 6194, 6292, 6390, 6488, 6586, 6684,
- 6782, 6880, 6978, 7076, 7174, 7272, 7370, 7468, 7566, 7664, 7762, 7860,
- 7958, 8056, 8154, 8252, 8350, 1074, 1075, 1076, 1077, 8448, 8546, 8644,
- 8742, 8840, 8938, 9036, 9134, 314, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 132, 231, 232, 0, 0, 0, 0, 0,
+ 998, 999, 1000, 237, 238, 239, 240, 241, 136, 137, 41, 42,
+ 424, 425, 426, 901, 902, 903, 704, 705, 1086, 516, 706, 1280,
+ 1377, 1474, 4675, 4772, 4803, 4966, 5063, 5160, 5257, 1099, 5354, 5451,
+ 5548, 5645, 5742, 5839, 5936, 6033, 6130, 6227, 6324, 6421, 6518, 6615,
+ 6712, 6809, 6906, 7003, 7100, 7197, 7294, 7391, 7488, 7585, 7682, 7779,
+ 7876, 7973, 8070, 8167, 8264, 1063, 1064, 1065, 1066, 8361, 8458, 8555,
+ 8652, 8749, 8846, 8943, 310, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 130, 228, 229, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0};
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static const uint8_t elem_idxs[] = {
- 74, 77, 75, 19, 20, 21, 22, 23, 15, 16, 17, 18, 11, 12, 13,
- 3, 4, 5, 0, 1, 41, 6, 2, 70, 48, 55, 56, 24, 25, 26,
- 27, 28, 29, 7, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 42, 43, 44, 45, 46, 47, 49, 50, 51, 52, 53, 54, 57, 58, 59,
- 60, 61, 62, 63, 64, 76, 78, 79, 80, 65, 66, 67, 68, 69, 71,
- 72, 73, 14, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 8, 9, 10};
+ 73, 76, 74, 19, 20, 21, 22, 23, 15, 16, 17, 18, 11, 12, 13,
+ 3, 4, 5, 0, 1, 41, 6, 2, 69, 48, 55, 24, 25, 26, 27,
+ 28, 29, 30, 7, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 42,
+ 43, 44, 45, 46, 47, 49, 50, 51, 52, 53, 54, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 75, 77, 78, 79, 65, 66, 67, 68, 70, 71,
+ 72, 14, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 8, 9, 10};
grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) {
if (a == -1 || b == -1) return GRPC_MDNULL;
- uint32_t k = (uint32_t)(a * 98 + b);
+ uint32_t k = (uint32_t)(a * 97 + b);
uint32_t h = elems_phash(k);
return h < GPR_ARRAY_SIZE(elem_keys) && elem_keys[h] == k
? GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[elem_idxs[h]],
@@ -483,328 +478,324 @@ grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) {
grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = {
{{.refcount = &grpc_static_metadata_refcounts[7],
.data.refcounted = {g_bytes + 50, 11}},
- {.refcount = &grpc_static_metadata_refcounts[26],
- .data.refcounted = {g_bytes + 355, 1}}},
+ {.refcount = &grpc_static_metadata_refcounts[25],
+ .data.refcounted = {g_bytes + 344, 1}}},
{{.refcount = &grpc_static_metadata_refcounts[7],
.data.refcounted = {g_bytes + 50, 11}},
- {.refcount = &grpc_static_metadata_refcounts[27],
- .data.refcounted = {g_bytes + 356, 1}}},
+ {.refcount = &grpc_static_metadata_refcounts[26],
+ .data.refcounted = {g_bytes + 345, 1}}},
{{.refcount = &grpc_static_metadata_refcounts[7],
.data.refcounted = {g_bytes + 50, 11}},
+ {.refcount = &grpc_static_metadata_refcounts[27],
+ .data.refcounted = {g_bytes + 346, 1}}},
+ {{.refcount = &grpc_static_metadata_refcounts[9],
+ .data.refcounted = {g_bytes + 77, 13}},
{.refcount = &grpc_static_metadata_refcounts[28],
- .data.refcounted = {g_bytes + 357, 1}}},
+ .data.refcounted = {g_bytes + 347, 8}}},
{{.refcount = &grpc_static_metadata_refcounts[9],
.data.refcounted = {g_bytes + 77, 13}},
{.refcount = &grpc_static_metadata_refcounts[29],
- .data.refcounted = {g_bytes + 358, 8}}},
+ .data.refcounted = {g_bytes + 355, 4}}},
{{.refcount = &grpc_static_metadata_refcounts[9],
.data.refcounted = {g_bytes + 77, 13}},
{.refcount = &grpc_static_metadata_refcounts[30],
- .data.refcounted = {g_bytes + 366, 4}}},
- {{.refcount = &grpc_static_metadata_refcounts[9],
- .data.refcounted = {g_bytes + 77, 13}},
- {.refcount = &grpc_static_metadata_refcounts[31],
- .data.refcounted = {g_bytes + 370, 7}}},
+ .data.refcounted = {g_bytes + 359, 7}}},
{{.refcount = &grpc_static_metadata_refcounts[5],
.data.refcounted = {g_bytes + 36, 2}},
- {.refcount = &grpc_static_metadata_refcounts[32],
- .data.refcounted = {g_bytes + 377, 8}}},
+ {.refcount = &grpc_static_metadata_refcounts[31],
+ .data.refcounted = {g_bytes + 366, 8}}},
{{.refcount = &grpc_static_metadata_refcounts[11],
.data.refcounted = {g_bytes + 110, 12}},
- {.refcount = &grpc_static_metadata_refcounts[33],
- .data.refcounted = {g_bytes + 385, 16}}},
+ {.refcount = &grpc_static_metadata_refcounts[32],
+ .data.refcounted = {g_bytes + 374, 16}}},
{{.refcount = &grpc_static_metadata_refcounts[1],
.data.refcounted = {g_bytes + 5, 7}},
- {.refcount = &grpc_static_metadata_refcounts[34],
- .data.refcounted = {g_bytes + 401, 4}}},
+ {.refcount = &grpc_static_metadata_refcounts[33],
+ .data.refcounted = {g_bytes + 390, 4}}},
{{.refcount = &grpc_static_metadata_refcounts[2],
.data.refcounted = {g_bytes + 12, 7}},
- {.refcount = &grpc_static_metadata_refcounts[35],
- .data.refcounted = {g_bytes + 405, 3}}},
+ {.refcount = &grpc_static_metadata_refcounts[34],
+ .data.refcounted = {g_bytes + 394, 3}}},
{{.refcount = &grpc_static_metadata_refcounts[2],
.data.refcounted = {g_bytes + 12, 7}},
+ {.refcount = &grpc_static_metadata_refcounts[35],
+ .data.refcounted = {g_bytes + 397, 3}}},
+ {{.refcount = &grpc_static_metadata_refcounts[4],
+ .data.refcounted = {g_bytes + 29, 7}},
{.refcount = &grpc_static_metadata_refcounts[36],
- .data.refcounted = {g_bytes + 408, 3}}},
+ .data.refcounted = {g_bytes + 400, 4}}},
{{.refcount = &grpc_static_metadata_refcounts[4],
.data.refcounted = {g_bytes + 29, 7}},
{.refcount = &grpc_static_metadata_refcounts[37],
- .data.refcounted = {g_bytes + 411, 4}}},
+ .data.refcounted = {g_bytes + 404, 5}}},
{{.refcount = &grpc_static_metadata_refcounts[4],
.data.refcounted = {g_bytes + 29, 7}},
{.refcount = &grpc_static_metadata_refcounts[38],
- .data.refcounted = {g_bytes + 415, 5}}},
- {{.refcount = &grpc_static_metadata_refcounts[4],
- .data.refcounted = {g_bytes + 29, 7}},
- {.refcount = &grpc_static_metadata_refcounts[39],
- .data.refcounted = {g_bytes + 420, 4}}},
+ .data.refcounted = {g_bytes + 409, 4}}},
{{.refcount = &grpc_static_metadata_refcounts[3],
.data.refcounted = {g_bytes + 19, 10}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[1],
.data.refcounted = {g_bytes + 5, 7}},
- {.refcount = &grpc_static_metadata_refcounts[40],
- .data.refcounted = {g_bytes + 424, 3}}},
+ {.refcount = &grpc_static_metadata_refcounts[39],
+ .data.refcounted = {g_bytes + 413, 3}}},
{{.refcount = &grpc_static_metadata_refcounts[1],
.data.refcounted = {g_bytes + 5, 7}},
- {.refcount = &grpc_static_metadata_refcounts[41],
- .data.refcounted = {g_bytes + 427, 3}}},
+ {.refcount = &grpc_static_metadata_refcounts[40],
+ .data.refcounted = {g_bytes + 416, 3}}},
{{.refcount = &grpc_static_metadata_refcounts[0],
.data.refcounted = {g_bytes + 0, 5}},
- {.refcount = &grpc_static_metadata_refcounts[42],
- .data.refcounted = {g_bytes + 430, 1}}},
+ {.refcount = &grpc_static_metadata_refcounts[41],
+ .data.refcounted = {g_bytes + 419, 1}}},
{{.refcount = &grpc_static_metadata_refcounts[0],
.data.refcounted = {g_bytes + 0, 5}},
+ {.refcount = &grpc_static_metadata_refcounts[42],
+ .data.refcounted = {g_bytes + 420, 11}}},
+ {{.refcount = &grpc_static_metadata_refcounts[2],
+ .data.refcounted = {g_bytes + 12, 7}},
{.refcount = &grpc_static_metadata_refcounts[43],
- .data.refcounted = {g_bytes + 431, 11}}},
+ .data.refcounted = {g_bytes + 431, 3}}},
{{.refcount = &grpc_static_metadata_refcounts[2],
.data.refcounted = {g_bytes + 12, 7}},
{.refcount = &grpc_static_metadata_refcounts[44],
- .data.refcounted = {g_bytes + 442, 3}}},
+ .data.refcounted = {g_bytes + 434, 3}}},
{{.refcount = &grpc_static_metadata_refcounts[2],
.data.refcounted = {g_bytes + 12, 7}},
{.refcount = &grpc_static_metadata_refcounts[45],
- .data.refcounted = {g_bytes + 445, 3}}},
+ .data.refcounted = {g_bytes + 437, 3}}},
{{.refcount = &grpc_static_metadata_refcounts[2],
.data.refcounted = {g_bytes + 12, 7}},
{.refcount = &grpc_static_metadata_refcounts[46],
- .data.refcounted = {g_bytes + 448, 3}}},
+ .data.refcounted = {g_bytes + 440, 3}}},
{{.refcount = &grpc_static_metadata_refcounts[2],
.data.refcounted = {g_bytes + 12, 7}},
{.refcount = &grpc_static_metadata_refcounts[47],
- .data.refcounted = {g_bytes + 451, 3}}},
- {{.refcount = &grpc_static_metadata_refcounts[2],
- .data.refcounted = {g_bytes + 12, 7}},
- {.refcount = &grpc_static_metadata_refcounts[48],
- .data.refcounted = {g_bytes + 454, 3}}},
+ .data.refcounted = {g_bytes + 443, 3}}},
+ {{.refcount = &grpc_static_metadata_refcounts[48],
+ .data.refcounted = {g_bytes + 446, 14}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[49],
- .data.refcounted = {g_bytes + 457, 14}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
- {{.refcount = &grpc_static_metadata_refcounts[50],
- .data.refcounted = {g_bytes + 471, 15}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
- {{.refcount = &grpc_static_metadata_refcounts[50],
- .data.refcounted = {g_bytes + 471, 15}},
- {.refcount = &grpc_static_metadata_refcounts[51],
- .data.refcounted = {g_bytes + 486, 13}}},
+ .data.refcounted = {g_bytes + 460, 15}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
+ {{.refcount = &grpc_static_metadata_refcounts[49],
+ .data.refcounted = {g_bytes + 460, 15}},
+ {.refcount = &grpc_static_metadata_refcounts[50],
+ .data.refcounted = {g_bytes + 475, 13}}},
+ {{.refcount = &grpc_static_metadata_refcounts[51],
+ .data.refcounted = {g_bytes + 488, 15}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[52],
- .data.refcounted = {g_bytes + 499, 15}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 503, 13}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[53],
- .data.refcounted = {g_bytes + 514, 13}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 516, 6}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[54],
- .data.refcounted = {g_bytes + 527, 6}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 522, 27}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[55],
- .data.refcounted = {g_bytes + 533, 27}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 549, 3}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[56],
- .data.refcounted = {g_bytes + 560, 3}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 552, 5}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[57],
- .data.refcounted = {g_bytes + 563, 5}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 557, 13}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[58],
- .data.refcounted = {g_bytes + 568, 13}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 570, 13}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[59],
- .data.refcounted = {g_bytes + 581, 13}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 583, 19}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[60],
- .data.refcounted = {g_bytes + 594, 19}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 602, 16}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[61],
- .data.refcounted = {g_bytes + 613, 16}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 618, 16}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[62],
- .data.refcounted = {g_bytes + 629, 16}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 634, 14}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[63],
- .data.refcounted = {g_bytes + 645, 14}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 648, 16}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[64],
- .data.refcounted = {g_bytes + 659, 16}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
- {{.refcount = &grpc_static_metadata_refcounts[65],
- .data.refcounted = {g_bytes + 675, 13}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 664, 13}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[11],
.data.refcounted = {g_bytes + 110, 12}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
+ {{.refcount = &grpc_static_metadata_refcounts[65],
+ .data.refcounted = {g_bytes + 677, 6}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[66],
- .data.refcounted = {g_bytes + 688, 6}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 683, 4}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[67],
- .data.refcounted = {g_bytes + 694, 4}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 687, 4}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[68],
- .data.refcounted = {g_bytes + 698, 4}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 691, 6}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[69],
- .data.refcounted = {g_bytes + 702, 6}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 697, 7}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[70],
- .data.refcounted = {g_bytes + 708, 7}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
- {{.refcount = &grpc_static_metadata_refcounts[71],
- .data.refcounted = {g_bytes + 715, 4}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 704, 4}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[14],
.data.refcounted = {g_bytes + 162, 4}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
+ {{.refcount = &grpc_static_metadata_refcounts[71],
+ .data.refcounted = {g_bytes + 708, 8}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[72],
- .data.refcounted = {g_bytes + 719, 8}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 716, 17}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[73],
- .data.refcounted = {g_bytes + 727, 17}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 733, 13}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[74],
- .data.refcounted = {g_bytes + 744, 13}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 746, 8}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[75],
- .data.refcounted = {g_bytes + 757, 8}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 754, 19}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[76],
- .data.refcounted = {g_bytes + 765, 19}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
- {{.refcount = &grpc_static_metadata_refcounts[77],
- .data.refcounted = {g_bytes + 784, 13}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 773, 13}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[15],
.data.refcounted = {g_bytes + 166, 8}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
- {{.refcount = &grpc_static_metadata_refcounts[16],
- .data.refcounted = {g_bytes + 174, 11}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
+ {{.refcount = &grpc_static_metadata_refcounts[77],
+ .data.refcounted = {g_bytes + 786, 4}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[78],
- .data.refcounted = {g_bytes + 797, 4}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 790, 8}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[79],
- .data.refcounted = {g_bytes + 801, 8}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 798, 12}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[80],
- .data.refcounted = {g_bytes + 809, 12}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 810, 18}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[81],
- .data.refcounted = {g_bytes + 821, 18}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 828, 19}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[82],
- .data.refcounted = {g_bytes + 839, 19}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 847, 5}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[83],
- .data.refcounted = {g_bytes + 858, 5}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 852, 7}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[84],
- .data.refcounted = {g_bytes + 863, 7}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 859, 7}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[85],
- .data.refcounted = {g_bytes + 870, 7}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 866, 11}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[86],
- .data.refcounted = {g_bytes + 877, 11}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 877, 6}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[87],
- .data.refcounted = {g_bytes + 888, 6}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 883, 10}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[88],
- .data.refcounted = {g_bytes + 894, 10}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 893, 25}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[89],
- .data.refcounted = {g_bytes + 904, 25}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
- {{.refcount = &grpc_static_metadata_refcounts[90],
- .data.refcounted = {g_bytes + 929, 17}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 918, 17}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[13],
.data.refcounted = {g_bytes + 152, 10}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
+ {{.refcount = &grpc_static_metadata_refcounts[90],
+ .data.refcounted = {g_bytes + 935, 4}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[91],
- .data.refcounted = {g_bytes + 946, 4}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 939, 3}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[92],
- .data.refcounted = {g_bytes + 950, 3}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
- {{.refcount = &grpc_static_metadata_refcounts[93],
- .data.refcounted = {g_bytes + 953, 16}},
- {.refcount = &grpc_static_metadata_refcounts[20],
- .data.refcounted = {g_bytes + 227, 0}}},
+ .data.refcounted = {g_bytes + 942, 16}},
+ {.refcount = &grpc_static_metadata_refcounts[19],
+ .data.refcounted = {g_bytes + 216, 0}}},
{{.refcount = &grpc_static_metadata_refcounts[10],
.data.refcounted = {g_bytes + 90, 20}},
- {.refcount = &grpc_static_metadata_refcounts[29],
- .data.refcounted = {g_bytes + 358, 8}}},
+ {.refcount = &grpc_static_metadata_refcounts[28],
+ .data.refcounted = {g_bytes + 347, 8}}},
{{.refcount = &grpc_static_metadata_refcounts[10],
.data.refcounted = {g_bytes + 90, 20}},
- {.refcount = &grpc_static_metadata_refcounts[31],
- .data.refcounted = {g_bytes + 370, 7}}},
+ {.refcount = &grpc_static_metadata_refcounts[30],
+ .data.refcounted = {g_bytes + 359, 7}}},
{{.refcount = &grpc_static_metadata_refcounts[10],
.data.refcounted = {g_bytes + 90, 20}},
- {.refcount = &grpc_static_metadata_refcounts[94],
- .data.refcounted = {g_bytes + 969, 16}}},
+ {.refcount = &grpc_static_metadata_refcounts[93],
+ .data.refcounted = {g_bytes + 958, 16}}},
{{.refcount = &grpc_static_metadata_refcounts[10],
.data.refcounted = {g_bytes + 90, 20}},
- {.refcount = &grpc_static_metadata_refcounts[30],
- .data.refcounted = {g_bytes + 366, 4}}},
+ {.refcount = &grpc_static_metadata_refcounts[29],
+ .data.refcounted = {g_bytes + 355, 4}}},
{{.refcount = &grpc_static_metadata_refcounts[10],
.data.refcounted = {g_bytes + 90, 20}},
- {.refcount = &grpc_static_metadata_refcounts[95],
- .data.refcounted = {g_bytes + 985, 13}}},
+ {.refcount = &grpc_static_metadata_refcounts[94],
+ .data.refcounted = {g_bytes + 974, 13}}},
{{.refcount = &grpc_static_metadata_refcounts[10],
.data.refcounted = {g_bytes + 90, 20}},
- {.refcount = &grpc_static_metadata_refcounts[96],
- .data.refcounted = {g_bytes + 998, 12}}},
+ {.refcount = &grpc_static_metadata_refcounts[95],
+ .data.refcounted = {g_bytes + 987, 12}}},
{{.refcount = &grpc_static_metadata_refcounts[10],
.data.refcounted = {g_bytes + 90, 20}},
- {.refcount = &grpc_static_metadata_refcounts[97],
- .data.refcounted = {g_bytes + 1010, 21}}},
+ {.refcount = &grpc_static_metadata_refcounts[96],
+ .data.refcounted = {g_bytes + 999, 21}}},
};
-const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 74, 75, 76,
- 77, 78, 79, 80};
+const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 73, 74, 75,
+ 76, 77, 78, 79};
diff --git a/src/core/lib/transport/static_metadata.h b/src/core/lib/transport/static_metadata.h
index 7649ccd5d2..f9600ee2e4 100644
--- a/src/core/lib/transport/static_metadata.h
+++ b/src/core/lib/transport/static_metadata.h
@@ -44,7 +44,7 @@
#include "src/core/lib/transport/metadata.h"
-#define GRPC_STATIC_MDSTR_COUNT 98
+#define GRPC_STATIC_MDSTR_COUNT 97
extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT];
/* ":path" */
#define GRPC_MDSTR_PATH (grpc_static_slice_table[0])
@@ -78,174 +78,172 @@ extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT];
#define GRPC_MDSTR_HOST (grpc_static_slice_table[14])
/* "lb-token" */
#define GRPC_MDSTR_LB_TOKEN (grpc_static_slice_table[15])
-/* "lb-cost-bin" */
-#define GRPC_MDSTR_LB_COST_BIN (grpc_static_slice_table[16])
/* "grpc-timeout" */
-#define GRPC_MDSTR_GRPC_TIMEOUT (grpc_static_slice_table[17])
+#define GRPC_MDSTR_GRPC_TIMEOUT (grpc_static_slice_table[16])
/* "grpc-tracing-bin" */
-#define GRPC_MDSTR_GRPC_TRACING_BIN (grpc_static_slice_table[18])
+#define GRPC_MDSTR_GRPC_TRACING_BIN (grpc_static_slice_table[17])
/* "grpc-stats-bin" */
-#define GRPC_MDSTR_GRPC_STATS_BIN (grpc_static_slice_table[19])
+#define GRPC_MDSTR_GRPC_STATS_BIN (grpc_static_slice_table[18])
/* "" */
-#define GRPC_MDSTR_EMPTY (grpc_static_slice_table[20])
+#define GRPC_MDSTR_EMPTY (grpc_static_slice_table[19])
/* "grpc.wait_for_ready" */
-#define GRPC_MDSTR_GRPC_DOT_WAIT_FOR_READY (grpc_static_slice_table[21])
+#define GRPC_MDSTR_GRPC_DOT_WAIT_FOR_READY (grpc_static_slice_table[20])
/* "grpc.timeout" */
-#define GRPC_MDSTR_GRPC_DOT_TIMEOUT (grpc_static_slice_table[22])
+#define GRPC_MDSTR_GRPC_DOT_TIMEOUT (grpc_static_slice_table[21])
/* "grpc.max_request_message_bytes" */
#define GRPC_MDSTR_GRPC_DOT_MAX_REQUEST_MESSAGE_BYTES \
- (grpc_static_slice_table[23])
+ (grpc_static_slice_table[22])
/* "grpc.max_response_message_bytes" */
#define GRPC_MDSTR_GRPC_DOT_MAX_RESPONSE_MESSAGE_BYTES \
- (grpc_static_slice_table[24])
+ (grpc_static_slice_table[23])
/* "/grpc.lb.v1.LoadBalancer/BalanceLoad" */
#define GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD \
- (grpc_static_slice_table[25])
+ (grpc_static_slice_table[24])
/* "0" */
-#define GRPC_MDSTR_0 (grpc_static_slice_table[26])
+#define GRPC_MDSTR_0 (grpc_static_slice_table[25])
/* "1" */
-#define GRPC_MDSTR_1 (grpc_static_slice_table[27])
+#define GRPC_MDSTR_1 (grpc_static_slice_table[26])
/* "2" */
-#define GRPC_MDSTR_2 (grpc_static_slice_table[28])
+#define GRPC_MDSTR_2 (grpc_static_slice_table[27])
/* "identity" */
-#define GRPC_MDSTR_IDENTITY (grpc_static_slice_table[29])
+#define GRPC_MDSTR_IDENTITY (grpc_static_slice_table[28])
/* "gzip" */
-#define GRPC_MDSTR_GZIP (grpc_static_slice_table[30])
+#define GRPC_MDSTR_GZIP (grpc_static_slice_table[29])
/* "deflate" */
-#define GRPC_MDSTR_DEFLATE (grpc_static_slice_table[31])
+#define GRPC_MDSTR_DEFLATE (grpc_static_slice_table[30])
/* "trailers" */
-#define GRPC_MDSTR_TRAILERS (grpc_static_slice_table[32])
+#define GRPC_MDSTR_TRAILERS (grpc_static_slice_table[31])
/* "application/grpc" */
-#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (grpc_static_slice_table[33])
+#define GRPC_MDSTR_APPLICATION_SLASH_GRPC (grpc_static_slice_table[32])
/* "POST" */
-#define GRPC_MDSTR_POST (grpc_static_slice_table[34])
+#define GRPC_MDSTR_POST (grpc_static_slice_table[33])
/* "200" */
-#define GRPC_MDSTR_200 (grpc_static_slice_table[35])
+#define GRPC_MDSTR_200 (grpc_static_slice_table[34])
/* "404" */
-#define GRPC_MDSTR_404 (grpc_static_slice_table[36])
+#define GRPC_MDSTR_404 (grpc_static_slice_table[35])
/* "http" */
-#define GRPC_MDSTR_HTTP (grpc_static_slice_table[37])
+#define GRPC_MDSTR_HTTP (grpc_static_slice_table[36])
/* "https" */
-#define GRPC_MDSTR_HTTPS (grpc_static_slice_table[38])
+#define GRPC_MDSTR_HTTPS (grpc_static_slice_table[37])
/* "grpc" */
-#define GRPC_MDSTR_GRPC (grpc_static_slice_table[39])
+#define GRPC_MDSTR_GRPC (grpc_static_slice_table[38])
/* "GET" */
-#define GRPC_MDSTR_GET (grpc_static_slice_table[40])
+#define GRPC_MDSTR_GET (grpc_static_slice_table[39])
/* "PUT" */
-#define GRPC_MDSTR_PUT (grpc_static_slice_table[41])
+#define GRPC_MDSTR_PUT (grpc_static_slice_table[40])
/* "/" */
-#define GRPC_MDSTR_SLASH (grpc_static_slice_table[42])
+#define GRPC_MDSTR_SLASH (grpc_static_slice_table[41])
/* "/index.html" */
-#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (grpc_static_slice_table[43])
+#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML (grpc_static_slice_table[42])
/* "204" */
-#define GRPC_MDSTR_204 (grpc_static_slice_table[44])
+#define GRPC_MDSTR_204 (grpc_static_slice_table[43])
/* "206" */
-#define GRPC_MDSTR_206 (grpc_static_slice_table[45])
+#define GRPC_MDSTR_206 (grpc_static_slice_table[44])
/* "304" */
-#define GRPC_MDSTR_304 (grpc_static_slice_table[46])
+#define GRPC_MDSTR_304 (grpc_static_slice_table[45])
/* "400" */
-#define GRPC_MDSTR_400 (grpc_static_slice_table[47])
+#define GRPC_MDSTR_400 (grpc_static_slice_table[46])
/* "500" */
-#define GRPC_MDSTR_500 (grpc_static_slice_table[48])
+#define GRPC_MDSTR_500 (grpc_static_slice_table[47])
/* "accept-charset" */
-#define GRPC_MDSTR_ACCEPT_CHARSET (grpc_static_slice_table[49])
+#define GRPC_MDSTR_ACCEPT_CHARSET (grpc_static_slice_table[48])
/* "accept-encoding" */
-#define GRPC_MDSTR_ACCEPT_ENCODING (grpc_static_slice_table[50])
+#define GRPC_MDSTR_ACCEPT_ENCODING (grpc_static_slice_table[49])
/* "gzip, deflate" */
-#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (grpc_static_slice_table[51])
+#define GRPC_MDSTR_GZIP_COMMA_DEFLATE (grpc_static_slice_table[50])
/* "accept-language" */
-#define GRPC_MDSTR_ACCEPT_LANGUAGE (grpc_static_slice_table[52])
+#define GRPC_MDSTR_ACCEPT_LANGUAGE (grpc_static_slice_table[51])
/* "accept-ranges" */
-#define GRPC_MDSTR_ACCEPT_RANGES (grpc_static_slice_table[53])
+#define GRPC_MDSTR_ACCEPT_RANGES (grpc_static_slice_table[52])
/* "accept" */
-#define GRPC_MDSTR_ACCEPT (grpc_static_slice_table[54])
+#define GRPC_MDSTR_ACCEPT (grpc_static_slice_table[53])
/* "access-control-allow-origin" */
-#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (grpc_static_slice_table[55])
+#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN (grpc_static_slice_table[54])
/* "age" */
-#define GRPC_MDSTR_AGE (grpc_static_slice_table[56])
+#define GRPC_MDSTR_AGE (grpc_static_slice_table[55])
/* "allow" */
-#define GRPC_MDSTR_ALLOW (grpc_static_slice_table[57])
+#define GRPC_MDSTR_ALLOW (grpc_static_slice_table[56])
/* "authorization" */
-#define GRPC_MDSTR_AUTHORIZATION (grpc_static_slice_table[58])
+#define GRPC_MDSTR_AUTHORIZATION (grpc_static_slice_table[57])
/* "cache-control" */
-#define GRPC_MDSTR_CACHE_CONTROL (grpc_static_slice_table[59])
+#define GRPC_MDSTR_CACHE_CONTROL (grpc_static_slice_table[58])
/* "content-disposition" */
-#define GRPC_MDSTR_CONTENT_DISPOSITION (grpc_static_slice_table[60])
+#define GRPC_MDSTR_CONTENT_DISPOSITION (grpc_static_slice_table[59])
/* "content-encoding" */
-#define GRPC_MDSTR_CONTENT_ENCODING (grpc_static_slice_table[61])
+#define GRPC_MDSTR_CONTENT_ENCODING (grpc_static_slice_table[60])
/* "content-language" */
-#define GRPC_MDSTR_CONTENT_LANGUAGE (grpc_static_slice_table[62])
+#define GRPC_MDSTR_CONTENT_LANGUAGE (grpc_static_slice_table[61])
/* "content-length" */
-#define GRPC_MDSTR_CONTENT_LENGTH (grpc_static_slice_table[63])
+#define GRPC_MDSTR_CONTENT_LENGTH (grpc_static_slice_table[62])
/* "content-location" */
-#define GRPC_MDSTR_CONTENT_LOCATION (grpc_static_slice_table[64])
+#define GRPC_MDSTR_CONTENT_LOCATION (grpc_static_slice_table[63])
/* "content-range" */
-#define GRPC_MDSTR_CONTENT_RANGE (grpc_static_slice_table[65])
+#define GRPC_MDSTR_CONTENT_RANGE (grpc_static_slice_table[64])
/* "cookie" */
-#define GRPC_MDSTR_COOKIE (grpc_static_slice_table[66])
+#define GRPC_MDSTR_COOKIE (grpc_static_slice_table[65])
/* "date" */
-#define GRPC_MDSTR_DATE (grpc_static_slice_table[67])
+#define GRPC_MDSTR_DATE (grpc_static_slice_table[66])
/* "etag" */
-#define GRPC_MDSTR_ETAG (grpc_static_slice_table[68])
+#define GRPC_MDSTR_ETAG (grpc_static_slice_table[67])
/* "expect" */
-#define GRPC_MDSTR_EXPECT (grpc_static_slice_table[69])
+#define GRPC_MDSTR_EXPECT (grpc_static_slice_table[68])
/* "expires" */
-#define GRPC_MDSTR_EXPIRES (grpc_static_slice_table[70])
+#define GRPC_MDSTR_EXPIRES (grpc_static_slice_table[69])
/* "from" */
-#define GRPC_MDSTR_FROM (grpc_static_slice_table[71])
+#define GRPC_MDSTR_FROM (grpc_static_slice_table[70])
/* "if-match" */
-#define GRPC_MDSTR_IF_MATCH (grpc_static_slice_table[72])
+#define GRPC_MDSTR_IF_MATCH (grpc_static_slice_table[71])
/* "if-modified-since" */
-#define GRPC_MDSTR_IF_MODIFIED_SINCE (grpc_static_slice_table[73])
+#define GRPC_MDSTR_IF_MODIFIED_SINCE (grpc_static_slice_table[72])
/* "if-none-match" */
-#define GRPC_MDSTR_IF_NONE_MATCH (grpc_static_slice_table[74])
+#define GRPC_MDSTR_IF_NONE_MATCH (grpc_static_slice_table[73])
/* "if-range" */
-#define GRPC_MDSTR_IF_RANGE (grpc_static_slice_table[75])
+#define GRPC_MDSTR_IF_RANGE (grpc_static_slice_table[74])
/* "if-unmodified-since" */
-#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (grpc_static_slice_table[76])
+#define GRPC_MDSTR_IF_UNMODIFIED_SINCE (grpc_static_slice_table[75])
/* "last-modified" */
-#define GRPC_MDSTR_LAST_MODIFIED (grpc_static_slice_table[77])
+#define GRPC_MDSTR_LAST_MODIFIED (grpc_static_slice_table[76])
/* "link" */
-#define GRPC_MDSTR_LINK (grpc_static_slice_table[78])
+#define GRPC_MDSTR_LINK (grpc_static_slice_table[77])
/* "location" */
-#define GRPC_MDSTR_LOCATION (grpc_static_slice_table[79])
+#define GRPC_MDSTR_LOCATION (grpc_static_slice_table[78])
/* "max-forwards" */
-#define GRPC_MDSTR_MAX_FORWARDS (grpc_static_slice_table[80])
+#define GRPC_MDSTR_MAX_FORWARDS (grpc_static_slice_table[79])
/* "proxy-authenticate" */
-#define GRPC_MDSTR_PROXY_AUTHENTICATE (grpc_static_slice_table[81])
+#define GRPC_MDSTR_PROXY_AUTHENTICATE (grpc_static_slice_table[80])
/* "proxy-authorization" */
-#define GRPC_MDSTR_PROXY_AUTHORIZATION (grpc_static_slice_table[82])
+#define GRPC_MDSTR_PROXY_AUTHORIZATION (grpc_static_slice_table[81])
/* "range" */
-#define GRPC_MDSTR_RANGE (grpc_static_slice_table[83])
+#define GRPC_MDSTR_RANGE (grpc_static_slice_table[82])
/* "referer" */
-#define GRPC_MDSTR_REFERER (grpc_static_slice_table[84])
+#define GRPC_MDSTR_REFERER (grpc_static_slice_table[83])
/* "refresh" */
-#define GRPC_MDSTR_REFRESH (grpc_static_slice_table[85])
+#define GRPC_MDSTR_REFRESH (grpc_static_slice_table[84])
/* "retry-after" */
-#define GRPC_MDSTR_RETRY_AFTER (grpc_static_slice_table[86])
+#define GRPC_MDSTR_RETRY_AFTER (grpc_static_slice_table[85])
/* "server" */
-#define GRPC_MDSTR_SERVER (grpc_static_slice_table[87])
+#define GRPC_MDSTR_SERVER (grpc_static_slice_table[86])
/* "set-cookie" */
-#define GRPC_MDSTR_SET_COOKIE (grpc_static_slice_table[88])
+#define GRPC_MDSTR_SET_COOKIE (grpc_static_slice_table[87])
/* "strict-transport-security" */
-#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (grpc_static_slice_table[89])
+#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY (grpc_static_slice_table[88])
/* "transfer-encoding" */
-#define GRPC_MDSTR_TRANSFER_ENCODING (grpc_static_slice_table[90])
+#define GRPC_MDSTR_TRANSFER_ENCODING (grpc_static_slice_table[89])
/* "vary" */
-#define GRPC_MDSTR_VARY (grpc_static_slice_table[91])
+#define GRPC_MDSTR_VARY (grpc_static_slice_table[90])
/* "via" */
-#define GRPC_MDSTR_VIA (grpc_static_slice_table[92])
+#define GRPC_MDSTR_VIA (grpc_static_slice_table[91])
/* "www-authenticate" */
-#define GRPC_MDSTR_WWW_AUTHENTICATE (grpc_static_slice_table[93])
+#define GRPC_MDSTR_WWW_AUTHENTICATE (grpc_static_slice_table[92])
/* "identity,deflate" */
-#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (grpc_static_slice_table[94])
+#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE (grpc_static_slice_table[93])
/* "identity,gzip" */
-#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (grpc_static_slice_table[95])
+#define GRPC_MDSTR_IDENTITY_COMMA_GZIP (grpc_static_slice_table[94])
/* "deflate,gzip" */
-#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (grpc_static_slice_table[96])
+#define GRPC_MDSTR_DEFLATE_COMMA_GZIP (grpc_static_slice_table[95])
/* "identity,deflate,gzip" */
#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
- (grpc_static_slice_table[97])
+ (grpc_static_slice_table[96])
extern const grpc_slice_refcount_vtable grpc_static_metadata_vtable;
extern grpc_slice_refcount
@@ -257,7 +255,7 @@ extern grpc_slice_refcount
#define GRPC_STATIC_METADATA_INDEX(static_slice) \
((int)((static_slice).refcount - grpc_static_metadata_refcounts))
-#define GRPC_STATIC_MDELEM_COUNT 81
+#define GRPC_STATIC_MDELEM_COUNT 80
extern grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];
/* "grpc-status": "0" */
@@ -428,81 +426,78 @@ extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];
/* "lb-token": "" */
#define GRPC_MDELEM_LB_TOKEN_EMPTY \
(GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[55], GRPC_MDELEM_STORAGE_STATIC))
-/* "lb-cost-bin": "" */
-#define GRPC_MDELEM_LB_COST_BIN_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[56], GRPC_MDELEM_STORAGE_STATIC))
/* "link": "" */
#define GRPC_MDELEM_LINK_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[57], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[56], GRPC_MDELEM_STORAGE_STATIC))
/* "location": "" */
#define GRPC_MDELEM_LOCATION_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[58], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[57], GRPC_MDELEM_STORAGE_STATIC))
/* "max-forwards": "" */
#define GRPC_MDELEM_MAX_FORWARDS_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[59], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[58], GRPC_MDELEM_STORAGE_STATIC))
/* "proxy-authenticate": "" */
#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[60], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[59], GRPC_MDELEM_STORAGE_STATIC))
/* "proxy-authorization": "" */
#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[61], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[60], GRPC_MDELEM_STORAGE_STATIC))
/* "range": "" */
#define GRPC_MDELEM_RANGE_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[62], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[61], GRPC_MDELEM_STORAGE_STATIC))
/* "referer": "" */
#define GRPC_MDELEM_REFERER_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[63], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[62], GRPC_MDELEM_STORAGE_STATIC))
/* "refresh": "" */
#define GRPC_MDELEM_REFRESH_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[64], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[63], GRPC_MDELEM_STORAGE_STATIC))
/* "retry-after": "" */
#define GRPC_MDELEM_RETRY_AFTER_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[65], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[64], GRPC_MDELEM_STORAGE_STATIC))
/* "server": "" */
#define GRPC_MDELEM_SERVER_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[66], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[65], GRPC_MDELEM_STORAGE_STATIC))
/* "set-cookie": "" */
#define GRPC_MDELEM_SET_COOKIE_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[67], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[66], GRPC_MDELEM_STORAGE_STATIC))
/* "strict-transport-security": "" */
#define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[68], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[67], GRPC_MDELEM_STORAGE_STATIC))
/* "transfer-encoding": "" */
#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[69], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[68], GRPC_MDELEM_STORAGE_STATIC))
/* "user-agent": "" */
#define GRPC_MDELEM_USER_AGENT_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[70], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[69], GRPC_MDELEM_STORAGE_STATIC))
/* "vary": "" */
#define GRPC_MDELEM_VARY_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[71], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[70], GRPC_MDELEM_STORAGE_STATIC))
/* "via": "" */
#define GRPC_MDELEM_VIA_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[72], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[71], GRPC_MDELEM_STORAGE_STATIC))
/* "www-authenticate": "" */
#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[73], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[72], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "identity" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[74], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[73], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "deflate" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[75], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[74], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "identity,deflate" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[76], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[75], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[77], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[76], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "identity,gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[78], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[77], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "deflate,gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[79], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[78], GRPC_MDELEM_STORAGE_STATIC))
/* "grpc-accept-encoding": "identity,deflate,gzip" */
#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \
- (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[80], GRPC_MDELEM_STORAGE_STATIC))
+ (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[79], GRPC_MDELEM_STORAGE_STATIC))
grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b);
typedef enum {
@@ -522,7 +517,6 @@ typedef enum {
GRPC_BATCH_USER_AGENT,
GRPC_BATCH_HOST,
GRPC_BATCH_LB_TOKEN,
- GRPC_BATCH_LB_COST_BIN,
GRPC_BATCH_CALLOUTS_COUNT
} grpc_metadata_batch_callouts_index;
@@ -545,7 +539,6 @@ typedef union {
struct grpc_linked_mdelem *user_agent;
struct grpc_linked_mdelem *host;
struct grpc_linked_mdelem *lb_token;
- struct grpc_linked_mdelem *lb_cost_bin;
} named;
} grpc_metadata_batch_callouts;
diff --git a/src/core/lib/transport/transport.c b/src/core/lib/transport/transport.c
index 004e748f25..165950e288 100644
--- a/src/core/lib/transport/transport.c
+++ b/src/core/lib/transport/transport.c
@@ -84,6 +84,39 @@ void grpc_stream_unref(grpc_exec_ctx *exec_ctx,
}
}
+#define STREAM_REF_FROM_SLICE_REF(p) \
+ ((grpc_stream_refcount *)(((uint8_t *)p) - \
+ offsetof(grpc_stream_refcount, slice_refcount)))
+
+static void slice_stream_ref(void *p) {
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+ grpc_stream_ref(STREAM_REF_FROM_SLICE_REF(p), "slice");
+#else
+ grpc_stream_ref(STREAM_REF_FROM_SLICE_REF(p));
+#endif
+}
+
+static void slice_stream_unref(grpc_exec_ctx *exec_ctx, void *p) {
+#ifdef GRPC_STREAM_REFCOUNT_DEBUG
+ grpc_stream_unref(exec_ctx, STREAM_REF_FROM_SLICE_REF(p), "slice");
+#else
+ grpc_stream_unref(exec_ctx, STREAM_REF_FROM_SLICE_REF(p));
+#endif
+}
+
+grpc_slice grpc_slice_from_stream_owned_buffer(grpc_stream_refcount *refcount,
+ void *buffer, size_t length) {
+ slice_stream_ref(&refcount->slice_refcount);
+ return (grpc_slice){.refcount = &refcount->slice_refcount,
+ .data.refcounted = {.bytes = buffer, .length = length}};
+}
+
+static const grpc_slice_refcount_vtable stream_ref_slice_vtable = {
+ .ref = slice_stream_ref,
+ .unref = slice_stream_unref,
+ .eq = grpc_slice_default_eq_impl,
+ .hash = grpc_slice_default_hash_impl};
+
#ifdef GRPC_STREAM_REFCOUNT_DEBUG
void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
grpc_iomgr_cb_func cb, void *cb_arg,
@@ -95,6 +128,8 @@ void grpc_stream_ref_init(grpc_stream_refcount *refcount, int initial_refs,
#endif
gpr_ref_init(&refcount->refs, initial_refs);
grpc_closure_init(&refcount->destroy, cb, cb_arg, grpc_schedule_on_exec_ctx);
+ refcount->slice_refcount.vtable = &stream_ref_slice_vtable;
+ refcount->slice_refcount.sub_refcount = &refcount->slice_refcount;
}
static void move64(uint64_t *from, uint64_t *to) {
diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h
index 9a0abe1ca4..cc1c277b35 100644
--- a/src/core/lib/transport/transport.h
+++ b/src/core/lib/transport/transport.h
@@ -64,6 +64,7 @@ typedef struct grpc_stream_refcount {
#ifdef GRPC_STREAM_REFCOUNT_DEBUG
const char *object_type;
#endif
+ grpc_slice_refcount slice_refcount;
} grpc_stream_refcount;
#ifdef GRPC_STREAM_REFCOUNT_DEBUG
@@ -84,6 +85,11 @@ void grpc_stream_unref(grpc_exec_ctx *exec_ctx, grpc_stream_refcount *refcount);
grpc_stream_ref_init(rc, ir, cb, cb_arg)
#endif
+/* Wrap a buffer that is owned by some stream object into a slice that shares
+ the same refcount */
+grpc_slice grpc_slice_from_stream_owned_buffer(grpc_stream_refcount *refcount,
+ void *buffer, size_t length);
+
typedef struct {
uint64_t framing_bytes;
uint64_t data_bytes;
@@ -167,9 +173,9 @@ typedef struct grpc_transport_stream_op {
/***************************************************************************
* remaining fields are initialized and used at the discretion of the
- * transport implementation */
+ * current handler of the op */
- grpc_transport_private_op_data transport_private;
+ grpc_transport_private_op_data handler_private;
} grpc_transport_stream_op;
/** Transport op: a set of operations to perform on a transport as a whole */
@@ -213,6 +219,7 @@ size_t grpc_transport_stream_size(grpc_transport *transport);
/* Initialize transport data for a stream.
Returns 0 on success, any other (transport-defined) value for failure.
+ May assume that stream contains all-zeros.
Arguments:
transport - the transport on which to create this stream
diff --git a/src/core/lib/tsi/fake_transport_security.c b/src/core/lib/tsi/fake_transport_security.c
index 0e20d6fd71..bbe323df3b 100644
--- a/src/core/lib/tsi/fake_transport_security.c
+++ b/src/core/lib/tsi/fake_transport_security.c
@@ -502,8 +502,7 @@ static const tsi_handshaker_vtable handshaker_vtable = {
};
tsi_handshaker *tsi_create_fake_handshaker(int is_client) {
- tsi_fake_handshaker *impl = gpr_malloc(sizeof(*impl));
- memset(impl, 0, sizeof(*impl));
+ tsi_fake_handshaker *impl = gpr_zalloc(sizeof(*impl));
impl->base.vtable = &handshaker_vtable;
impl->is_client = is_client;
impl->result = TSI_HANDSHAKE_IN_PROGRESS;
@@ -519,8 +518,7 @@ tsi_handshaker *tsi_create_fake_handshaker(int is_client) {
tsi_frame_protector *tsi_create_fake_protector(
size_t *max_protected_frame_size) {
- tsi_fake_frame_protector *impl = gpr_malloc(sizeof(*impl));
- memset(impl, 0, sizeof(*impl));
+ tsi_fake_frame_protector *impl = gpr_zalloc(sizeof(*impl));
impl->max_frame_size = (max_protected_frame_size == NULL)
? TSI_FAKE_DEFAULT_FRAME_SIZE
: *max_protected_frame_size;
diff --git a/src/core/lib/tsi/ssl_transport_security.c b/src/core/lib/tsi/ssl_transport_security.c
index 366dca9507..53aabdb926 100644
--- a/src/core/lib/tsi/ssl_transport_security.c
+++ b/src/core/lib/tsi/ssl_transport_security.c
@@ -976,9 +976,7 @@ static tsi_result ssl_handshaker_extract_peer(tsi_handshaker *self,
if (alpn_selected != NULL) {
size_t i;
tsi_peer_property *new_properties =
- gpr_malloc(sizeof(*new_properties) * (peer->property_count + 1));
- memset(new_properties, 0,
- sizeof(*new_properties) * (peer->property_count + 1));
+ gpr_zalloc(sizeof(*new_properties) * (peer->property_count + 1));
for (i = 0; i < peer->property_count; i++) {
new_properties[i] = peer->properties[i];
}
@@ -1002,8 +1000,7 @@ static tsi_result ssl_handshaker_create_frame_protector(
size_t actual_max_output_protected_frame_size =
TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
- tsi_ssl_frame_protector *protector_impl = gpr_malloc(sizeof(*protector_impl));
- memset(protector_impl, 0, sizeof(*protector_impl));
+ tsi_ssl_frame_protector *protector_impl = gpr_zalloc(sizeof(*protector_impl));
if (max_output_protected_frame_size != NULL) {
if (*max_output_protected_frame_size >
@@ -1119,8 +1116,7 @@ static tsi_result create_tsi_ssl_handshaker(SSL_CTX *ctx, int is_client,
SSL_set_accept_state(ssl);
}
- impl = gpr_malloc(sizeof(*impl));
- memset(impl, 0, sizeof(*impl));
+ impl = gpr_zalloc(sizeof(*impl));
impl->ssl = ssl;
impl->into_ssl = into_ssl;
impl->from_ssl = from_ssl;
@@ -1338,8 +1334,7 @@ tsi_result tsi_create_ssl_client_handshaker_factory(
return TSI_INVALID_ARGUMENT;
}
- impl = gpr_malloc(sizeof(*impl));
- memset(impl, 0, sizeof(*impl));
+ impl = gpr_zalloc(sizeof(*impl));
impl->ssl_context = ssl_context;
do {
@@ -1433,17 +1428,13 @@ tsi_result tsi_create_ssl_server_handshaker_factory_ex(
return TSI_INVALID_ARGUMENT;
}
- impl = gpr_malloc(sizeof(*impl));
- memset(impl, 0, sizeof(*impl));
+ impl = gpr_zalloc(sizeof(*impl));
impl->base.create_handshaker =
ssl_server_handshaker_factory_create_handshaker;
impl->base.destroy = ssl_server_handshaker_factory_destroy;
- impl->ssl_contexts = gpr_malloc(key_cert_pair_count * sizeof(SSL_CTX *));
- memset(impl->ssl_contexts, 0, key_cert_pair_count * sizeof(SSL_CTX *));
+ impl->ssl_contexts = gpr_zalloc(key_cert_pair_count * sizeof(SSL_CTX *));
impl->ssl_context_x509_subject_names =
- gpr_malloc(key_cert_pair_count * sizeof(tsi_peer));
- memset(impl->ssl_context_x509_subject_names, 0,
- key_cert_pair_count * sizeof(tsi_peer));
+ gpr_zalloc(key_cert_pair_count * sizeof(tsi_peer));
if (impl->ssl_contexts == NULL ||
impl->ssl_context_x509_subject_names == NULL) {
tsi_ssl_handshaker_factory_destroy(&impl->base);
diff --git a/src/core/lib/tsi/test_creds/BUILD b/src/core/lib/tsi/test_creds/BUILD
new file mode 100644
index 0000000000..5cf04caf17
--- /dev/null
+++ b/src/core/lib/tsi/test_creds/BUILD
@@ -0,0 +1,36 @@
+# Copyright 2017, 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.
+
+licenses(["notice"]) # 3-clause BSD
+
+exports_files([
+ "ca.pem",
+ "server1.key",
+ "server1.pem",
+])
diff --git a/src/core/lib/tsi/transport_security.c b/src/core/lib/tsi/transport_security.c
index 830cf09584..2cbf381c88 100644
--- a/src/core/lib/tsi/transport_security.c
+++ b/src/core/lib/tsi/transport_security.c
@@ -231,8 +231,7 @@ tsi_result tsi_construct_allocated_string_peer_property(
*property = tsi_init_peer_property();
if (name != NULL) property->name = gpr_strdup(name);
if (value_length > 0) {
- property->value.data = gpr_malloc(value_length);
- memset(property->value.data, 0, value_length);
+ property->value.data = gpr_zalloc(value_length);
property->value.length = value_length;
}
return TSI_OK;
@@ -260,8 +259,7 @@ tsi_result tsi_construct_string_peer_property(const char *name,
tsi_result tsi_construct_peer(size_t property_count, tsi_peer *peer) {
memset(peer, 0, sizeof(tsi_peer));
if (property_count > 0) {
- peer->properties = gpr_malloc(property_count * sizeof(tsi_peer_property));
- memset(peer->properties, 0, property_count * sizeof(tsi_peer_property));
+ peer->properties = gpr_zalloc(property_count * sizeof(tsi_peer_property));
peer->property_count = property_count;
}
return TSI_OK;
diff --git a/src/core/plugin_registry/grpc_cronet_plugin_registry.c b/src/core/plugin_registry/grpc_cronet_plugin_registry.c
index d339ed327f..c97f47b397 100644
--- a/src/core/plugin_registry/grpc_cronet_plugin_registry.c
+++ b/src/core/plugin_registry/grpc_cronet_plugin_registry.c
@@ -37,10 +37,14 @@ extern void grpc_chttp2_plugin_init(void);
extern void grpc_chttp2_plugin_shutdown(void);
extern void grpc_client_channel_init(void);
extern void grpc_client_channel_shutdown(void);
+extern void grpc_load_reporting_plugin_init(void);
+extern void grpc_load_reporting_plugin_shutdown(void);
void grpc_register_built_in_plugins(void) {
grpc_register_plugin(grpc_chttp2_plugin_init,
grpc_chttp2_plugin_shutdown);
grpc_register_plugin(grpc_client_channel_init,
grpc_client_channel_shutdown);
+ grpc_register_plugin(grpc_load_reporting_plugin_init,
+ grpc_load_reporting_plugin_shutdown);
}
diff --git a/src/cpp/common/channel_filter.h b/src/cpp/common/channel_filter.h
index 5f9fd8790b..79c4bab985 100644
--- a/src/cpp/common/channel_filter.h
+++ b/src/cpp/common/channel_filter.h
@@ -244,7 +244,7 @@ class CallData {
/// Initializes the call data.
virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, ChannelData *channel_data,
- grpc_call_element_args *args) {
+ const grpc_call_element_args *args) {
return GRPC_ERROR_NONE;
}
@@ -308,7 +308,7 @@ class ChannelFilter final {
static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
- grpc_call_element_args *args) {
+ const grpc_call_element_args *args) {
ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data;
// Construct the object in the already-allocated memory.
CallDataType *call_data = new (elem->call_data) CallDataType();
diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc
index 039c530cdc..f5a0e4131d 100644
--- a/src/cpp/common/version_cc.cc
+++ b/src/cpp/common/version_cc.cc
@@ -37,5 +37,5 @@
#include <grpc++/grpc++.h>
namespace grpc {
-grpc::string Version() { return "1.2.0-dev"; }
+grpc::string Version() { return "1.3.0-dev"; }
}
diff --git a/src/cpp/server/channel_argument_option.cc b/src/cpp/server/channel_argument_option.cc
new file mode 100644
index 0000000000..723f968ff8
--- /dev/null
+++ b/src/cpp/server/channel_argument_option.cc
@@ -0,0 +1,78 @@
+/*
+ *
+ * Copyright 2017, 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.
+ *
+ */
+
+#include <grpc++/impl/channel_argument_option.h>
+
+namespace grpc {
+
+std::unique_ptr<ServerBuilderOption> MakeChannelArgumentOption(
+ const grpc::string &name, const grpc::string &value) {
+ class StringOption final : public ServerBuilderOption {
+ public:
+ StringOption(const grpc::string &name, const grpc::string &value)
+ : name_(name), value_(value) {}
+
+ virtual void UpdateArguments(ChannelArguments *args) override {
+ args->SetString(name_, value_);
+ }
+ virtual void UpdatePlugins(
+ std::vector<std::unique_ptr<ServerBuilderPlugin>> *plugins) override {}
+
+ private:
+ const grpc::string name_;
+ const grpc::string value_;
+ };
+ return std::unique_ptr<ServerBuilderOption>(new StringOption(name, value));
+}
+
+std::unique_ptr<ServerBuilderOption> MakeChannelArgumentOption(
+ const grpc::string &name, int value) {
+ class IntOption final : public ServerBuilderOption {
+ public:
+ IntOption(const grpc::string &name, int value)
+ : name_(name), value_(value) {}
+
+ virtual void UpdateArguments(ChannelArguments *args) override {
+ args->SetInt(name_, value_);
+ }
+ virtual void UpdatePlugins(
+ std::vector<std::unique_ptr<ServerBuilderPlugin>> *plugins) override {}
+
+ private:
+ const grpc::string name_;
+ const int value_;
+ };
+ return std::unique_ptr<ServerBuilderOption>(new IntOption(name, value));
+}
+
+} // namespace grpc
diff --git a/src/cpp/server/health/default_health_check_service.cc b/src/cpp/server/health/default_health_check_service.cc
new file mode 100644
index 0000000000..bc98ce79a7
--- /dev/null
+++ b/src/cpp/server/health/default_health_check_service.cc
@@ -0,0 +1,168 @@
+/*
+ *
+ * Copyright 2016, 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.
+ *
+ */
+
+#include <memory>
+#include <mutex>
+
+#include <grpc++/impl/codegen/method_handler_impl.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/cpp/server/health/default_health_check_service.h"
+#include "src/cpp/server/health/health.pb.h"
+#include "third_party/nanopb/pb_decode.h"
+#include "third_party/nanopb/pb_encode.h"
+
+namespace grpc {
+namespace {
+const char kHealthCheckMethodName[] = "/grpc.health.v1.Health/Check";
+} // namespace
+
+DefaultHealthCheckService::HealthCheckServiceImpl::HealthCheckServiceImpl(
+ DefaultHealthCheckService* service)
+ : service_(service), method_(nullptr) {
+ MethodHandler* handler =
+ new RpcMethodHandler<HealthCheckServiceImpl, ByteBuffer, ByteBuffer>(
+ std::mem_fn(&HealthCheckServiceImpl::Check), this);
+ method_ = new RpcServiceMethod(kHealthCheckMethodName, RpcMethod::NORMAL_RPC,
+ handler);
+ AddMethod(method_);
+}
+
+Status DefaultHealthCheckService::HealthCheckServiceImpl::Check(
+ ServerContext* context, const ByteBuffer* request, ByteBuffer* response) {
+ // Decode request.
+ std::vector<Slice> slices;
+ if (!request->Dump(&slices).ok()) {
+ return Status(StatusCode::INVALID_ARGUMENT, "");
+ }
+ uint8_t* request_bytes = nullptr;
+ bool request_bytes_owned = false;
+ size_t request_size = 0;
+ grpc_health_v1_HealthCheckRequest request_struct;
+ if (slices.empty()) {
+ request_struct.has_service = false;
+ } else if (slices.size() == 1) {
+ request_bytes = const_cast<uint8_t*>(slices[0].begin());
+ request_size = slices[0].size();
+ } else {
+ request_bytes_owned = true;
+ request_bytes = static_cast<uint8_t*>(gpr_malloc(request->Length()));
+ uint8_t* copy_to = request_bytes;
+ for (size_t i = 0; i < slices.size(); i++) {
+ memcpy(copy_to, slices[i].begin(), slices[i].size());
+ copy_to += slices[i].size();
+ }
+ }
+
+ if (request_bytes != nullptr) {
+ pb_istream_t istream = pb_istream_from_buffer(request_bytes, request_size);
+ bool decode_status = pb_decode(
+ &istream, grpc_health_v1_HealthCheckRequest_fields, &request_struct);
+ if (request_bytes_owned) {
+ gpr_free(request_bytes);
+ }
+ if (!decode_status) {
+ return Status(StatusCode::INVALID_ARGUMENT, "");
+ }
+ }
+
+ // Check status from the associated default health checking service.
+ DefaultHealthCheckService::ServingStatus serving_status =
+ service_->GetServingStatus(
+ request_struct.has_service ? request_struct.service : "");
+ if (serving_status == DefaultHealthCheckService::NOT_FOUND) {
+ return Status(StatusCode::NOT_FOUND, "");
+ }
+
+ // Encode response
+ grpc_health_v1_HealthCheckResponse response_struct;
+ response_struct.has_status = true;
+ response_struct.status =
+ serving_status == DefaultHealthCheckService::SERVING
+ ? grpc_health_v1_HealthCheckResponse_ServingStatus_SERVING
+ : grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING;
+ pb_ostream_t ostream;
+ memset(&ostream, 0, sizeof(ostream));
+ pb_encode(&ostream, grpc_health_v1_HealthCheckResponse_fields,
+ &response_struct);
+ grpc_slice response_slice = grpc_slice_malloc(ostream.bytes_written);
+ ostream = pb_ostream_from_buffer(GRPC_SLICE_START_PTR(response_slice),
+ GRPC_SLICE_LENGTH(response_slice));
+ bool encode_status = pb_encode(
+ &ostream, grpc_health_v1_HealthCheckResponse_fields, &response_struct);
+ if (!encode_status) {
+ return Status(StatusCode::INTERNAL, "Failed to encode response.");
+ }
+ Slice encoded_response(response_slice, Slice::STEAL_REF);
+ ByteBuffer response_buffer(&encoded_response, 1);
+ response->Swap(&response_buffer);
+ return Status::OK;
+}
+
+DefaultHealthCheckService::DefaultHealthCheckService() {
+ services_map_.emplace("", true);
+}
+
+void DefaultHealthCheckService::SetServingStatus(
+ const grpc::string& service_name, bool serving) {
+ std::lock_guard<std::mutex> lock(mu_);
+ services_map_[service_name] = serving;
+}
+
+void DefaultHealthCheckService::SetServingStatus(bool serving) {
+ std::lock_guard<std::mutex> lock(mu_);
+ for (auto iter = services_map_.begin(); iter != services_map_.end(); ++iter) {
+ iter->second = serving;
+ }
+}
+
+DefaultHealthCheckService::ServingStatus
+DefaultHealthCheckService::GetServingStatus(
+ const grpc::string& service_name) const {
+ std::lock_guard<std::mutex> lock(mu_);
+ const auto& iter = services_map_.find(service_name);
+ if (iter == services_map_.end()) {
+ return NOT_FOUND;
+ }
+ return iter->second ? SERVING : NOT_SERVING;
+}
+
+DefaultHealthCheckService::HealthCheckServiceImpl*
+DefaultHealthCheckService::GetHealthCheckService() {
+ GPR_ASSERT(impl_ == nullptr);
+ impl_.reset(new HealthCheckServiceImpl(this));
+ return impl_.get();
+}
+
+} // namespace grpc
diff --git a/src/cpp/server/health/default_health_check_service.h b/src/cpp/server/health/default_health_check_service.h
new file mode 100644
index 0000000000..5c0e230342
--- /dev/null
+++ b/src/cpp/server/health/default_health_check_service.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * Copyright 2016, 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.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_CPP_SERVER_DEFAULT_HEALTH_CHECK_SERVICE_H
+#define GRPC_INTERNAL_CPP_SERVER_DEFAULT_HEALTH_CHECK_SERVICE_H
+
+#include <mutex>
+
+#include <grpc++/health_check_service_interface.h>
+#include <grpc++/impl/codegen/service_type.h>
+#include <grpc++/support/byte_buffer.h>
+
+namespace grpc {
+
+// Default implementation of HealthCheckServiceInterface. Server will create and
+// own it.
+class DefaultHealthCheckService final : public HealthCheckServiceInterface {
+ public:
+ // The service impl to register with the server.
+ class HealthCheckServiceImpl : public Service {
+ public:
+ explicit HealthCheckServiceImpl(DefaultHealthCheckService* service);
+
+ Status Check(ServerContext* context, const ByteBuffer* request,
+ ByteBuffer* response);
+
+ private:
+ const DefaultHealthCheckService* const service_;
+ RpcServiceMethod* method_;
+ };
+
+ DefaultHealthCheckService();
+ void SetServingStatus(const grpc::string& service_name,
+ bool serving) override;
+ void SetServingStatus(bool serving) override;
+ enum ServingStatus { NOT_FOUND, SERVING, NOT_SERVING };
+ ServingStatus GetServingStatus(const grpc::string& service_name) const;
+ HealthCheckServiceImpl* GetHealthCheckService();
+
+ private:
+ mutable std::mutex mu_;
+ std::map<grpc::string, bool> services_map_;
+ std::unique_ptr<HealthCheckServiceImpl> impl_;
+};
+
+} // namespace grpc
+
+#endif // GRPC_INTERNAL_CPP_SERVER_DEFAULT_HEALTH_CHECK_SERVICE_H
diff --git a/src/cpp/server/health/health.pb.c b/src/cpp/server/health/health.pb.c
new file mode 100644
index 0000000000..09bd98a3d9
--- /dev/null
+++ b/src/cpp/server/health/health.pb.c
@@ -0,0 +1,24 @@
+/* Automatically generated nanopb constant definitions */
+/* Generated by nanopb-0.3.7-dev */
+
+#include "src/cpp/server/health/health.pb.h"
+
+/* @@protoc_insertion_point(includes) */
+#if PB_PROTO_HEADER_VERSION != 30
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+
+
+const pb_field_t grpc_health_v1_HealthCheckRequest_fields[2] = {
+ PB_FIELD( 1, STRING , OPTIONAL, STATIC , FIRST, grpc_health_v1_HealthCheckRequest, service, service, 0),
+ PB_LAST_FIELD
+};
+
+const pb_field_t grpc_health_v1_HealthCheckResponse_fields[2] = {
+ PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, grpc_health_v1_HealthCheckResponse, status, status, 0),
+ PB_LAST_FIELD
+};
+
+
+/* @@protoc_insertion_point(eof) */
diff --git a/src/cpp/server/health/health.pb.h b/src/cpp/server/health/health.pb.h
new file mode 100644
index 0000000000..7051b3260a
--- /dev/null
+++ b/src/cpp/server/health/health.pb.h
@@ -0,0 +1,72 @@
+/* Automatically generated nanopb header */
+/* Generated by nanopb-0.3.7-dev */
+
+#ifndef PB_GRPC_HEALTH_V1_HEALTH_PB_H_INCLUDED
+#define PB_GRPC_HEALTH_V1_HEALTH_PB_H_INCLUDED
+#include "third_party/nanopb/pb.h"
+/* @@protoc_insertion_point(includes) */
+#if PB_PROTO_HEADER_VERSION != 30
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Enum definitions */
+typedef enum _grpc_health_v1_HealthCheckResponse_ServingStatus {
+ grpc_health_v1_HealthCheckResponse_ServingStatus_UNKNOWN = 0,
+ grpc_health_v1_HealthCheckResponse_ServingStatus_SERVING = 1,
+ grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING = 2
+} grpc_health_v1_HealthCheckResponse_ServingStatus;
+#define _grpc_health_v1_HealthCheckResponse_ServingStatus_MIN grpc_health_v1_HealthCheckResponse_ServingStatus_UNKNOWN
+#define _grpc_health_v1_HealthCheckResponse_ServingStatus_MAX grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING
+#define _grpc_health_v1_HealthCheckResponse_ServingStatus_ARRAYSIZE ((grpc_health_v1_HealthCheckResponse_ServingStatus)(grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING+1))
+
+/* Struct definitions */
+typedef struct _grpc_health_v1_HealthCheckRequest {
+ bool has_service;
+ char service[200];
+/* @@protoc_insertion_point(struct:grpc_health_v1_HealthCheckRequest) */
+} grpc_health_v1_HealthCheckRequest;
+
+typedef struct _grpc_health_v1_HealthCheckResponse {
+ bool has_status;
+ grpc_health_v1_HealthCheckResponse_ServingStatus status;
+/* @@protoc_insertion_point(struct:grpc_health_v1_HealthCheckResponse) */
+} grpc_health_v1_HealthCheckResponse;
+
+/* Default values for struct fields */
+
+/* Initializer values for message structs */
+#define grpc_health_v1_HealthCheckRequest_init_default {false, ""}
+#define grpc_health_v1_HealthCheckResponse_init_default {false, (grpc_health_v1_HealthCheckResponse_ServingStatus)0}
+#define grpc_health_v1_HealthCheckRequest_init_zero {false, ""}
+#define grpc_health_v1_HealthCheckResponse_init_zero {false, (grpc_health_v1_HealthCheckResponse_ServingStatus)0}
+
+/* Field tags (for use in manual encoding/decoding) */
+#define grpc_health_v1_HealthCheckRequest_service_tag 1
+#define grpc_health_v1_HealthCheckResponse_status_tag 1
+
+/* Struct field encoding specification for nanopb */
+extern const pb_field_t grpc_health_v1_HealthCheckRequest_fields[2];
+extern const pb_field_t grpc_health_v1_HealthCheckResponse_fields[2];
+
+/* Maximum encoded size of messages (where known) */
+#define grpc_health_v1_HealthCheckRequest_size 203
+#define grpc_health_v1_HealthCheckResponse_size 2
+
+/* Message IDs (where set with "msgid" option) */
+#ifdef PB_MSGID
+
+#define HEALTH_MESSAGES \
+
+
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+/* @@protoc_insertion_point(eof) */
+
+#endif
diff --git a/src/cpp/test/server_context_test_spouse.cc b/src/cpp/server/health/health_check_service.cc
index b812d169a5..cca68c5549 100644
--- a/src/cpp/test/server_context_test_spouse.cc
+++ b/src/cpp/server/health/health_check_service.cc
@@ -31,23 +31,19 @@
*
*/
-#include <grpc++/test/server_context_test_spouse.h>
+#include <grpc++/health_check_service_interface.h>
namespace grpc {
-namespace testing {
+namespace {
+bool g_grpc_default_health_check_service_enabled = false;
+} // namesapce
-void ServerContextTestSpouse::AddClientMetadata(const grpc::string& key,
- const grpc::string& value) {
- client_metadata_storage_.insert(
- std::pair<grpc::string, grpc::string>(key, value));
- ctx_->client_metadata_.map()->clear();
- for (auto iter = client_metadata_storage_.begin();
- iter != client_metadata_storage_.end(); ++iter) {
- ctx_->client_metadata_.map()->insert(
- std::pair<grpc::string_ref, grpc::string_ref>(iter->first.c_str(),
- iter->second.c_str()));
- }
+bool DefaultHealthCheckServiceEnabled() {
+ return g_grpc_default_health_check_service_enabled;
+}
+
+void EnableDefaultHealthCheckService(bool enable) {
+ g_grpc_default_health_check_service_enabled = enable;
}
-} // namespace testing
} // namespace grpc
diff --git a/src/cpp/server/health/health_check_service_server_builder_option.cc b/src/cpp/server/health/health_check_service_server_builder_option.cc
new file mode 100644
index 0000000000..24264204b3
--- /dev/null
+++ b/src/cpp/server/health/health_check_service_server_builder_option.cc
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright 2016, 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.
+ *
+ */
+
+#include <grpc++/ext/health_check_service_server_builder_option.h>
+
+namespace grpc {
+
+HealthCheckServiceServerBuilderOption::HealthCheckServiceServerBuilderOption(
+ std::unique_ptr<HealthCheckServiceInterface> hc)
+ : hc_(std::move(hc)) {}
+// Hand over hc_ to the server.
+void HealthCheckServiceServerBuilderOption::UpdateArguments(
+ ChannelArguments* args) {
+ args->SetPointer(kHealthCheckServiceInterfaceArg, hc_.release());
+}
+
+void HealthCheckServiceServerBuilderOption::UpdatePlugins(
+ std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) {}
+
+} // namespace grpc
diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc
index 00a90bb184..4eb4b5a1b2 100644
--- a/src/cpp/server/server_builder.cc
+++ b/src/cpp/server/server_builder.cc
@@ -323,9 +323,14 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
}
}
+ bool added_port = false;
for (auto port = ports_.begin(); port != ports_.end(); port++) {
int r = server->AddListeningPort(port->addr, port->creds.get());
- if (!r) return nullptr;
+ if (!r) {
+ if (added_port) server->Shutdown();
+ return nullptr;
+ }
+ added_port = true;
if (port->selected_port != nullptr) {
*port->selected_port = r;
}
@@ -333,6 +338,7 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
auto cqs_data = cqs_.empty() ? nullptr : &cqs_[0];
if (!server->Start(cqs_data, cqs_.size())) {
+ if (added_port) server->Shutdown();
return nullptr;
}
diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc
index 29898a4209..e874892e73 100644
--- a/src/cpp/server/server_cc.cc
+++ b/src/cpp/server/server_cc.cc
@@ -37,6 +37,7 @@
#include <grpc++/completion_queue.h>
#include <grpc++/generic/async_generic_service.h>
+#include <grpc++/impl/codegen/async_unary_call.h>
#include <grpc++/impl/codegen/completion_queue_tag.h>
#include <grpc++/impl/grpc_library.h>
#include <grpc++/impl/method_handler_impl.h>
@@ -51,6 +52,7 @@
#include <grpc/support/log.h>
#include "src/core/lib/profiling/timers.h"
+#include "src/cpp/server/health/default_health_check_service.h"
#include "src/cpp/thread_manager/thread_manager.h"
namespace grpc {
@@ -186,9 +188,8 @@ class Server::SyncRequest final : public CompletionQueueTag {
public:
explicit CallData(Server* server, SyncRequest* mrd)
: cq_(mrd->cq_),
- call_(mrd->call_, server, &cq_),
- ctx_(mrd->deadline_, mrd->request_metadata_.metadata,
- mrd->request_metadata_.count),
+ call_(mrd->call_, server, &cq_, server->max_receive_message_size()),
+ ctx_(mrd->deadline_, &mrd->request_metadata_),
has_request_payload_(mrd->has_request_payload_),
request_payload_(mrd->request_payload_),
method_(mrd->method_) {
@@ -342,6 +343,7 @@ class Server::SyncRequestThreadManager : public ThreadManager {
int cq_timeout_msec_;
std::vector<std::unique_ptr<SyncRequest>> sync_requests_;
std::unique_ptr<RpcServiceMethod> unknown_method_;
+ std::unique_ptr<RpcServiceMethod> health_check_;
std::shared_ptr<Server::GlobalCallbacks> global_callbacks_;
};
@@ -358,7 +360,8 @@ Server::Server(
shutdown_notified_(false),
has_generic_service_(false),
server_(nullptr),
- server_initializer_(new ServerInitializer(this)) {
+ server_initializer_(new ServerInitializer(this)),
+ health_check_service_disabled_(false) {
g_gli_initializer.summon();
gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks);
global_callbacks_ = g_callbacks;
@@ -374,6 +377,19 @@ Server::Server(
grpc_channel_args channel_args;
args->SetChannelArgs(&channel_args);
+ for (size_t i = 0; i < channel_args.num_args; i++) {
+ if (0 ==
+ strcmp(channel_args.args[i].key, kHealthCheckServiceInterfaceArg)) {
+ if (channel_args.args[i].value.pointer.p == nullptr) {
+ health_check_service_disabled_ = true;
+ } else {
+ health_check_service_.reset(static_cast<HealthCheckServiceInterface*>(
+ channel_args.args[i].value.pointer.p));
+ }
+ break;
+ }
+ }
+
server_ = grpc_server_create(&channel_args, nullptr);
}
@@ -480,6 +496,21 @@ bool Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
GPR_ASSERT(!started_);
global_callbacks_->PreServerStart(this);
started_ = true;
+
+ // Only create default health check service when user did not provide an
+ // explicit one.
+ if (health_check_service_ == nullptr && !health_check_service_disabled_ &&
+ DefaultHealthCheckServiceEnabled()) {
+ if (sync_server_cqs_->empty()) {
+ gpr_log(GPR_ERROR,
+ "Default health check service disabled at async-only server.");
+ } else {
+ auto* default_hc_service = new DefaultHealthCheckService;
+ health_check_service_.reset(default_hc_service);
+ RegisterService(nullptr, default_hc_service->GetHealthCheckService());
+ }
+ }
+
grpc_server_start(server_);
if (!has_generic_service_) {
@@ -503,7 +534,7 @@ bool Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
void Server::ShutdownInternal(gpr_timespec deadline) {
std::unique_lock<std::mutex> lock(mu_);
- if (started_ && !shutdown_) {
+ if (!shutdown_) {
shutdown_ = true;
/// The completion queue to use for server shutdown completion notification
@@ -590,7 +621,7 @@ bool ServerInterface::BaseAsyncRequest::FinalizeResult(void** tag,
}
context_->set_call(call_);
context_->cq_ = call_cq_;
- Call call(call_, server_, call_cq_);
+ Call call(call_, server_, call_cq_, server_->max_receive_message_size());
if (*status && call_) {
context_->BeginCompletionOp(&call);
}
diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc
index a7aaa25572..05c05c8695 100644
--- a/src/cpp/server/server_context.cc
+++ b/src/cpp/server/server_context.cc
@@ -33,7 +33,9 @@
#include <grpc++/server_context.h>
+#include <algorithm>
#include <mutex>
+#include <utility>
#include <grpc++/completion_queue.h>
#include <grpc++/impl/call.h>
@@ -133,8 +135,7 @@ ServerContext::ServerContext()
sent_initial_metadata_(false),
compression_level_set_(false) {}
-ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata* metadata,
- size_t metadata_count)
+ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata_array* arr)
: completion_op_(nullptr),
has_notify_when_done_tag_(false),
async_notify_when_done_tag_(nullptr),
@@ -143,12 +144,8 @@ ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata* metadata,
cq_(nullptr),
sent_initial_metadata_(false),
compression_level_set_(false) {
- for (size_t i = 0; i < metadata_count; i++) {
- client_metadata_.map()->insert(
- std::pair<grpc::string_ref, grpc::string_ref>(
- StringRefFromSlice(&metadata[i].key),
- StringRefFromSlice(&metadata[i].value)));
- }
+ std::swap(*client_metadata_.arr(), *arr);
+ client_metadata_.FillMap();
}
ServerContext::~ServerContext() {
@@ -224,4 +221,20 @@ const struct census_context* ServerContext::census_context() const {
return grpc_census_call_get_context(call_);
}
+void ServerContext::SetLoadReportingCosts(
+ const std::vector<grpc::string>& cost_data) {
+ if (call_ == nullptr) return;
+ grpc_load_reporting_cost_context* cost_ctx =
+ static_cast<grpc_load_reporting_cost_context*>(
+ gpr_malloc(sizeof(*cost_ctx)));
+ cost_ctx->values_count = cost_data.size();
+ cost_ctx->values = static_cast<grpc_slice*>(
+ gpr_malloc(sizeof(*cost_ctx->values) * cost_ctx->values_count));
+ for (size_t i = 0; i < cost_ctx->values_count; ++i) {
+ cost_ctx->values[i] =
+ grpc_slice_from_copied_buffer(cost_data[i].data(), cost_data[i].size());
+ }
+ grpc_call_set_load_reporting_cost_context(call_, cost_ctx);
+}
+
} // namespace grpc
diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.csproj b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
index db55ed5a6c..9ef98529e8 100644
--- a/src/csharp/Grpc.Auth/Grpc.Auth.csproj
+++ b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
@@ -34,32 +34,26 @@
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.WebRequest" />
- <Reference Include="BouncyCastle.Crypto">
- <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
- </Reference>
- <Reference Include="Newtonsoft.Json">
- <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
- </Reference>
- <Reference Include="log4net">
- <HintPath>..\packages\log4net.2.0.3\lib\net40-full\log4net.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Core">
- <HintPath>..\packages\Google.Apis.Core.1.16.0\lib\net45\Google.Apis.Core.dll</HintPath>
- </Reference>
<Reference Include="Zlib.Portable">
<HintPath>..\packages\Zlib.Portable.Signed.1.11.0\lib\portable-net4+sl5+wp8+win8+wpa81+MonoTouch+MonoAndroid\Zlib.Portable.dll</HintPath>
</Reference>
+ <Reference Include="Google.Apis.Core">
+ <HintPath>..\packages\Google.Apis.Core.1.21.0\lib\net45\Google.Apis.Core.dll</HintPath>
+ </Reference>
<Reference Include="Google.Apis">
- <HintPath>..\packages\Google.Apis.1.16.0\lib\net45\Google.Apis.dll</HintPath>
+ <HintPath>..\packages\Google.Apis.1.21.0\lib\net45\Google.Apis.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.PlatformServices">
- <HintPath>..\packages\Google.Apis.1.16.0\lib\net45\Google.Apis.PlatformServices.dll</HintPath>
+ <HintPath>..\packages\Google.Apis.1.21.0\lib\net45\Google.Apis.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Auth">
- <HintPath>..\packages\Google.Apis.Auth.1.16.0\lib\net45\Google.Apis.Auth.dll</HintPath>
+ <HintPath>..\packages\Google.Apis.Auth.1.21.0\lib\net45\Google.Apis.Auth.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Auth.PlatformServices">
- <HintPath>..\packages\Google.Apis.Auth.1.16.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
+ <HintPath>..\packages\Google.Apis.Auth.1.21.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
+ </Reference>
+ <Reference Include="Newtonsoft.Json">
+ <HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
diff --git a/src/csharp/Grpc.Auth/packages.config b/src/csharp/Grpc.Auth/packages.config
index 11c6375c63..aecc65e849 100644
--- a/src/csharp/Grpc.Auth/packages.config
+++ b/src/csharp/Grpc.Auth/packages.config
@@ -1,10 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
- <package id="Google.Apis" version="1.16.0" targetFramework="net45" />
- <package id="Google.Apis.Auth" version="1.16.0" targetFramework="net45" />
- <package id="Google.Apis.Core" version="1.16.0" targetFramework="net45" />
- <package id="log4net" version="2.0.3" targetFramework="net45" />
- <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
+ <package id="Google.Apis" version="1.21.0" targetFramework="net45" />
+ <package id="Google.Apis.Auth" version="1.21.0" targetFramework="net45" />
+ <package id="Google.Apis.Core" version="1.21.0" targetFramework="net45" />
+ <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
<package id="Zlib.Portable.Signed" version="1.11.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Auth/project.json b/src/csharp/Grpc.Auth/project.json
index 3805f4759e..370bf11b2d 100644
--- a/src/csharp/Grpc.Auth/project.json
+++ b/src/csharp/Grpc.Auth/project.json
@@ -1,5 +1,5 @@
{
- "version": "1.2.0-dev",
+ "version": "1.3.0-dev",
"title": "gRPC C# Auth",
"authors": [ "Google Inc." ],
"copyright": "Copyright 2015, Google Inc.",
@@ -21,8 +21,8 @@
}
},
"dependencies": {
- "Grpc.Core": "1.2.0-dev",
- "Google.Apis.Auth": "1.16.0"
+ "Grpc.Core": "1.3.0-dev",
+ "Google.Apis.Auth": "1.21.0"
},
"frameworks": {
"net45": { },
diff --git a/src/csharp/Grpc.Core.Testing/project.json b/src/csharp/Grpc.Core.Testing/project.json
index 02be957812..38d5fab50e 100644
--- a/src/csharp/Grpc.Core.Testing/project.json
+++ b/src/csharp/Grpc.Core.Testing/project.json
@@ -1,5 +1,5 @@
{
- "version": "1.2.0-dev",
+ "version": "1.3.0-dev",
"title": "gRPC C# Core Testing",
"authors": [ "Google Inc." ],
"copyright": "Copyright 2017, Google Inc.",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
- "Grpc.Core": "1.2.0-dev"
+ "Grpc.Core": "1.3.0-dev"
},
"frameworks": {
"net45": {
diff --git a/src/csharp/Grpc.Core.Tests/AuthContextTest.cs b/src/csharp/Grpc.Core.Tests/AuthContextTest.cs
new file mode 100644
index 0000000000..f5fa469520
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/AuthContextTest.cs
@@ -0,0 +1,86 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using NUnit.Framework;
+using Grpc.Core;
+using System.Linq;
+
+namespace Grpc.Core.Tests
+{
+ public class AuthContextTest
+ {
+ [Test]
+ public void EmptyContext()
+ {
+ var context = new AuthContext(null, new Dictionary<string, List<AuthProperty>>());
+ Assert.IsFalse(context.IsPeerAuthenticated);
+ Assert.IsNull(context.PeerIdentityPropertyName);
+ Assert.AreEqual(0, context.PeerIdentity.Count());
+ Assert.AreEqual(0, context.Properties.Count());
+ Assert.AreEqual(0, context.FindPropertiesByName("nonexistent").Count());
+ }
+
+ [Test]
+ public void AuthenticatedContext()
+ {
+ var property1 = AuthProperty.Create("abc", new byte[] { 68, 69, 70 });
+ var context = new AuthContext("some_identity", new Dictionary<string, List<AuthProperty>>
+ {
+ {"some_identity", new List<AuthProperty> {property1}}
+ });
+ Assert.IsTrue(context.IsPeerAuthenticated);
+ Assert.AreEqual("some_identity", context.PeerIdentityPropertyName);
+ Assert.AreEqual(1, context.PeerIdentity.Count());
+ }
+
+ [Test]
+ public void FindPropertiesByName()
+ {
+ var property1 = AuthProperty.Create("abc", new byte[] {68, 69, 70});
+ var property2 = AuthProperty.Create("abc", new byte[] {71, 72, 73 });
+ var property3 = AuthProperty.Create("abc", new byte[] {});
+ var context = new AuthContext(null, new Dictionary<string, List<AuthProperty>>
+ {
+ {"existent", new List<AuthProperty> {property1, property2}},
+ {"foobar", new List<AuthProperty> {property3}},
+ });
+ Assert.AreEqual(3, context.Properties.Count());
+ Assert.AreEqual(0, context.FindPropertiesByName("nonexistent").Count());
+
+ var existentProperties = new List<AuthProperty>(context.FindPropertiesByName("existent"));
+ Assert.AreEqual(2, existentProperties.Count);
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core.Tests/AuthPropertyTest.cs b/src/csharp/Grpc.Core.Tests/AuthPropertyTest.cs
new file mode 100644
index 0000000000..745191b80d
--- /dev/null
+++ b/src/csharp/Grpc.Core.Tests/AuthPropertyTest.cs
@@ -0,0 +1,82 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using NUnit.Framework;
+
+namespace Grpc.Core.Tests
+{
+ public class AuthPropertyTest
+ {
+ [Test]
+ public void Create_NameIsNotNull()
+ {
+ Assert.Throws(typeof(ArgumentNullException), () => AuthProperty.Create(null, new byte[0]));
+ Assert.Throws(typeof(ArgumentNullException), () => AuthProperty.CreateUnsafe(null, new byte[0]));
+ }
+
+ [Test]
+ public void Create_ValueIsNotNull()
+ {
+ Assert.Throws(typeof(ArgumentNullException), () => AuthProperty.Create("abc", null));
+ Assert.Throws(typeof(ArgumentNullException), () => AuthProperty.CreateUnsafe("abc", null));
+ }
+
+ [Test]
+ public void Create()
+ {
+ var valueBytes = new byte[] { 68, 69, 70 };
+ var authProperty = AuthProperty.Create("abc", valueBytes);
+
+ Assert.AreEqual("abc", authProperty.Name);
+ Assert.AreNotSame(valueBytes, authProperty.ValueBytesUnsafe);
+ CollectionAssert.AreEqual(valueBytes, authProperty.ValueBytes);
+ CollectionAssert.AreEqual(valueBytes, authProperty.ValueBytesUnsafe);
+ Assert.AreEqual("DEF", authProperty.Value);
+ }
+
+ [Test]
+ public void CreateUnsafe()
+ {
+ var valueBytes = new byte[] { 68, 69, 70 };
+ var authProperty = AuthProperty.CreateUnsafe("abc", valueBytes);
+
+ Assert.AreEqual("abc", authProperty.Name);
+ Assert.AreSame(valueBytes, authProperty.ValueBytesUnsafe);
+ Assert.AreNotSame(valueBytes, authProperty.ValueBytes);
+ CollectionAssert.AreEqual(valueBytes, authProperty.ValueBytes);
+ CollectionAssert.AreEqual(valueBytes, authProperty.ValueBytesUnsafe);
+ Assert.AreEqual("DEF", authProperty.Value);
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
index 6bf9756962..3a99107c42 100644
--- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
@@ -376,6 +376,18 @@ namespace Grpc.Core.Tests
}
[Test]
+ public void ServerCallContext_AuthContextNotPopulated()
+ {
+ helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
+ {
+ Assert.IsFalse(context.AuthContext.IsPeerAuthenticated);
+ Assert.AreEqual(0, context.AuthContext.Properties.Count());
+ return "PASS";
+ });
+ Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
+ }
+
+ [Test]
public async Task Channel_WaitForStateChangedAsync()
{
helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
index 646effe21a..a1a2e4eebd 100644
--- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
+++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
@@ -27,17 +27,17 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
- <Reference Include="nunit.framework">
- <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
- </Reference>
- <Reference Include="nunitlite">
- <HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
+ <Reference Include="System.Interactive.Async">
+ <HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
- <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+ <HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
- <Reference Include="System.Interactive.Async">
- <HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.3.6.0\lib\net45\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="nunitlite">
+ <HintPath>..\packages\NUnitLite.3.6.0\lib\net45\nunitlite.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -64,7 +64,6 @@
<Compile Include="ChannelOptionsTest.cs" />
<Compile Include="Internal\TimespecTest.cs" />
<Compile Include="TimeoutsTest.cs" />
- <Compile Include="NUnitVersionTest.cs" />
<Compile Include="ChannelTest.cs" />
<Compile Include="MockServiceHelper.cs" />
<Compile Include="ResponseHeadersTest.cs" />
@@ -81,6 +80,8 @@
<Compile Include="ShutdownHookPendingCallTest.cs" />
<Compile Include="ShutdownHookClientTest.cs" />
<Compile Include="AppDomainUnloadTest.cs" />
+ <Compile Include="AuthContextTest.cs" />
+ <Compile Include="AuthPropertyTest.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
diff --git a/src/csharp/Grpc.Core.Tests/TestResult.xml b/src/csharp/Grpc.Core.Tests/TestResult.xml
deleted file mode 100644
index 13da80739c..0000000000
--- a/src/csharp/Grpc.Core.Tests/TestResult.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="no"?>
-<!--This file represents the results of running a test suite-->
-<test-results name="/usr/local/google/home/jtattermusch/github/grpc/src/csharp/GrpcCoreTests/bin/Debug/GrpcCoreTests.dll" total="3" errors="0" failures="0" not-run="0" inconclusive="0" ignored="0" skipped="0" invalid="0" date="2015-01-29" time="19:40:47">
- <environment nunit-version="2.6.0.0" clr-version="4.0.30319.17020" os-version="Unix 3.13.0.43" platform="Unix" cwd="/usr/local/google/home/jtattermusch/github/grpc/src/csharp/GrpcCoreTests" machine-name="jtattermusch.mtv.corp.google.com" user="jtattermusch" user-domain="jtattermusch.mtv.corp.google.com" />
- <culture-info current-culture="en-US" current-uiculture="en-US" />
- <test-suite type="Assembly" name="/usr/local/google/home/jtattermusch/github/grpc/src/csharp/GrpcCoreTests/bin/Debug/GrpcCoreTests.dll" executed="True" result="Success" success="True" time="0.172" asserts="0">
- <results>
- <test-suite type="Namespace" name="Google" executed="True" result="Success" success="True" time="0.166" asserts="0">
- <results>
- <test-suite type="Namespace" name="GRPC" executed="True" result="Success" success="True" time="0.166" asserts="0">
- <results>
- <test-suite type="Namespace" name="Core" executed="True" result="Success" success="True" time="0.166" asserts="0">
- <results>
- <test-suite type="Namespace" name="Tests" executed="True" result="Success" success="True" time="0.166" asserts="0">
- <results>
- <test-suite type="TestFixture" name="CallsTest" executed="True" result="Success" success="True" time="0.009" asserts="0">
- <results>
- <test-case name="Grpc.Core.Tests.CallsTest.Test1" executed="True" result="Success" success="True" time="0.004" asserts="0" />
- </results>
- </test-suite>
- <test-suite type="TestFixture" name="ClientServerTest" executed="True" result="Success" success="True" time="0.149" asserts="0">
- <results>
- <test-case name="Grpc.Core.Tests.ClientServerTest.EmptyCall" executed="True" result="Success" success="True" time="0.111" asserts="0" />
- </results>
- </test-suite>
- <test-suite type="TestFixture" name="ServerTest" executed="True" result="Success" success="True" time="0.001" asserts="0">
- <results>
- <test-case name="Grpc.Core.Tests.ServerTest.StartAndShutdownServer" executed="True" result="Success" success="True" time="0.001" asserts="0" />
- </results>
- </test-suite>
- </results>
- </test-suite>
- </results>
- </test-suite>
- </results>
- </test-suite>
- </results>
- </test-suite>
- </results>
- </test-suite>
-</test-results> \ No newline at end of file
diff --git a/src/csharp/Grpc.Core.Tests/packages.config b/src/csharp/Grpc.Core.Tests/packages.config
index 4750735fad..994a278762 100644
--- a/src/csharp/Grpc.Core.Tests/packages.config
+++ b/src/csharp/Grpc.Core.Tests/packages.config
@@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
- <package id="NUnit" version="3.2.0" targetFramework="net45" />
- <package id="NUnit.ConsoleRunner" version="3.2.0" />
- <package id="NUnitLite" version="3.2.0" targetFramework="net45" />
+ <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
+ <package id="NUnit" version="3.6.0" targetFramework="net45" />
+ <package id="NUnitLite" version="3.6.0" targetFramework="net45" />
<package id="OpenCover" version="4.6.519" />
<package id="ReportGenerator" version="2.4.4.0" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
diff --git a/src/csharp/Grpc.Core.Tests/project.json b/src/csharp/Grpc.Core.Tests/project.json
index 509084a71a..14e5ed51ad 100644
--- a/src/csharp/Grpc.Core.Tests/project.json
+++ b/src/csharp/Grpc.Core.Tests/project.json
@@ -13,8 +13,8 @@
},
"copyToOutput": {
"mappings": {
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
@@ -31,8 +31,8 @@
},
"copyToOutput": {
"mappings": {
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
@@ -45,10 +45,10 @@
"Grpc.Core": {
"target": "project"
},
- "Newtonsoft.Json": "8.0.3",
- "NUnit": "3.2.0",
- "NUnitLite": "3.2.0-*",
- "NUnit.ConsoleRunner": "3.2.0",
+ "Newtonsoft.Json": "9.0.1",
+ "NUnit": "3.6.0",
+ "NUnitLite": "3.6.0",
+ "NUnit.ConsoleRunner": "3.6.0",
"OpenCover": "4.6.519",
"ReportGenerator": "2.4.4.0"
},
diff --git a/src/csharp/Grpc.Core/AuthContext.cs b/src/csharp/Grpc.Core/AuthContext.cs
new file mode 100644
index 0000000000..340b2201c7
--- /dev/null
+++ b/src/csharp/Grpc.Core/AuthContext.cs
@@ -0,0 +1,128 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core
+{
+ /// <summary>
+ /// Authentication context for a call.
+ /// AuthContext is the only reliable source of truth when it comes to authenticating calls.
+ /// Using any other call/context properties for authentication purposes is wrong and inherently unsafe.
+ /// Note: experimental API that can change or be removed without any prior notice.
+ /// </summary>
+ public class AuthContext
+ {
+ string peerIdentityPropertyName;
+ Dictionary<string, List<AuthProperty>> properties;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:Grpc.Core.AuthContext"/> class.
+ /// </summary>
+ /// <param name="peerIdentityPropertyName">Peer identity property name.</param>
+ /// <param name="properties">Multimap of auth properties by name.</param>
+ internal AuthContext(string peerIdentityPropertyName, Dictionary<string, List<AuthProperty>> properties)
+ {
+ this.peerIdentityPropertyName = peerIdentityPropertyName;
+ this.properties = GrpcPreconditions.CheckNotNull(properties);
+ }
+
+ /// <summary>
+ /// Returns <c>true</c> if the peer is authenticated.
+ /// </summary>
+ public bool IsPeerAuthenticated
+ {
+ get
+ {
+ return peerIdentityPropertyName != null;
+ }
+ }
+
+ /// <summary>
+ /// Gets the name of the property that indicates the peer identity. Returns <c>null</c>
+ /// if the peer is not authenticated.
+ /// </summary>
+ public string PeerIdentityPropertyName
+ {
+ get
+ {
+ return peerIdentityPropertyName;
+ }
+ }
+
+ /// <summary>
+ /// Gets properties that represent the peer identity (there can be more than one). Returns an empty collection
+ /// if the peer is not authenticated.
+ /// </summary>
+ public IEnumerable<AuthProperty> PeerIdentity
+ {
+ get
+ {
+ if (peerIdentityPropertyName == null)
+ {
+ return Enumerable.Empty<AuthProperty>();
+ }
+ return properties[peerIdentityPropertyName];
+ }
+ }
+
+ /// <summary>
+ /// Gets the auth properties of this context.
+ /// </summary>
+ public IEnumerable<AuthProperty> Properties
+ {
+ get
+ {
+ return properties.Values.SelectMany(v => v);
+ }
+ }
+
+ /// <summary>
+ /// Returns the auth properties with given name (there can be more than one).
+ /// If no properties of given name exist, an empty collection will be returned.
+ /// </summary>
+ public IEnumerable<AuthProperty> FindPropertiesByName(string propertyName)
+ {
+ List<AuthProperty> result;
+ if (!properties.TryGetValue(propertyName, out result))
+ {
+ return Enumerable.Empty<AuthProperty>();
+ }
+ return result;
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/AuthProperty.cs b/src/csharp/Grpc.Core/AuthProperty.cs
new file mode 100644
index 0000000000..c7a132b09e
--- /dev/null
+++ b/src/csharp/Grpc.Core/AuthProperty.cs
@@ -0,0 +1,126 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core
+{
+ /// <summary>
+ /// A property of an <see cref="AuthContext"/>.
+ /// Note: experimental API that can change or be removed without any prior notice.
+ /// </summary>
+ public class AuthProperty
+ {
+ string name;
+ byte[] valueBytes;
+ Lazy<string> value;
+
+ private AuthProperty(string name, byte[] valueBytes)
+ {
+ this.name = GrpcPreconditions.CheckNotNull(name);
+ this.valueBytes = GrpcPreconditions.CheckNotNull(valueBytes);
+ this.value = new Lazy<string>(() => MarshalUtils.GetStringUTF8(this.valueBytes));
+ }
+
+ /// <summary>
+ /// Gets the name of the property.
+ /// </summary>
+ public string Name
+ {
+ get
+ {
+ return name;
+ }
+ }
+
+ /// <summary>
+ /// Gets the string value of the property.
+ /// </summary>
+ public string Value
+ {
+ get
+ {
+ return value.Value;
+ }
+ }
+
+ /// <summary>
+ /// Gets the binary value of the property.
+ /// </summary>
+ public byte[] ValueBytes
+ {
+ get
+ {
+ var valueCopy = new byte[valueBytes.Length];
+ Buffer.BlockCopy(valueBytes, 0, valueCopy, 0, valueBytes.Length);
+ return valueCopy;
+ }
+ }
+
+ /// <summary>
+ /// Creates an instance of <c>AuthProperty</c>.
+ /// </summary>
+ /// <param name="name">the name</param>
+ /// <param name="valueBytes">the binary value of the property</param>
+ public static AuthProperty Create(string name, byte[] valueBytes)
+ {
+ GrpcPreconditions.CheckNotNull(valueBytes);
+ var valueCopy = new byte[valueBytes.Length];
+ Buffer.BlockCopy(valueBytes, 0, valueCopy, 0, valueBytes.Length);
+ return new AuthProperty(name, valueCopy);
+ }
+
+ /// <summary>
+ /// Gets the binary value of the property (without making a defensive copy).
+ /// </summary>
+ internal byte[] ValueBytesUnsafe
+ {
+ get
+ {
+ return valueBytes;
+ }
+ }
+
+ /// <summary>
+ /// Creates and instance of <c>AuthProperty</c> without making a defensive copy of <c>valueBytes</c>.
+ /// </summary>
+ internal static AuthProperty CreateUnsafe(string name, byte[] valueBytes)
+ {
+ return new AuthProperty(name, valueBytes);
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 23e1ddcf7f..d6d8dfac22 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -131,6 +131,10 @@
<Compile Include="Internal\RequestCallContextSafeHandle.cs" />
<Compile Include="Utils\TaskUtils.cs" />
<Compile Include="Internal\CallFlags.cs" />
+ <Compile Include="AuthContext.cs" />
+ <Compile Include="Internal\AuthContextSafeHandle.cs" />
+ <Compile Include="Internal\MarshalUtils.cs" />
+ <Compile Include="AuthProperty.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Grpc.Core.project.json" />
diff --git a/src/csharp/Grpc.Core/Internal/AuthContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/AuthContextSafeHandle.cs
new file mode 100644
index 0000000000..59e33a0fdf
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/AuthContextSafeHandle.cs
@@ -0,0 +1,119 @@
+#region Copyright notice and license
+
+// Copyright 2017, 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.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using Grpc.Core;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core.Internal
+{
+ /// <summary>
+ /// grpc_auth_context
+ /// </summary>
+ internal class AuthContextSafeHandle : SafeHandleZeroIsInvalid
+ {
+ static readonly NativeMethods Native = NativeMethods.Get();
+
+ private AuthContextSafeHandle()
+ {
+ }
+
+ /// <summary>
+ /// Copies contents of the native auth context into a new <c>AuthContext</c> instance.
+ /// </summary>
+ public AuthContext ToAuthContext()
+ {
+ if (IsInvalid)
+ {
+ return new AuthContext(null, new Dictionary<string, List<AuthProperty>>());
+ }
+
+ var peerIdentityPropertyName = Marshal.PtrToStringAnsi(Native.grpcsharp_auth_context_peer_identity_property_name(this));
+
+ var propertiesDict = new Dictionary<string, List<AuthProperty>>();
+
+ var it = Native.grpcsharp_auth_context_property_iterator(this);
+ IntPtr authPropertyPtr = IntPtr.Zero;
+ while ((authPropertyPtr = Native.grpcsharp_auth_property_iterator_next(ref it)) != IntPtr.Zero)
+ {
+ var authProperty = PtrToAuthProperty(authPropertyPtr);
+
+ if (!propertiesDict.ContainsKey(authProperty.Name))
+ {
+ propertiesDict[authProperty.Name] = new List<AuthProperty>();
+ }
+ propertiesDict[authProperty.Name].Add(authProperty);
+ }
+
+ return new AuthContext(peerIdentityPropertyName, propertiesDict);
+ }
+
+ protected override bool ReleaseHandle()
+ {
+ Native.grpcsharp_auth_context_release(handle);
+ return true;
+ }
+
+ private AuthProperty PtrToAuthProperty(IntPtr authPropertyPtr)
+ {
+ var nativeAuthProperty = (NativeAuthProperty) Marshal.PtrToStructure(authPropertyPtr, typeof(NativeAuthProperty));
+ var name = Marshal.PtrToStringAnsi(nativeAuthProperty.Name);
+ var valueBytes = new byte[(int) nativeAuthProperty.ValueLength];
+ Marshal.Copy(nativeAuthProperty.Value, valueBytes, 0, (int)nativeAuthProperty.ValueLength);
+ return AuthProperty.CreateUnsafe(name, valueBytes);
+ }
+
+ /// <summary>
+ /// grpc_auth_property
+ /// </summary>
+ internal struct NativeAuthProperty
+ {
+ public IntPtr Name;
+ public IntPtr Value;
+ public UIntPtr ValueLength;
+ }
+
+ /// <summary>
+ /// grpc_auth_property_iterator
+ /// </summary>
+ internal struct NativeAuthPropertyIterator
+ {
+ public IntPtr AuthContext;
+ public UIntPtr Index;
+ public IntPtr Name;
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
index efae149f09..6dee6d8c35 100644
--- a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
@@ -43,7 +43,6 @@ namespace Grpc.Core.Internal
/// </summary>
internal class BatchContextSafeHandle : SafeHandleZeroIsInvalid
{
- static readonly Encoding EncodingUTF8 = System.Text.Encoding.UTF8;
static readonly NativeMethods Native = NativeMethods.Get();
private BatchContextSafeHandle()
@@ -75,7 +74,7 @@ namespace Grpc.Core.Internal
{
UIntPtr detailsLength;
IntPtr detailsPtr = Native.grpcsharp_batch_context_recv_status_on_client_details(this, out detailsLength);
- string details = PtrToStringUtf8(detailsPtr, (int) detailsLength.ToUInt32());
+ string details = MarshalUtils.PtrToStringUTF8(detailsPtr, (int) detailsLength.ToUInt32());
var status = new Status(Native.grpcsharp_batch_context_recv_status_on_client_status(this), details);
IntPtr metadataArrayPtr = Native.grpcsharp_batch_context_recv_status_on_client_trailing_metadata(this);
@@ -108,12 +107,5 @@ namespace Grpc.Core.Internal
Native.grpcsharp_batch_context_destroy(handle);
return true;
}
-
- string PtrToStringUtf8(IntPtr ptr, int len)
- {
- var bytes = new byte[len];
- Marshal.Copy(ptr, bytes, 0, len);
- return EncodingUTF8.GetString(bytes);
- }
}
}
diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
index 710ca480e8..3c368fbc6c 100644
--- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
@@ -45,7 +45,6 @@ namespace Grpc.Core.Internal
internal class CallSafeHandle : SafeHandleZeroIsInvalid, INativeCall
{
public static readonly CallSafeHandle NullInstance = new CallSafeHandle();
- static readonly Encoding EncodingUTF8 = System.Text.Encoding.UTF8;
static readonly NativeMethods Native = NativeMethods.Get();
const uint GRPC_WRITE_BUFFER_HINT = 1;
@@ -140,7 +139,7 @@ namespace Grpc.Core.Internal
var ctx = BatchContextSafeHandle.Create();
var optionalPayloadLength = optionalPayload != null ? new UIntPtr((ulong)optionalPayload.Length) : UIntPtr.Zero;
completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
- var statusDetailBytes = EncodingUTF8.GetBytes(status.Detail);
+ var statusDetailBytes = MarshalUtils.GetBytesUTF8(status.Detail);
Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, statusDetailBytes, new UIntPtr((ulong)statusDetailBytes.Length), metadataArray, sendEmptyInitialMetadata,
optionalPayload, optionalPayloadLength, writeFlags).CheckOk();
}
@@ -204,6 +203,11 @@ namespace Grpc.Core.Internal
}
}
+ public AuthContextSafeHandle GetAuthContext()
+ {
+ return Native.grpcsharp_call_auth_context(this);
+ }
+
protected override bool ReleaseHandle()
{
Native.grpcsharp_call_destroy(handle);
diff --git a/src/csharp/Grpc.Core/Internal/MarshalUtils.cs b/src/csharp/Grpc.Core/Internal/MarshalUtils.cs
new file mode 100644
index 0000000000..897e2f70bb
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/MarshalUtils.cs
@@ -0,0 +1,90 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Grpc.Core.Internal
+{
+ /// <summary>
+ /// Useful methods for native/managed marshalling.
+ /// </summary>
+ internal static class MarshalUtils
+ {
+ static readonly Encoding EncodingUTF8 = System.Text.Encoding.UTF8;
+ static readonly Encoding EncodingASCII = System.Text.Encoding.ASCII;
+
+ /// <summary>
+ /// Converts <c>IntPtr</c> pointing to a UTF-8 encoded byte array to <c>string</c>.
+ /// </summary>
+ public static string PtrToStringUTF8(IntPtr ptr, int len)
+ {
+ var bytes = new byte[len];
+ Marshal.Copy(ptr, bytes, 0, len);
+ return EncodingUTF8.GetString(bytes);
+ }
+
+ /// <summary>
+ /// Returns byte array containing UTF-8 encoding of given string.
+ /// </summary>
+ public static byte[] GetBytesUTF8(string str)
+ {
+ return EncodingUTF8.GetBytes(str);
+ }
+
+ /// <summary>
+ /// Get string from a UTF8 encoded byte array.
+ /// </summary>
+ public static string GetStringUTF8(byte[] bytes)
+ {
+ return EncodingUTF8.GetString(bytes);
+ }
+
+ /// <summary>
+ /// Returns byte array containing ASCII encoding of given string.
+ /// </summary>
+ public static byte[] GetBytesASCII(string str)
+ {
+ return EncodingASCII.GetBytes(str);
+ }
+
+ /// <summary>
+ /// Get string from an ASCII encoded byte array.
+ /// </summary>
+ public static string GetStringASCII(byte[] bytes)
+ {
+ return EncodingASCII.GetString(bytes);
+ }
+ }
+}
diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
index aff9550e8d..dd65f05217 100644
--- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs
+++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs
@@ -148,6 +148,12 @@ namespace Grpc.Core.Internal
public readonly Delegates.grpcsharp_server_shutdown_and_notify_callback_delegate grpcsharp_server_shutdown_and_notify_callback;
public readonly Delegates.grpcsharp_server_destroy_delegate grpcsharp_server_destroy;
+ public readonly Delegates.grpcsharp_call_auth_context_delegate grpcsharp_call_auth_context;
+ public readonly Delegates.grpcsharp_auth_context_peer_identity_property_name_delegate grpcsharp_auth_context_peer_identity_property_name;
+ public readonly Delegates.grpcsharp_auth_context_property_iterator_delegate grpcsharp_auth_context_property_iterator;
+ public readonly Delegates.grpcsharp_auth_property_iterator_next_delegate grpcsharp_auth_property_iterator_next;
+ public readonly Delegates.grpcsharp_auth_context_release_delegate grpcsharp_auth_context_release;
+
public readonly Delegates.gprsharp_now_delegate gprsharp_now;
public readonly Delegates.gprsharp_inf_future_delegate gprsharp_inf_future;
public readonly Delegates.gprsharp_inf_past_delegate gprsharp_inf_past;
@@ -256,6 +262,12 @@ namespace Grpc.Core.Internal
this.grpcsharp_server_shutdown_and_notify_callback = GetMethodDelegate<Delegates.grpcsharp_server_shutdown_and_notify_callback_delegate>(library);
this.grpcsharp_server_destroy = GetMethodDelegate<Delegates.grpcsharp_server_destroy_delegate>(library);
+ this.grpcsharp_call_auth_context = GetMethodDelegate<Delegates.grpcsharp_call_auth_context_delegate>(library);
+ this.grpcsharp_auth_context_peer_identity_property_name = GetMethodDelegate<Delegates.grpcsharp_auth_context_peer_identity_property_name_delegate>(library);
+ this.grpcsharp_auth_context_property_iterator = GetMethodDelegate<Delegates.grpcsharp_auth_context_property_iterator_delegate>(library);
+ this.grpcsharp_auth_property_iterator_next = GetMethodDelegate<Delegates.grpcsharp_auth_property_iterator_next_delegate>(library);
+ this.grpcsharp_auth_context_release = GetMethodDelegate<Delegates.grpcsharp_auth_context_release_delegate>(library);
+
this.gprsharp_now = GetMethodDelegate<Delegates.gprsharp_now_delegate>(library);
this.gprsharp_inf_future = GetMethodDelegate<Delegates.gprsharp_inf_future_delegate>(library);
this.gprsharp_inf_past = GetMethodDelegate<Delegates.gprsharp_inf_past_delegate>(library);
@@ -404,6 +416,12 @@ namespace Grpc.Core.Internal
public delegate void grpcsharp_server_shutdown_and_notify_callback_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx);
public delegate void grpcsharp_server_destroy_delegate(IntPtr server);
+ public delegate AuthContextSafeHandle grpcsharp_call_auth_context_delegate(CallSafeHandle call);
+ public delegate IntPtr grpcsharp_auth_context_peer_identity_property_name_delegate(AuthContextSafeHandle authContext); // returns const char*
+ public delegate AuthContextSafeHandle.NativeAuthPropertyIterator grpcsharp_auth_context_property_iterator_delegate(AuthContextSafeHandle authContext);
+ public delegate IntPtr grpcsharp_auth_property_iterator_next_delegate(ref AuthContextSafeHandle.NativeAuthPropertyIterator iterator); // returns const auth_property*
+ public delegate void grpcsharp_auth_context_release_delegate(IntPtr authContext);
+
public delegate Timespec gprsharp_now_delegate(ClockType clockType);
public delegate Timespec gprsharp_inf_future_delegate(ClockType clockType);
public delegate Timespec gprsharp_inf_past_delegate(ClockType clockType);
diff --git a/src/csharp/Grpc.Core/Metadata.cs b/src/csharp/Grpc.Core/Metadata.cs
index 6fc715d6ee..6e195b49cc 100644
--- a/src/csharp/Grpc.Core/Metadata.cs
+++ b/src/csharp/Grpc.Core/Metadata.cs
@@ -32,12 +32,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Globalization;
-using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
+using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core
@@ -242,7 +240,6 @@ namespace Grpc.Core
/// </summary>
public class Entry
{
- private static readonly Encoding Encoding = Encoding.ASCII;
private static readonly Regex ValidKeyRegex = new Regex("^[a-z0-9_-]+$");
readonly string key;
@@ -306,7 +303,7 @@ namespace Grpc.Core
{
if (valueBytes == null)
{
- return Encoding.GetBytes(value);
+ return MarshalUtils.GetBytesASCII(value);
}
// defensive copy to guarantee immutability
@@ -324,7 +321,7 @@ namespace Grpc.Core
get
{
GrpcPreconditions.CheckState(!IsBinary, "Cannot access string value of a binary metadata entry");
- return value ?? Encoding.GetString(valueBytes);
+ return value ?? MarshalUtils.GetStringASCII(valueBytes);
}
}
@@ -358,7 +355,7 @@ namespace Grpc.Core
/// </summary>
internal byte[] GetSerializedValueUnsafe()
{
- return valueBytes ?? Encoding.GetBytes(value);
+ return valueBytes ?? MarshalUtils.GetBytesASCII(value);
}
/// <summary>
@@ -371,7 +368,7 @@ namespace Grpc.Core
{
return new Entry(key, null, valueBytes);
}
- return new Entry(key, Encoding.GetString(valueBytes), null);
+ return new Entry(key, MarshalUtils.GetStringASCII(valueBytes), null);
}
private static string NormalizeKey(string key)
diff --git a/src/csharp/Grpc.Core/NativeDeps.Windows.targets b/src/csharp/Grpc.Core/NativeDeps.Windows.targets
index 93db0935bc..623f58b95b 100644
--- a/src/csharp/Grpc.Core/NativeDeps.Windows.targets
+++ b/src/csharp/Grpc.Core/NativeDeps.Windows.targets
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
- <Content Include="..\..\..\vsprojects\$(NativeDependenciesConfiguration)\grpc_csharp_ext.dll">
+ <Content Include="..\..\..\cmake\build\Win32\$(NativeDependenciesConfiguration)\grpc_csharp_ext.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>grpc_csharp_ext.x86.dll</Link>
</Content>
diff --git a/src/csharp/Grpc.Core/ServerCallContext.cs b/src/csharp/Grpc.Core/ServerCallContext.cs
index 8f28fbc045..c8950b7677 100644
--- a/src/csharp/Grpc.Core/ServerCallContext.cs
+++ b/src/csharp/Grpc.Core/ServerCallContext.cs
@@ -32,7 +32,6 @@
#endregion
using System;
-using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
@@ -56,6 +55,7 @@ namespace Grpc.Core
private Status status = Status.DefaultSuccess;
private Func<Metadata, Task> writeHeadersFunc;
private IHasWriteOptions writeOptionsHolder;
+ private Lazy<AuthContext> authContext;
internal ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder)
@@ -68,6 +68,7 @@ namespace Grpc.Core
this.cancellationToken = cancellationToken;
this.writeHeadersFunc = writeHeadersFunc;
this.writeOptionsHolder = writeOptionsHolder;
+ this.authContext = new Lazy<AuthContext>(GetAuthContextEager);
}
/// <summary>
@@ -187,6 +188,26 @@ namespace Grpc.Core
writeOptionsHolder.WriteOptions = value;
}
}
+
+ /// <summary>
+ /// Gets the <c>AuthContext</c> associated with this call.
+ /// Note: Access to AuthContext is an experimental API that can change without any prior notice.
+ /// </summary>
+ public AuthContext AuthContext
+ {
+ get
+ {
+ return authContext.Value;
+ }
+ }
+
+ private AuthContext GetAuthContextEager()
+ {
+ using (var authContextNative = callHandle.GetAuthContext())
+ {
+ return authContextNative.ToAuthContext();
+ }
+ }
}
/// <summary>
diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs
index f01a024db4..6012d904b6 100644
--- a/src/csharp/Grpc.Core/VersionInfo.cs
+++ b/src/csharp/Grpc.Core/VersionInfo.cs
@@ -48,11 +48,11 @@ namespace Grpc.Core
/// <summary>
/// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
/// </summary>
- public const string CurrentAssemblyFileVersion = "1.2.0.0";
+ public const string CurrentAssemblyFileVersion = "1.3.0.0";
/// <summary>
/// Current version of gRPC C#
/// </summary>
- public const string CurrentVersion = "1.2.0-dev";
+ public const string CurrentVersion = "1.3.0-dev";
}
}
diff --git a/src/csharp/Grpc.Core/project.json b/src/csharp/Grpc.Core/project.json
index 0e37ec8927..a1306baa87 100644
--- a/src/csharp/Grpc.Core/project.json
+++ b/src/csharp/Grpc.Core/project.json
@@ -1,5 +1,5 @@
{
- "version": "1.2.0-dev",
+ "version": "1.3.0-dev",
"title": "gRPC C# Core",
"authors": [ "Google Inc." ],
"copyright": "Copyright 2015, Google Inc.",
diff --git a/src/csharp/Grpc.Examples.MathClient/project.json b/src/csharp/Grpc.Examples.MathClient/project.json
index 9a8880b5d4..81c17151aa 100644
--- a/src/csharp/Grpc.Examples.MathClient/project.json
+++ b/src/csharp/Grpc.Examples.MathClient/project.json
@@ -13,8 +13,8 @@
},
"copyToOutput": {
"mappings": {
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
@@ -31,8 +31,8 @@
},
"copyToOutput": {
"mappings": {
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
diff --git a/src/csharp/Grpc.Examples.MathServer/project.json b/src/csharp/Grpc.Examples.MathServer/project.json
index 9a8880b5d4..81c17151aa 100644
--- a/src/csharp/Grpc.Examples.MathServer/project.json
+++ b/src/csharp/Grpc.Examples.MathServer/project.json
@@ -13,8 +13,8 @@
},
"copyToOutput": {
"mappings": {
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
@@ -31,8 +31,8 @@
},
"copyToOutput": {
"mappings": {
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
diff --git a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
index d22fe87825..c96243b1c7 100644
--- a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
+++ b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
@@ -27,17 +27,17 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
+ <Reference Include="System.Interactive.Async">
+ <HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
+ </Reference>
<Reference Include="nunit.framework">
- <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
+ <HintPath>..\packages\NUnit.3.6.0\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="nunitlite">
- <HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
+ <HintPath>..\packages\NUnitLite.3.6.0\lib\net45\nunitlite.dll</HintPath>
</Reference>
<Reference Include="Google.Protobuf">
- <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
- </Reference>
- <Reference Include="System.Interactive.Async">
- <HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
+ <HintPath>..\packages\Google.Protobuf.3.2.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
diff --git a/src/csharp/Grpc.Examples.Tests/packages.config b/src/csharp/Grpc.Examples.Tests/packages.config
index 0fed4dbd41..8a7f7a0652 100644
--- a/src/csharp/Grpc.Examples.Tests/packages.config
+++ b/src/csharp/Grpc.Examples.Tests/packages.config
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
- <package id="NUnit" version="3.2.0" targetFramework="net45" />
- <package id="NUnitLite" version="3.2.0" targetFramework="net45" />
+ <package id="Google.Protobuf" version="3.2.0" targetFramework="net45" />
+ <package id="NUnit" version="3.6.0" targetFramework="net45" />
+ <package id="NUnitLite" version="3.6.0" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Examples.Tests/project.json b/src/csharp/Grpc.Examples.Tests/project.json
index 3e130beeac..4ffcaf57fd 100644
--- a/src/csharp/Grpc.Examples.Tests/project.json
+++ b/src/csharp/Grpc.Examples.Tests/project.json
@@ -13,8 +13,8 @@
},
"copyToOutput": {
"mappings": {
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
@@ -31,8 +31,8 @@
},
"copyToOutput": {
"mappings": {
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
@@ -45,8 +45,8 @@
"Grpc.Examples": {
"target": "project"
},
- "NUnit": "3.2.0",
- "NUnitLite": "3.2.0-*"
+ "NUnit": "3.6.0",
+ "NUnitLite": "3.6.0"
},
"frameworks": {
"net45": { },
diff --git a/src/csharp/Grpc.Examples/Grpc.Examples.csproj b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
index 44acb6c2e3..fc927543f7 100644
--- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj
+++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
@@ -3,8 +3,6 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>10.0.0</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{7DC1433E-3225-42C7-B7EA-546D56E27A4B}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>Grpc.Examples</RootNamespace>
@@ -28,17 +26,17 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
- <Reference Include="nunit.framework">
- <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
- </Reference>
<Reference Include="System" />
<Reference Include="System.Data.Linq" />
- <Reference Include="Google.Protobuf">
- <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
- </Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.3.6.0\lib\net45\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.Protobuf">
+ <HintPath>..\packages\Google.Protobuf.3.2.0\lib\net45\Google.Protobuf.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
diff --git a/src/csharp/Grpc.Examples/packages.config b/src/csharp/Grpc.Examples/packages.config
index c7db26bd64..79a898081e 100644
--- a/src/csharp/Grpc.Examples/packages.config
+++ b/src/csharp/Grpc.Examples/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
- <package id="NUnit" version="3.2.0" targetFramework="net45" />
+ <package id="Google.Protobuf" version="3.2.0" targetFramework="net45" />
+ <package id="NUnit" version="3.6.0" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Examples/project.json b/src/csharp/Grpc.Examples/project.json
index 21a730cb22..3ee0a71356 100644
--- a/src/csharp/Grpc.Examples/project.json
+++ b/src/csharp/Grpc.Examples/project.json
@@ -6,15 +6,10 @@
"Grpc.Core": {
"target": "project"
},
- "Google.Protobuf": "3.0.0"
+ "Google.Protobuf": "3.2.0"
},
"frameworks": {
- "net45": {
- "frameworkAssemblies": {
- "System.Runtime": "",
- "System.IO": ""
- }
- },
+ "net45": {},
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
diff --git a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj
index b82f976861..71f0ee19b8 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj
+++ b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj
@@ -35,14 +35,14 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
+ <Reference Include="Google.Protobuf">
+ <HintPath>..\packages\Google.Protobuf.3.2.0\lib\net45\Google.Protobuf.dll</HintPath>
+ </Reference>
<Reference Include="nunit.framework">
- <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
+ <HintPath>..\packages\NUnit.3.6.0\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="nunitlite">
- <HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
- </Reference>
- <Reference Include="Google.Protobuf">
- <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
+ <HintPath>..\packages\NUnitLite.3.6.0\lib\net45\nunitlite.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
diff --git a/src/csharp/Grpc.HealthCheck.Tests/packages.config b/src/csharp/Grpc.HealthCheck.Tests/packages.config
index e796d6b135..48c94bc4a3 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/packages.config
+++ b/src/csharp/Grpc.HealthCheck.Tests/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
- <package id="NUnit" version="3.2.0" targetFramework="net45" />
- <package id="NUnitLite" version="3.2.0" targetFramework="net45" />
+ <package id="Google.Protobuf" version="3.2.0" targetFramework="net45" />
+ <package id="NUnit" version="3.6.0" targetFramework="net45" />
+ <package id="NUnitLite" version="3.6.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck.Tests/project.json b/src/csharp/Grpc.HealthCheck.Tests/project.json
index addc782afe..2814cbfe46 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/project.json
+++ b/src/csharp/Grpc.HealthCheck.Tests/project.json
@@ -13,8 +13,8 @@
},
"copyToOutput": {
"mappings": {
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
@@ -31,8 +31,8 @@
},
"copyToOutput": {
"mappings": {
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
@@ -45,8 +45,8 @@
"Grpc.HealthCheck": {
"target": "project"
},
- "NUnit": "3.2.0",
- "NUnitLite": "3.2.0-*"
+ "NUnit": "3.6.0",
+ "NUnitLite": "3.6.0"
},
"frameworks": {
"net45": { },
diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
index 63aa18584d..171525b708 100644
--- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
+++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
@@ -36,12 +36,12 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
- <Reference Include="Google.Protobuf">
- <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
- </Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
+ <Reference Include="Google.Protobuf">
+ <HintPath>..\packages\Google.Protobuf.3.2.0\lib\net45\Google.Protobuf.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
diff --git a/src/csharp/Grpc.HealthCheck/packages.config b/src/csharp/Grpc.HealthCheck/packages.config
index 5ab40b7a8c..eec292b306 100644
--- a/src/csharp/Grpc.HealthCheck/packages.config
+++ b/src/csharp/Grpc.HealthCheck/packages.config
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
+ <package id="Google.Protobuf" version="3.2.0" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.HealthCheck/project.json b/src/csharp/Grpc.HealthCheck/project.json
index 5d3b2f554b..e93d0bf81b 100644
--- a/src/csharp/Grpc.HealthCheck/project.json
+++ b/src/csharp/Grpc.HealthCheck/project.json
@@ -1,5 +1,5 @@
{
- "version": "1.2.0-dev",
+ "version": "1.3.0-dev",
"title": "gRPC C# Healthchecking",
"authors": [ "Google Inc." ],
"copyright": "Copyright 2015, Google Inc.",
@@ -21,16 +21,11 @@
}
},
"dependencies": {
- "Grpc.Core": "1.2.0-dev",
- "Google.Protobuf": "3.0.0"
+ "Grpc.Core": "1.3.0-dev",
+ "Google.Protobuf": "3.2.0"
},
"frameworks": {
- "net45": {
- "frameworkAssemblies": {
- "System.Runtime": "",
- "System.IO": ""
- }
- },
+ "net45": {},
"netstandard1.5": {
"dependencies": {
"NETStandard.Library": "1.6.0"
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
index 6bb5f33966..a793f3f6df 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
@@ -34,33 +34,6 @@
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.WebRequest" />
- <Reference Include="BouncyCastle.Crypto">
- <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
- </Reference>
- <Reference Include="Newtonsoft.Json">
- <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
- </Reference>
- <Reference Include="log4net">
- <HintPath>..\packages\log4net.2.0.3\lib\net40-full\log4net.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Core">
- <HintPath>..\packages\Google.Apis.Core.1.16.0\lib\net45\Google.Apis.Core.dll</HintPath>
- </Reference>
- <Reference Include="Zlib.Portable">
- <HintPath>..\packages\Zlib.Portable.Signed.1.11.0\lib\portable-net4+sl5+wp8+win8+wpa81+MonoTouch+MonoAndroid\Zlib.Portable.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis">
- <HintPath>..\packages\Google.Apis.1.16.0\lib\net45\Google.Apis.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.PlatformServices">
- <HintPath>..\packages\Google.Apis.1.16.0\lib\net45\Google.Apis.PlatformServices.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Auth">
- <HintPath>..\packages\Google.Apis.Auth.1.16.0\lib\net45\Google.Apis.Auth.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Auth.PlatformServices">
- <HintPath>..\packages\Google.Apis.Auth.1.16.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
- </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
@@ -82,6 +55,5 @@
</ItemGroup>
<ItemGroup>
<None Include="Grpc.IntegrationTesting.Client.project.json" />
- <None Include="packages.config" />
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/packages.config b/src/csharp/Grpc.IntegrationTesting.Client/packages.config
deleted file mode 100644
index 11c6375c63..0000000000
--- a/src/csharp/Grpc.IntegrationTesting.Client/packages.config
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
- <package id="Google.Apis" version="1.16.0" targetFramework="net45" />
- <package id="Google.Apis.Auth" version="1.16.0" targetFramework="net45" />
- <package id="Google.Apis.Core" version="1.16.0" targetFramework="net45" />
- <package id="log4net" version="2.0.3" targetFramework="net45" />
- <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
- <package id="Zlib.Portable.Signed" version="1.11.0" targetFramework="net45" />
-</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/project.json b/src/csharp/Grpc.IntegrationTesting.Client/project.json
index ad81cbc48b..f90528151b 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.Client/project.json
@@ -16,8 +16,8 @@
"data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
"data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
"data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
@@ -37,8 +37,8 @@
"data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
"data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
"data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/packages.config b/src/csharp/Grpc.IntegrationTesting.QpsWorker/packages.config
deleted file mode 100644
index 79ece06bef..0000000000
--- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/packages.config
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
-</packages>
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json
index 2c7643b74f..161e602abc 100644
--- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json
@@ -16,8 +16,8 @@
"data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
"data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
"data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
@@ -37,8 +37,8 @@
"data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
"data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
"data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
index 081dc24fbf..80d36363f7 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
@@ -34,33 +34,6 @@
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.WebRequest" />
- <Reference Include="BouncyCastle.Crypto">
- <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
- </Reference>
- <Reference Include="Newtonsoft.Json">
- <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
- </Reference>
- <Reference Include="log4net">
- <HintPath>..\packages\log4net.2.0.3\lib\net40-full\log4net.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Core">
- <HintPath>..\packages\Google.Apis.Core.1.16.0\lib\net45\Google.Apis.Core.dll</HintPath>
- </Reference>
- <Reference Include="Zlib.Portable">
- <HintPath>..\packages\Zlib.Portable.Signed.1.11.0\lib\portable-net4+sl5+wp8+win8+wpa81+MonoTouch+MonoAndroid\Zlib.Portable.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis">
- <HintPath>..\packages\Google.Apis.1.16.0\lib\net45\Google.Apis.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.PlatformServices">
- <HintPath>..\packages\Google.Apis.1.16.0\lib\net45\Google.Apis.PlatformServices.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Auth">
- <HintPath>..\packages\Google.Apis.Auth.1.16.0\lib\net45\Google.Apis.Auth.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Auth.PlatformServices">
- <HintPath>..\packages\Google.Apis.Auth.1.16.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
- </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
@@ -82,6 +55,5 @@
</ItemGroup>
<ItemGroup>
<None Include="Grpc.IntegrationTesting.Server.project.json" />
- <None Include="packages.config" />
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/packages.config b/src/csharp/Grpc.IntegrationTesting.Server/packages.config
deleted file mode 100644
index 11c6375c63..0000000000
--- a/src/csharp/Grpc.IntegrationTesting.Server/packages.config
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
- <package id="Google.Apis" version="1.16.0" targetFramework="net45" />
- <package id="Google.Apis.Auth" version="1.16.0" targetFramework="net45" />
- <package id="Google.Apis.Core" version="1.16.0" targetFramework="net45" />
- <package id="log4net" version="2.0.3" targetFramework="net45" />
- <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
- <package id="Zlib.Portable.Signed" version="1.11.0" targetFramework="net45" />
-</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/project.json b/src/csharp/Grpc.IntegrationTesting.Server/project.json
index ad81cbc48b..f90528151b 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.Server/project.json
@@ -16,8 +16,8 @@
"data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
"data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
"data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
@@ -37,8 +37,8 @@
"data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
"data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
"data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/packages.config b/src/csharp/Grpc.IntegrationTesting.StressClient/packages.config
deleted file mode 100644
index 79ece06bef..0000000000
--- a/src/csharp/Grpc.IntegrationTesting.StressClient/packages.config
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
-</packages>
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/project.json b/src/csharp/Grpc.IntegrationTesting.StressClient/project.json
index ad81cbc48b..f90528151b 100644
--- a/src/csharp/Grpc.IntegrationTesting.StressClient/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.StressClient/project.json
@@ -16,8 +16,8 @@
"data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
"data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
"data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
@@ -37,8 +37,8 @@
"data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
"data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
"data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
diff --git a/src/csharp/Grpc.IntegrationTesting/Control.cs b/src/csharp/Grpc.IntegrationTesting/Control.cs
index 3f4862d567..6c0176fb43 100644
--- a/src/csharp/Grpc.IntegrationTesting/Control.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Control.cs
@@ -30,63 +30,66 @@ namespace Grpc.Testing {
"cnBjLnRlc3RpbmcuQ2xvc2VkTG9vcFBhcmFtc0gAEi4KB3BvaXNzb24YAiAB",
"KAsyGy5ncnBjLnRlc3RpbmcuUG9pc3NvblBhcmFtc0gAQgYKBGxvYWQiQwoO",
"U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy",
- "X2hvc3Rfb3ZlcnJpZGUYAiABKAki8AMKDENsaWVudENvbmZpZxIWCg5zZXJ2",
- "ZXJfdGFyZ2V0cxgBIAMoCRItCgtjbGllbnRfdHlwZRgCIAEoDjIYLmdycGMu",
- "dGVzdGluZy5DbGllbnRUeXBlEjUKD3NlY3VyaXR5X3BhcmFtcxgDIAEoCzIc",
- "LmdycGMudGVzdGluZy5TZWN1cml0eVBhcmFtcxIkChxvdXRzdGFuZGluZ19y",
- "cGNzX3Blcl9jaGFubmVsGAQgASgFEhcKD2NsaWVudF9jaGFubmVscxgFIAEo",
- "BRIcChRhc3luY19jbGllbnRfdGhyZWFkcxgHIAEoBRInCghycGNfdHlwZRgI",
- "IAEoDjIVLmdycGMudGVzdGluZy5ScGNUeXBlEi0KC2xvYWRfcGFyYW1zGAog",
- "ASgLMhguZ3JwYy50ZXN0aW5nLkxvYWRQYXJhbXMSMwoOcGF5bG9hZF9jb25m",
- "aWcYCyABKAsyGy5ncnBjLnRlc3RpbmcuUGF5bG9hZENvbmZpZxI3ChBoaXN0",
- "b2dyYW1fcGFyYW1zGAwgASgLMh0uZ3JwYy50ZXN0aW5nLkhpc3RvZ3JhbVBh",
- "cmFtcxIRCgljb3JlX2xpc3QYDSADKAUSEgoKY29yZV9saW1pdBgOIAEoBRIY",
- "ChBvdGhlcl9jbGllbnRfYXBpGA8gASgJIjgKDENsaWVudFN0YXR1cxIoCgVz",
- "dGF0cxgBIAEoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cyIVCgRNYXJr",
- "Eg0KBXJlc2V0GAEgASgIImgKCkNsaWVudEFyZ3MSKwoFc2V0dXAYASABKAsy",
- "Gi5ncnBjLnRlc3RpbmcuQ2xpZW50Q29uZmlnSAASIgoEbWFyaxgCIAEoCzIS",
- "LmdycGMudGVzdGluZy5NYXJrSABCCQoHYXJndHlwZSK0AgoMU2VydmVyQ29u",
- "ZmlnEi0KC3NlcnZlcl90eXBlGAEgASgOMhguZ3JwYy50ZXN0aW5nLlNlcnZl",
- "clR5cGUSNQoPc2VjdXJpdHlfcGFyYW1zGAIgASgLMhwuZ3JwYy50ZXN0aW5n",
- "LlNlY3VyaXR5UGFyYW1zEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNfc2VydmVy",
- "X3RocmVhZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5wYXlsb2Fk",
- "X2NvbmZpZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmlnEhEK",
- "CWNvcmVfbGlzdBgKIAMoBRIYChBvdGhlcl9zZXJ2ZXJfYXBpGAsgASgJEhwK",
- "E3Jlc291cmNlX3F1b3RhX3NpemUY6QcgASgFImgKClNlcnZlckFyZ3MSKwoF",
- "c2V0dXAYASABKAsyGi5ncnBjLnRlc3RpbmcuU2VydmVyQ29uZmlnSAASIgoE",
- "bWFyaxgCIAEoCzISLmdycGMudGVzdGluZy5NYXJrSABCCQoHYXJndHlwZSJV",
- "CgxTZXJ2ZXJTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5ncnBjLnRlc3Rpbmcu",
- "U2VydmVyU3RhdHMSDAoEcG9ydBgCIAEoBRINCgVjb3JlcxgDIAEoBSINCgtD",
- "b3JlUmVxdWVzdCIdCgxDb3JlUmVzcG9uc2USDQoFY29yZXMYASABKAUiBgoE",
- "Vm9pZCL9AQoIU2NlbmFyaW8SDAoEbmFtZRgBIAEoCRIxCg1jbGllbnRfY29u",
- "ZmlnGAIgASgLMhouZ3JwYy50ZXN0aW5nLkNsaWVudENvbmZpZxITCgtudW1f",
- "Y2xpZW50cxgDIAEoBRIxCg1zZXJ2ZXJfY29uZmlnGAQgASgLMhouZ3JwYy50",
- "ZXN0aW5nLlNlcnZlckNvbmZpZxITCgtudW1fc2VydmVycxgFIAEoBRIWCg53",
- "YXJtdXBfc2Vjb25kcxgGIAEoBRIZChFiZW5jaG1hcmtfc2Vjb25kcxgHIAEo",
- "BRIgChhzcGF3bl9sb2NhbF93b3JrZXJfY291bnQYCCABKAUiNgoJU2NlbmFy",
- "aW9zEikKCXNjZW5hcmlvcxgBIAMoCzIWLmdycGMudGVzdGluZy5TY2VuYXJp",
- "byL4AgoVU2NlbmFyaW9SZXN1bHRTdW1tYXJ5EgsKA3FwcxgBIAEoARIbChNx",
- "cHNfcGVyX3NlcnZlcl9jb3JlGAIgASgBEhoKEnNlcnZlcl9zeXN0ZW1fdGlt",
- "ZRgDIAEoARIYChBzZXJ2ZXJfdXNlcl90aW1lGAQgASgBEhoKEmNsaWVudF9z",
- "eXN0ZW1fdGltZRgFIAEoARIYChBjbGllbnRfdXNlcl90aW1lGAYgASgBEhIK",
- "CmxhdGVuY3lfNTAYByABKAESEgoKbGF0ZW5jeV85MBgIIAEoARISCgpsYXRl",
- "bmN5Xzk1GAkgASgBEhIKCmxhdGVuY3lfOTkYCiABKAESEwoLbGF0ZW5jeV85",
- "OTkYCyABKAESGAoQc2VydmVyX2NwdV91c2FnZRgMIAEoARImCh5zdWNjZXNz",
- "ZnVsX3JlcXVlc3RzX3Blcl9zZWNvbmQYDSABKAESIgoaZmFpbGVkX3JlcXVl",
- "c3RzX3Blcl9zZWNvbmQYDiABKAEigwMKDlNjZW5hcmlvUmVzdWx0EigKCHNj",
- "ZW5hcmlvGAEgASgLMhYuZ3JwYy50ZXN0aW5nLlNjZW5hcmlvEi4KCWxhdGVu",
- "Y2llcxgCIAEoCzIbLmdycGMudGVzdGluZy5IaXN0b2dyYW1EYXRhEi8KDGNs",
- "aWVudF9zdGF0cxgDIAMoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cxIv",
- "CgxzZXJ2ZXJfc3RhdHMYBCADKAsyGS5ncnBjLnRlc3RpbmcuU2VydmVyU3Rh",
- "dHMSFAoMc2VydmVyX2NvcmVzGAUgAygFEjQKB3N1bW1hcnkYBiABKAsyIy5n",
- "cnBjLnRlc3RpbmcuU2NlbmFyaW9SZXN1bHRTdW1tYXJ5EhYKDmNsaWVudF9z",
- "dWNjZXNzGAcgAygIEhYKDnNlcnZlcl9zdWNjZXNzGAggAygIEjkKD3JlcXVl",
- "c3RfcmVzdWx0cxgJIAMoCzIgLmdycGMudGVzdGluZy5SZXF1ZXN0UmVzdWx0",
- "Q291bnQqQQoKQ2xpZW50VHlwZRIPCgtTWU5DX0NMSUVOVBAAEhAKDEFTWU5D",
- "X0NMSUVOVBABEhAKDE9USEVSX0NMSUVOVBACKlsKClNlcnZlclR5cGUSDwoL",
- "U1lOQ19TRVJWRVIQABIQCgxBU1lOQ19TRVJWRVIQARIYChRBU1lOQ19HRU5F",
- "UklDX1NFUlZFUhACEhAKDE9USEVSX1NFUlZFUhADKiMKB1JwY1R5cGUSCQoF",
- "VU5BUlkQABINCglTVFJFQU1JTkcQAWIGcHJvdG8z"));
+ "X2hvc3Rfb3ZlcnJpZGUYAiABKAkiTQoKQ2hhbm5lbEFyZxIMCgRuYW1lGAEg",
+ "ASgJEhMKCXN0cl92YWx1ZRgCIAEoCUgAEhMKCWludF92YWx1ZRgDIAEoBUgA",
+ "QgcKBXZhbHVlIqAECgxDbGllbnRDb25maWcSFgoOc2VydmVyX3RhcmdldHMY",
+ "ASADKAkSLQoLY2xpZW50X3R5cGUYAiABKA4yGC5ncnBjLnRlc3RpbmcuQ2xp",
+ "ZW50VHlwZRI1Cg9zZWN1cml0eV9wYXJhbXMYAyABKAsyHC5ncnBjLnRlc3Rp",
+ "bmcuU2VjdXJpdHlQYXJhbXMSJAocb3V0c3RhbmRpbmdfcnBjc19wZXJfY2hh",
+ "bm5lbBgEIAEoBRIXCg9jbGllbnRfY2hhbm5lbHMYBSABKAUSHAoUYXN5bmNf",
+ "Y2xpZW50X3RocmVhZHMYByABKAUSJwoIcnBjX3R5cGUYCCABKA4yFS5ncnBj",
+ "LnRlc3RpbmcuUnBjVHlwZRItCgtsb2FkX3BhcmFtcxgKIAEoCzIYLmdycGMu",
+ "dGVzdGluZy5Mb2FkUGFyYW1zEjMKDnBheWxvYWRfY29uZmlnGAsgASgLMhsu",
+ "Z3JwYy50ZXN0aW5nLlBheWxvYWRDb25maWcSNwoQaGlzdG9ncmFtX3BhcmFt",
+ "cxgMIAEoCzIdLmdycGMudGVzdGluZy5IaXN0b2dyYW1QYXJhbXMSEQoJY29y",
+ "ZV9saXN0GA0gAygFEhIKCmNvcmVfbGltaXQYDiABKAUSGAoQb3RoZXJfY2xp",
+ "ZW50X2FwaRgPIAEoCRIuCgxjaGFubmVsX2FyZ3MYECADKAsyGC5ncnBjLnRl",
+ "c3RpbmcuQ2hhbm5lbEFyZyI4CgxDbGllbnRTdGF0dXMSKAoFc3RhdHMYASAB",
+ "KAsyGS5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHMiFQoETWFyaxINCgVyZXNl",
+ "dBgBIAEoCCJoCgpDbGllbnRBcmdzEisKBXNldHVwGAEgASgLMhouZ3JwYy50",
+ "ZXN0aW5nLkNsaWVudENvbmZpZ0gAEiIKBG1hcmsYAiABKAsyEi5ncnBjLnRl",
+ "c3RpbmcuTWFya0gAQgkKB2FyZ3R5cGUitAIKDFNlcnZlckNvbmZpZxItCgtz",
+ "ZXJ2ZXJfdHlwZRgBIAEoDjIYLmdycGMudGVzdGluZy5TZXJ2ZXJUeXBlEjUK",
+ "D3NlY3VyaXR5X3BhcmFtcxgCIAEoCzIcLmdycGMudGVzdGluZy5TZWN1cml0",
+ "eVBhcmFtcxIMCgRwb3J0GAQgASgFEhwKFGFzeW5jX3NlcnZlcl90aHJlYWRz",
+ "GAcgASgFEhIKCmNvcmVfbGltaXQYCCABKAUSMwoOcGF5bG9hZF9jb25maWcY",
+ "CSABKAsyGy5ncnBjLnRlc3RpbmcuUGF5bG9hZENvbmZpZxIRCgljb3JlX2xp",
+ "c3QYCiADKAUSGAoQb3RoZXJfc2VydmVyX2FwaRgLIAEoCRIcChNyZXNvdXJj",
+ "ZV9xdW90YV9zaXplGOkHIAEoBSJoCgpTZXJ2ZXJBcmdzEisKBXNldHVwGAEg",
+ "ASgLMhouZ3JwYy50ZXN0aW5nLlNlcnZlckNvbmZpZ0gAEiIKBG1hcmsYAiAB",
+ "KAsyEi5ncnBjLnRlc3RpbmcuTWFya0gAQgkKB2FyZ3R5cGUiVQoMU2VydmVy",
+ "U3RhdHVzEigKBXN0YXRzGAEgASgLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0",
+ "YXRzEgwKBHBvcnQYAiABKAUSDQoFY29yZXMYAyABKAUiDQoLQ29yZVJlcXVl",
+ "c3QiHQoMQ29yZVJlc3BvbnNlEg0KBWNvcmVzGAEgASgFIgYKBFZvaWQi/QEK",
+ "CFNjZW5hcmlvEgwKBG5hbWUYASABKAkSMQoNY2xpZW50X2NvbmZpZxgCIAEo",
+ "CzIaLmdycGMudGVzdGluZy5DbGllbnRDb25maWcSEwoLbnVtX2NsaWVudHMY",
+ "AyABKAUSMQoNc2VydmVyX2NvbmZpZxgEIAEoCzIaLmdycGMudGVzdGluZy5T",
+ "ZXJ2ZXJDb25maWcSEwoLbnVtX3NlcnZlcnMYBSABKAUSFgoOd2FybXVwX3Nl",
+ "Y29uZHMYBiABKAUSGQoRYmVuY2htYXJrX3NlY29uZHMYByABKAUSIAoYc3Bh",
+ "d25fbG9jYWxfd29ya2VyX2NvdW50GAggASgFIjYKCVNjZW5hcmlvcxIpCglz",
+ "Y2VuYXJpb3MYASADKAsyFi5ncnBjLnRlc3RpbmcuU2NlbmFyaW8i+AIKFVNj",
+ "ZW5hcmlvUmVzdWx0U3VtbWFyeRILCgNxcHMYASABKAESGwoTcXBzX3Blcl9z",
+ "ZXJ2ZXJfY29yZRgCIAEoARIaChJzZXJ2ZXJfc3lzdGVtX3RpbWUYAyABKAES",
+ "GAoQc2VydmVyX3VzZXJfdGltZRgEIAEoARIaChJjbGllbnRfc3lzdGVtX3Rp",
+ "bWUYBSABKAESGAoQY2xpZW50X3VzZXJfdGltZRgGIAEoARISCgpsYXRlbmN5",
+ "XzUwGAcgASgBEhIKCmxhdGVuY3lfOTAYCCABKAESEgoKbGF0ZW5jeV85NRgJ",
+ "IAEoARISCgpsYXRlbmN5Xzk5GAogASgBEhMKC2xhdGVuY3lfOTk5GAsgASgB",
+ "EhgKEHNlcnZlcl9jcHVfdXNhZ2UYDCABKAESJgoec3VjY2Vzc2Z1bF9yZXF1",
+ "ZXN0c19wZXJfc2Vjb25kGA0gASgBEiIKGmZhaWxlZF9yZXF1ZXN0c19wZXJf",
+ "c2Vjb25kGA4gASgBIoMDCg5TY2VuYXJpb1Jlc3VsdBIoCghzY2VuYXJpbxgB",
+ "IAEoCzIWLmdycGMudGVzdGluZy5TY2VuYXJpbxIuCglsYXRlbmNpZXMYAiAB",
+ "KAsyGy5ncnBjLnRlc3RpbmcuSGlzdG9ncmFtRGF0YRIvCgxjbGllbnRfc3Rh",
+ "dHMYAyADKAsyGS5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHMSLwoMc2VydmVy",
+ "X3N0YXRzGAQgAygLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXRzEhQKDHNl",
+ "cnZlcl9jb3JlcxgFIAMoBRI0CgdzdW1tYXJ5GAYgASgLMiMuZ3JwYy50ZXN0",
+ "aW5nLlNjZW5hcmlvUmVzdWx0U3VtbWFyeRIWCg5jbGllbnRfc3VjY2VzcxgH",
+ "IAMoCBIWCg5zZXJ2ZXJfc3VjY2VzcxgIIAMoCBI5Cg9yZXF1ZXN0X3Jlc3Vs",
+ "dHMYCSADKAsyIC5ncnBjLnRlc3RpbmcuUmVxdWVzdFJlc3VsdENvdW50KkEK",
+ "CkNsaWVudFR5cGUSDwoLU1lOQ19DTElFTlQQABIQCgxBU1lOQ19DTElFTlQQ",
+ "ARIQCgxPVEhFUl9DTElFTlQQAipbCgpTZXJ2ZXJUeXBlEg8KC1NZTkNfU0VS",
+ "VkVSEAASEAoMQVNZTkNfU0VSVkVSEAESGAoUQVNZTkNfR0VORVJJQ19TRVJW",
+ "RVIQAhIQCgxPVEhFUl9TRVJWRVIQAyojCgdScGNUeXBlEgkKBVVOQVJZEAAS",
+ "DQoJU1RSRUFNSU5HEAFiBnByb3RvMw=="));
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[] {
@@ -94,7 +97,8 @@ namespace Grpc.Testing {
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClosedLoopParams), global::Grpc.Testing.ClosedLoopParams.Parser, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson" }, new[]{ "Load" }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride" }, null, null, null),
- new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi" }, null, null, null),
+ new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ChannelArg), global::Grpc.Testing.ChannelArg.Parser, new[]{ "Name", "StrValue", "IntValue" }, new[]{ "Value" }, null, null),
+ new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi", "ChannelArgs" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
@@ -116,13 +120,13 @@ namespace Grpc.Testing {
#region Enums
public enum ClientType {
/// <summary>
- /// Many languages support a basic distinction between using
- /// sync or async client, and this allows the specification
+ /// Many languages support a basic distinction between using
+ /// sync or async client, and this allows the specification
/// </summary>
[pbr::OriginalName("SYNC_CLIENT")] SyncClient = 0,
[pbr::OriginalName("ASYNC_CLIENT")] AsyncClient = 1,
/// <summary>
- /// used for some language-specific variants
+ /// used for some language-specific variants
/// </summary>
[pbr::OriginalName("OTHER_CLIENT")] OtherClient = 2,
}
@@ -132,7 +136,7 @@ namespace Grpc.Testing {
[pbr::OriginalName("ASYNC_SERVER")] AsyncServer = 1,
[pbr::OriginalName("ASYNC_GENERIC_SERVER")] AsyncGenericServer = 2,
/// <summary>
- /// used for some language-specific variants
+ /// used for some language-specific variants
/// </summary>
[pbr::OriginalName("OTHER_SERVER")] OtherServer = 3,
}
@@ -146,8 +150,8 @@ namespace Grpc.Testing {
#region Messages
/// <summary>
- /// Parameters of poisson process distribution, which is a good representation
- /// of activity coming in from independent identical stationary sources.
+ /// Parameters of poisson process distribution, which is a good representation
+ /// of activity coming in from independent identical stationary sources.
/// </summary>
public sealed partial class PoissonParams : pb::IMessage<PoissonParams> {
private static readonly pb::MessageParser<PoissonParams> _parser = new pb::MessageParser<PoissonParams>(() => new PoissonParams());
@@ -185,7 +189,7 @@ namespace Grpc.Testing {
public const int OfferedLoadFieldNumber = 1;
private double offeredLoad_;
/// <summary>
- /// The rate of arrivals (a.k.a. lambda parameter of the exp distribution).
+ /// The rate of arrivals (a.k.a. lambda parameter of the exp distribution).
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double OfferedLoad {
@@ -270,8 +274,8 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Once an RPC finishes, immediately start a new one.
- /// No configuration parameters needed.
+ /// Once an RPC finishes, immediately start a new one.
+ /// No configuration parameters needed.
/// </summary>
public sealed partial class ClosedLoopParams : pb::IMessage<ClosedLoopParams> {
private static readonly pb::MessageParser<ClosedLoopParams> _parser = new pb::MessageParser<ClosedLoopParams>(() => new ClosedLoopParams());
@@ -549,7 +553,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// presence of SecurityParams implies use of TLS
+ /// presence of SecurityParams implies use of TLS
/// </summary>
public sealed partial class SecurityParams : pb::IMessage<SecurityParams> {
private static readonly pb::MessageParser<SecurityParams> _parser = new pb::MessageParser<SecurityParams>(() => new SecurityParams());
@@ -696,6 +700,210 @@ namespace Grpc.Testing {
}
+ public sealed partial class ChannelArg : pb::IMessage<ChannelArg> {
+ private static readonly pb::MessageParser<ChannelArg> _parser = new pb::MessageParser<ChannelArg>(() => new ChannelArg());
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pb::MessageParser<ChannelArg> Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[4]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public ChannelArg() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public ChannelArg(ChannelArg other) : this() {
+ name_ = other.name_;
+ switch (other.ValueCase) {
+ case ValueOneofCase.StrValue:
+ StrValue = other.StrValue;
+ break;
+ case ValueOneofCase.IntValue:
+ IntValue = other.IntValue;
+ break;
+ }
+
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public ChannelArg Clone() {
+ return new ChannelArg(this);
+ }
+
+ /// <summary>Field number for the "name" field.</summary>
+ 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");
+ }
+ }
+
+ /// <summary>Field number for the "str_value" field.</summary>
+ public const int StrValueFieldNumber = 2;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public string StrValue {
+ get { return valueCase_ == ValueOneofCase.StrValue ? (string) value_ : ""; }
+ set {
+ value_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ valueCase_ = ValueOneofCase.StrValue;
+ }
+ }
+
+ /// <summary>Field number for the "int_value" field.</summary>
+ public const int IntValueFieldNumber = 3;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int IntValue {
+ get { return valueCase_ == ValueOneofCase.IntValue ? (int) value_ : 0; }
+ set {
+ value_ = value;
+ valueCase_ = ValueOneofCase.IntValue;
+ }
+ }
+
+ private object value_;
+ /// <summary>Enum of possible cases for the "value" oneof.</summary>
+ public enum ValueOneofCase {
+ None = 0,
+ StrValue = 2,
+ IntValue = 3,
+ }
+ private ValueOneofCase valueCase_ = ValueOneofCase.None;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public ValueOneofCase ValueCase {
+ get { return valueCase_; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void ClearValue() {
+ valueCase_ = ValueOneofCase.None;
+ value_ = null;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override bool Equals(object other) {
+ return Equals(other as ChannelArg);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public bool Equals(ChannelArg other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (Name != other.Name) return false;
+ if (StrValue != other.StrValue) return false;
+ if (IntValue != other.IntValue) return false;
+ if (ValueCase != other.ValueCase) return false;
+ return true;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override int GetHashCode() {
+ int hash = 1;
+ if (Name.Length != 0) hash ^= Name.GetHashCode();
+ if (valueCase_ == ValueOneofCase.StrValue) hash ^= StrValue.GetHashCode();
+ if (valueCase_ == ValueOneofCase.IntValue) hash ^= IntValue.GetHashCode();
+ hash ^= (int) valueCase_;
+ 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);
+ }
+ if (valueCase_ == ValueOneofCase.StrValue) {
+ output.WriteRawTag(18);
+ output.WriteString(StrValue);
+ }
+ if (valueCase_ == ValueOneofCase.IntValue) {
+ output.WriteRawTag(24);
+ output.WriteInt32(IntValue);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int CalculateSize() {
+ int size = 0;
+ if (Name.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+ }
+ if (valueCase_ == ValueOneofCase.StrValue) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(StrValue);
+ }
+ if (valueCase_ == ValueOneofCase.IntValue) {
+ size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntValue);
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(ChannelArg other) {
+ if (other == null) {
+ return;
+ }
+ if (other.Name.Length != 0) {
+ Name = other.Name;
+ }
+ switch (other.ValueCase) {
+ case ValueOneofCase.StrValue:
+ StrValue = other.StrValue;
+ break;
+ case ValueOneofCase.IntValue:
+ IntValue = other.IntValue;
+ break;
+ }
+
+ }
+
+ [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;
+ }
+ case 18: {
+ StrValue = input.ReadString();
+ break;
+ }
+ case 24: {
+ IntValue = input.ReadInt32();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
public sealed partial class ClientConfig : pb::IMessage<ClientConfig> {
private static readonly pb::MessageParser<ClientConfig> _parser = new pb::MessageParser<ClientConfig>(() => new ClientConfig());
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -703,7 +911,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[4]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[5]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -733,6 +941,7 @@ namespace Grpc.Testing {
coreList_ = other.coreList_.Clone();
coreLimit_ = other.coreLimit_;
otherClientApi_ = other.otherClientApi_;
+ channelArgs_ = other.channelArgs_.Clone();
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -746,7 +955,7 @@ namespace Grpc.Testing {
= pb::FieldCodec.ForString(10);
private readonly pbc::RepeatedField<string> serverTargets_ = new pbc::RepeatedField<string>();
/// <summary>
- /// List of targets to connect to. At least one target needs to be specified.
+ /// List of targets to connect to. At least one target needs to be specified.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<string> ServerTargets {
@@ -779,8 +988,8 @@ namespace Grpc.Testing {
public const int OutstandingRpcsPerChannelFieldNumber = 4;
private int outstandingRpcsPerChannel_;
/// <summary>
- /// How many concurrent RPCs to start for each channel.
- /// For synchronous client, use a separate thread for each outstanding RPC.
+ /// How many concurrent RPCs to start for each channel.
+ /// For synchronous client, use a separate thread for each outstanding RPC.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int OutstandingRpcsPerChannel {
@@ -794,8 +1003,8 @@ namespace Grpc.Testing {
public const int ClientChannelsFieldNumber = 5;
private int clientChannels_;
/// <summary>
- /// Number of independent client channels to create.
- /// i-th channel will connect to server_target[i % server_targets.size()]
+ /// Number of independent client channels to create.
+ /// i-th channel will connect to server_target[i % server_targets.size()]
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int ClientChannels {
@@ -809,7 +1018,7 @@ namespace Grpc.Testing {
public const int AsyncClientThreadsFieldNumber = 7;
private int asyncClientThreads_;
/// <summary>
- /// Only for async client. Number of threads to use to start/manage RPCs.
+ /// Only for async client. Number of threads to use to start/manage RPCs.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int AsyncClientThreads {
@@ -834,7 +1043,7 @@ namespace Grpc.Testing {
public const int LoadParamsFieldNumber = 10;
private global::Grpc.Testing.LoadParams loadParams_;
/// <summary>
- /// The requested load for the entire client (aggregated over all the threads).
+ /// The requested load for the entire client (aggregated over all the threads).
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.LoadParams LoadParams {
@@ -872,7 +1081,7 @@ namespace Grpc.Testing {
= pb::FieldCodec.ForInt32(106);
private readonly pbc::RepeatedField<int> coreList_ = new pbc::RepeatedField<int>();
/// <summary>
- /// Specify the cores we should run the client on, if desired
+ /// Specify the cores we should run the client on, if desired
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<int> CoreList {
@@ -894,7 +1103,7 @@ namespace Grpc.Testing {
public const int OtherClientApiFieldNumber = 15;
private string otherClientApi_ = "";
/// <summary>
- /// If we use an OTHER_CLIENT client_type, this string gives more detail
+ /// If we use an OTHER_CLIENT client_type, this string gives more detail
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string OtherClientApi {
@@ -904,6 +1113,16 @@ namespace Grpc.Testing {
}
}
+ /// <summary>Field number for the "channel_args" field.</summary>
+ public const int ChannelArgsFieldNumber = 16;
+ private static readonly pb::FieldCodec<global::Grpc.Testing.ChannelArg> _repeated_channelArgs_codec
+ = pb::FieldCodec.ForMessage(130, global::Grpc.Testing.ChannelArg.Parser);
+ private readonly pbc::RepeatedField<global::Grpc.Testing.ChannelArg> channelArgs_ = new pbc::RepeatedField<global::Grpc.Testing.ChannelArg>();
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public pbc::RepeatedField<global::Grpc.Testing.ChannelArg> ChannelArgs {
+ get { return channelArgs_; }
+ }
+
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as ClientConfig);
@@ -930,6 +1149,7 @@ namespace Grpc.Testing {
if(!coreList_.Equals(other.coreList_)) return false;
if (CoreLimit != other.CoreLimit) return false;
if (OtherClientApi != other.OtherClientApi) return false;
+ if(!channelArgs_.Equals(other.channelArgs_)) return false;
return true;
}
@@ -949,6 +1169,7 @@ namespace Grpc.Testing {
hash ^= coreList_.GetHashCode();
if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
if (OtherClientApi.Length != 0) hash ^= OtherClientApi.GetHashCode();
+ hash ^= channelArgs_.GetHashCode();
return hash;
}
@@ -1005,6 +1226,7 @@ namespace Grpc.Testing {
output.WriteRawTag(122);
output.WriteString(OtherClientApi);
}
+ channelArgs_.WriteTo(output, _repeated_channelArgs_codec);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1045,6 +1267,7 @@ namespace Grpc.Testing {
if (OtherClientApi.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherClientApi);
}
+ size += channelArgs_.CalculateSize(_repeated_channelArgs_codec);
return size;
}
@@ -1100,6 +1323,7 @@ namespace Grpc.Testing {
if (other.OtherClientApi.Length != 0) {
OtherClientApi = other.OtherClientApi;
}
+ channelArgs_.Add(other.channelArgs_);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1175,6 +1399,10 @@ namespace Grpc.Testing {
OtherClientApi = input.ReadString();
break;
}
+ case 130: {
+ channelArgs_.AddEntriesFrom(input, _repeated_channelArgs_codec);
+ break;
+ }
}
}
}
@@ -1188,7 +1416,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[5]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[6]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1305,7 +1533,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Request current stats
+ /// Request current stats
/// </summary>
public sealed partial class Mark : pb::IMessage<Mark> {
private static readonly pb::MessageParser<Mark> _parser = new pb::MessageParser<Mark>(() => new Mark());
@@ -1314,7 +1542,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[6]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[7]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1343,7 +1571,7 @@ namespace Grpc.Testing {
public const int ResetFieldNumber = 1;
private bool reset_;
/// <summary>
- /// if true, the stats will be reset after taking their snapshot.
+ /// if true, the stats will be reset after taking their snapshot.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Reset {
@@ -1434,7 +1662,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[7]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[8]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1620,7 +1848,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[8]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[9]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1679,7 +1907,7 @@ namespace Grpc.Testing {
public const int PortFieldNumber = 4;
private int port_;
/// <summary>
- /// Port on which to listen. Zero means pick unused port.
+ /// Port on which to listen. Zero means pick unused port.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Port {
@@ -1693,7 +1921,7 @@ namespace Grpc.Testing {
public const int AsyncServerThreadsFieldNumber = 7;
private int asyncServerThreads_;
/// <summary>
- /// Only for async server. Number of threads used to serve the requests.
+ /// Only for async server. Number of threads used to serve the requests.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int AsyncServerThreads {
@@ -1707,7 +1935,7 @@ namespace Grpc.Testing {
public const int CoreLimitFieldNumber = 8;
private int coreLimit_;
/// <summary>
- /// Specify the number of cores to limit server to, if desired
+ /// Specify the number of cores to limit server to, if desired
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CoreLimit {
@@ -1721,7 +1949,10 @@ namespace Grpc.Testing {
public const int PayloadConfigFieldNumber = 9;
private global::Grpc.Testing.PayloadConfig payloadConfig_;
/// <summary>
- /// payload config, used in generic server
+ /// payload config, used in generic server.
+ /// Note this must NOT be used in proto (non-generic) servers. For proto servers,
+ /// 'response sizes' must be configured from the 'response_size' field of the
+ /// 'SimpleRequest' objects in RPC requests.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.PayloadConfig PayloadConfig {
@@ -1737,7 +1968,7 @@ namespace Grpc.Testing {
= pb::FieldCodec.ForInt32(82);
private readonly pbc::RepeatedField<int> coreList_ = new pbc::RepeatedField<int>();
/// <summary>
- /// Specify the cores we should run the server on, if desired
+ /// Specify the cores we should run the server on, if desired
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<int> CoreList {
@@ -1748,7 +1979,7 @@ namespace Grpc.Testing {
public const int OtherServerApiFieldNumber = 11;
private string otherServerApi_ = "";
/// <summary>
- /// If we use an OTHER_SERVER client_type, this string gives more detail
+ /// If we use an OTHER_SERVER client_type, this string gives more detail
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string OtherServerApi {
@@ -1762,7 +1993,7 @@ namespace Grpc.Testing {
public const int ResourceQuotaSizeFieldNumber = 1001;
private int resourceQuotaSize_;
/// <summary>
- /// Buffer pool size (no buffer pool specified if unset)
+ /// Buffer pool size (no buffer pool specified if unset)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int ResourceQuotaSize {
@@ -1987,7 +2218,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[9]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[10]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2173,7 +2404,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[10]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[11]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2215,7 +2446,7 @@ namespace Grpc.Testing {
public const int PortFieldNumber = 2;
private int port_;
/// <summary>
- /// the port bound by the server
+ /// the port bound by the server
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Port {
@@ -2229,7 +2460,7 @@ namespace Grpc.Testing {
public const int CoresFieldNumber = 3;
private int cores_;
/// <summary>
- /// Number of cores available to the server
+ /// Number of cores available to the server
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Cores {
@@ -2358,7 +2589,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[11]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[12]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2447,7 +2678,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[12]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[13]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2476,7 +2707,7 @@ namespace Grpc.Testing {
public const int CoresFieldNumber = 1;
private int cores_;
/// <summary>
- /// Number of cores available on the server
+ /// Number of cores available on the server
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Cores {
@@ -2567,7 +2798,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[13]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[14]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2650,7 +2881,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// A single performance scenario: input to qps_json_driver
+ /// A single performance scenario: input to qps_json_driver
/// </summary>
public sealed partial class Scenario : pb::IMessage<Scenario> {
private static readonly pb::MessageParser<Scenario> _parser = new pb::MessageParser<Scenario>(() => new Scenario());
@@ -2659,7 +2890,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[14]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[15]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2695,7 +2926,7 @@ namespace Grpc.Testing {
public const int NameFieldNumber = 1;
private string name_ = "";
/// <summary>
- /// Human readable name for this scenario
+ /// Human readable name for this scenario
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Name {
@@ -2709,7 +2940,7 @@ namespace Grpc.Testing {
public const int ClientConfigFieldNumber = 2;
private global::Grpc.Testing.ClientConfig clientConfig_;
/// <summary>
- /// Client configuration
+ /// Client configuration
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.ClientConfig ClientConfig {
@@ -2723,7 +2954,7 @@ namespace Grpc.Testing {
public const int NumClientsFieldNumber = 3;
private int numClients_;
/// <summary>
- /// Number of clients to start for the test
+ /// Number of clients to start for the test
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int NumClients {
@@ -2737,7 +2968,7 @@ namespace Grpc.Testing {
public const int ServerConfigFieldNumber = 4;
private global::Grpc.Testing.ServerConfig serverConfig_;
/// <summary>
- /// Server configuration
+ /// Server configuration
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.ServerConfig ServerConfig {
@@ -2751,7 +2982,7 @@ namespace Grpc.Testing {
public const int NumServersFieldNumber = 5;
private int numServers_;
/// <summary>
- /// Number of servers to start for the test
+ /// Number of servers to start for the test
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int NumServers {
@@ -2765,7 +2996,7 @@ namespace Grpc.Testing {
public const int WarmupSecondsFieldNumber = 6;
private int warmupSeconds_;
/// <summary>
- /// Warmup period, in seconds
+ /// Warmup period, in seconds
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int WarmupSeconds {
@@ -2779,7 +3010,7 @@ namespace Grpc.Testing {
public const int BenchmarkSecondsFieldNumber = 7;
private int benchmarkSeconds_;
/// <summary>
- /// Benchmark time, in seconds
+ /// Benchmark time, in seconds
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int BenchmarkSeconds {
@@ -2793,7 +3024,7 @@ namespace Grpc.Testing {
public const int SpawnLocalWorkerCountFieldNumber = 8;
private int spawnLocalWorkerCount_;
/// <summary>
- /// Number of workers to spawn locally (usually zero)
+ /// Number of workers to spawn locally (usually zero)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int SpawnLocalWorkerCount {
@@ -3002,7 +3233,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// A set of scenarios to be run with qps_json_driver
+ /// A set of scenarios to be run with qps_json_driver
/// </summary>
public sealed partial class Scenarios : pb::IMessage<Scenarios> {
private static readonly pb::MessageParser<Scenarios> _parser = new pb::MessageParser<Scenarios>(() => new Scenarios());
@@ -3011,7 +3242,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[15]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[16]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3114,8 +3345,8 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Basic summary that can be computed from ClientStats and ServerStats
- /// once the scenario has finished.
+ /// Basic summary that can be computed from ClientStats and ServerStats
+ /// once the scenario has finished.
/// </summary>
public sealed partial class ScenarioResultSummary : pb::IMessage<ScenarioResultSummary> {
private static readonly pb::MessageParser<ScenarioResultSummary> _parser = new pb::MessageParser<ScenarioResultSummary>(() => new ScenarioResultSummary());
@@ -3124,7 +3355,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[16]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[17]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3166,7 +3397,7 @@ namespace Grpc.Testing {
public const int QpsFieldNumber = 1;
private double qps_;
/// <summary>
- /// Total number of operations per second over all clients.
+ /// Total number of operations per second over all clients.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double Qps {
@@ -3180,7 +3411,7 @@ namespace Grpc.Testing {
public const int QpsPerServerCoreFieldNumber = 2;
private double qpsPerServerCore_;
/// <summary>
- /// QPS per one server core.
+ /// QPS per one server core.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double QpsPerServerCore {
@@ -3194,7 +3425,7 @@ namespace Grpc.Testing {
public const int ServerSystemTimeFieldNumber = 3;
private double serverSystemTime_;
/// <summary>
- /// server load based on system_time (0.85 => 85%)
+ /// server load based on system_time (0.85 => 85%)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double ServerSystemTime {
@@ -3208,7 +3439,7 @@ namespace Grpc.Testing {
public const int ServerUserTimeFieldNumber = 4;
private double serverUserTime_;
/// <summary>
- /// server load based on user_time (0.85 => 85%)
+ /// server load based on user_time (0.85 => 85%)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double ServerUserTime {
@@ -3222,7 +3453,7 @@ namespace Grpc.Testing {
public const int ClientSystemTimeFieldNumber = 5;
private double clientSystemTime_;
/// <summary>
- /// client load based on system_time (0.85 => 85%)
+ /// client load based on system_time (0.85 => 85%)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double ClientSystemTime {
@@ -3236,7 +3467,7 @@ namespace Grpc.Testing {
public const int ClientUserTimeFieldNumber = 6;
private double clientUserTime_;
/// <summary>
- /// client load based on user_time (0.85 => 85%)
+ /// client load based on user_time (0.85 => 85%)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double ClientUserTime {
@@ -3250,7 +3481,7 @@ namespace Grpc.Testing {
public const int Latency50FieldNumber = 7;
private double latency50_;
/// <summary>
- /// X% latency percentiles (in nanoseconds)
+ /// X% latency percentiles (in nanoseconds)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double Latency50 {
@@ -3308,7 +3539,7 @@ namespace Grpc.Testing {
public const int ServerCpuUsageFieldNumber = 12;
private double serverCpuUsage_;
/// <summary>
- /// server cpu usage percentage
+ /// server cpu usage percentage
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double ServerCpuUsage {
@@ -3322,7 +3553,7 @@ namespace Grpc.Testing {
public const int SuccessfulRequestsPerSecondFieldNumber = 13;
private double successfulRequestsPerSecond_;
/// <summary>
- /// Number of requests that succeeded/failed
+ /// Number of requests that succeeded/failed
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double SuccessfulRequestsPerSecond {
@@ -3626,7 +3857,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Results of a single benchmark scenario.
+ /// Results of a single benchmark scenario.
/// </summary>
public sealed partial class ScenarioResult : pb::IMessage<ScenarioResult> {
private static readonly pb::MessageParser<ScenarioResult> _parser = new pb::MessageParser<ScenarioResult>(() => new ScenarioResult());
@@ -3635,7 +3866,7 @@ namespace Grpc.Testing {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor {
- get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[17]; }
+ get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[18]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3672,7 +3903,7 @@ namespace Grpc.Testing {
public const int ScenarioFieldNumber = 1;
private global::Grpc.Testing.Scenario scenario_;
/// <summary>
- /// Inputs used to run the scenario.
+ /// Inputs used to run the scenario.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.Scenario Scenario {
@@ -3686,7 +3917,7 @@ namespace Grpc.Testing {
public const int LatenciesFieldNumber = 2;
private global::Grpc.Testing.HistogramData latencies_;
/// <summary>
- /// Histograms from all clients merged into one histogram.
+ /// Histograms from all clients merged into one histogram.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.HistogramData Latencies {
@@ -3702,7 +3933,7 @@ namespace Grpc.Testing {
= pb::FieldCodec.ForMessage(26, global::Grpc.Testing.ClientStats.Parser);
private readonly pbc::RepeatedField<global::Grpc.Testing.ClientStats> clientStats_ = new pbc::RepeatedField<global::Grpc.Testing.ClientStats>();
/// <summary>
- /// Client stats for each client
+ /// Client stats for each client
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<global::Grpc.Testing.ClientStats> ClientStats {
@@ -3715,7 +3946,7 @@ namespace Grpc.Testing {
= pb::FieldCodec.ForMessage(34, global::Grpc.Testing.ServerStats.Parser);
private readonly pbc::RepeatedField<global::Grpc.Testing.ServerStats> serverStats_ = new pbc::RepeatedField<global::Grpc.Testing.ServerStats>();
/// <summary>
- /// Server stats for each server
+ /// Server stats for each server
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<global::Grpc.Testing.ServerStats> ServerStats {
@@ -3728,7 +3959,7 @@ namespace Grpc.Testing {
= pb::FieldCodec.ForInt32(42);
private readonly pbc::RepeatedField<int> serverCores_ = new pbc::RepeatedField<int>();
/// <summary>
- /// Number of cores available to each server
+ /// Number of cores available to each server
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<int> ServerCores {
@@ -3739,7 +3970,7 @@ namespace Grpc.Testing {
public const int SummaryFieldNumber = 6;
private global::Grpc.Testing.ScenarioResultSummary summary_;
/// <summary>
- /// An after-the-fact computed summary
+ /// An after-the-fact computed summary
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.ScenarioResultSummary Summary {
@@ -3755,7 +3986,7 @@ namespace Grpc.Testing {
= pb::FieldCodec.ForBool(58);
private readonly pbc::RepeatedField<bool> clientSuccess_ = new pbc::RepeatedField<bool>();
/// <summary>
- /// Information on success or failure of each worker
+ /// Information on success or failure of each worker
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<bool> ClientSuccess {
@@ -3778,7 +4009,7 @@ namespace Grpc.Testing {
= pb::FieldCodec.ForMessage(74, global::Grpc.Testing.RequestResultCount.Parser);
private readonly pbc::RepeatedField<global::Grpc.Testing.RequestResultCount> requestResults_ = new pbc::RepeatedField<global::Grpc.Testing.RequestResultCount>();
/// <summary>
- /// Number of failed requests (one row per status code seen)
+ /// Number of failed requests (one row per status code seen)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<global::Grpc.Testing.RequestResultCount> RequestResults {
diff --git a/src/csharp/Grpc.IntegrationTesting/Empty.cs b/src/csharp/Grpc.IntegrationTesting/Empty.cs
index 3017e664b9..24ffd61741 100644
--- a/src/csharp/Grpc.IntegrationTesting/Empty.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Empty.cs
@@ -35,13 +35,13 @@ namespace Grpc.Testing {
}
#region Messages
/// <summary>
- /// An empty message that you can re-use to avoid defining duplicated empty
- /// messages in your project. A typical example is to use it as argument or the
- /// return value of a service API. For instance:
+ /// An empty message that you can re-use to avoid defining duplicated empty
+ /// messages in your project. A typical example is to use it as argument or the
+ /// return value of a service API. For instance:
///
- /// service Foo {
- /// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { };
- /// };
+ /// service Foo {
+ /// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { };
+ /// };
/// </summary>
public sealed partial class Empty : pb::IMessage<Empty> {
private static readonly pb::MessageParser<Empty> _parser = new pb::MessageParser<Empty>(() => new Empty());
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index f7abcf8046..38b9a5d3c5 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -33,53 +33,47 @@
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.WebRequest" />
- <Reference Include="BouncyCastle.Crypto">
- <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
- </Reference>
- <Reference Include="Newtonsoft.Json">
- <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
- </Reference>
- <Reference Include="nunit.framework">
- <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
- </Reference>
- <Reference Include="nunitlite">
- <HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
- </Reference>
- <Reference Include="CommandLineParser.Unofficial">
- <HintPath>..\packages\CommandLineParser.Unofficial.2.0.275\lib\net45\CommandLineParser.Unofficial.dll</HintPath>
+ <Reference Include="Zlib.Portable">
+ <HintPath>..\packages\Zlib.Portable.Signed.1.11.0\lib\portable-net4+sl5+wp8+win8+wpa81+MonoTouch+MonoAndroid\Zlib.Portable.dll</HintPath>
</Reference>
- <Reference Include="log4net">
- <HintPath>..\packages\log4net.2.0.3\lib\net40-full\log4net.dll</HintPath>
+ <Reference Include="System.Interactive.Async">
+ <HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Core">
- <HintPath>..\packages\Google.Apis.Core.1.16.0\lib\net45\Google.Apis.Core.dll</HintPath>
- </Reference>
- <Reference Include="Zlib.Portable">
- <HintPath>..\packages\Zlib.Portable.Signed.1.11.0\lib\portable-net4+sl5+wp8+win8+wpa81+MonoTouch+MonoAndroid\Zlib.Portable.dll</HintPath>
+ <HintPath>..\packages\Google.Apis.Core.1.21.0\lib\net45\Google.Apis.Core.dll</HintPath>
</Reference>
<Reference Include="Google.Apis">
- <HintPath>..\packages\Google.Apis.1.16.0\lib\net45\Google.Apis.dll</HintPath>
+ <HintPath>..\packages\Google.Apis.1.21.0\lib\net45\Google.Apis.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.PlatformServices">
- <HintPath>..\packages\Google.Apis.1.16.0\lib\net45\Google.Apis.PlatformServices.dll</HintPath>
+ <HintPath>..\packages\Google.Apis.1.21.0\lib\net45\Google.Apis.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Auth">
- <HintPath>..\packages\Google.Apis.Auth.1.16.0\lib\net45\Google.Apis.Auth.dll</HintPath>
+ <HintPath>..\packages\Google.Apis.Auth.1.21.0\lib\net45\Google.Apis.Auth.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Auth.PlatformServices">
- <HintPath>..\packages\Google.Apis.Auth.1.16.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
+ <HintPath>..\packages\Google.Apis.Auth.1.21.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="Google.Protobuf">
- <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
+ <HintPath>..\packages\Google.Protobuf.3.2.0\lib\net45\Google.Protobuf.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.3.6.0\lib\net45\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="nunitlite">
+ <HintPath>..\packages\NUnitLite.3.6.0\lib\net45\nunitlite.dll</HintPath>
+ </Reference>
+ <Reference Include="Newtonsoft.Json">
+ <HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Castle.Core">
- <HintPath>..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll</HintPath>
+ <HintPath>..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath>
</Reference>
<Reference Include="Moq">
- <HintPath>..\packages\Moq.4.6.38-alpha\lib\net45\Moq.dll</HintPath>
+ <HintPath>..\packages\Moq.4.7.0\lib\net45\Moq.dll</HintPath>
</Reference>
- <Reference Include="System.Interactive.Async">
- <HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
+ <Reference Include="CommandLine">
+ <HintPath>..\packages\CommandLineParser.2.1.1-beta\lib\net45\CommandLine.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index 5ba83b143e..32a52eee6b 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -45,6 +45,7 @@ using Google.Apis.Auth.OAuth2;
using Google.Protobuf;
using Grpc.Auth;
using Grpc.Core;
+using Grpc.Core.Logging;
using Grpc.Core.Utils;
using Grpc.Testing;
using Newtonsoft.Json.Linq;
@@ -56,7 +57,7 @@ namespace Grpc.IntegrationTesting
{
private class ClientOptions
{
- [Option("server_host", Default = "127.0.0.1")]
+ [Option("server_host", Default = "localhost")]
public string ServerHost { get; set; }
[Option("server_host_override", Default = TestCredentials.DefaultHostOverride)]
@@ -95,6 +96,7 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args)
{
+ GrpcEnvironment.SetLogger(new ConsoleLogger());
var parserResult = Parser.Default.ParseArguments<ClientOptions>(args)
.WithNotParsed(errors => Environment.Exit(1))
.WithParsed(options =>
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
index 4118f99c2b..be99f92d0b 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
@@ -41,6 +41,7 @@ using System.Threading.Tasks;
using CommandLine;
using CommandLine.Text;
using Grpc.Core;
+using Grpc.Core.Logging;
using Grpc.Core.Utils;
using Grpc.Testing;
using NUnit.Framework;
@@ -68,6 +69,7 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args)
{
+ GrpcEnvironment.SetLogger(new ConsoleLogger());
var parserResult = Parser.Default.ParseArguments<ServerOptions>(args)
.WithNotParsed(errors => Environment.Exit(1))
.WithParsed(options =>
diff --git a/src/csharp/Grpc.IntegrationTesting/Messages.cs b/src/csharp/Grpc.IntegrationTesting/Messages.cs
index 369fe738d6..278ef662e4 100644
--- a/src/csharp/Grpc.IntegrationTesting/Messages.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Messages.cs
@@ -75,12 +75,12 @@ namespace Grpc.Testing {
}
#region Enums
/// <summary>
- /// DEPRECATED, don't use. To be removed shortly.
- /// The type of payload that should be returned.
+ /// DEPRECATED, don't use. To be removed shortly.
+ /// The type of payload that should be returned.
/// </summary>
public enum PayloadType {
/// <summary>
- /// Compressable text format.
+ /// Compressable text format.
/// </summary>
[pbr::OriginalName("COMPRESSABLE")] Compressable = 0,
}
@@ -89,9 +89,9 @@ namespace Grpc.Testing {
#region Messages
/// <summary>
- /// TODO(dgq): Go back to using well-known types once
- /// https://github.com/grpc/grpc/issues/6980 has been fixed.
- /// import "google/protobuf/wrappers.proto";
+ /// TODO(dgq): Go back to using well-known types once
+ /// https://github.com/grpc/grpc/issues/6980 has been fixed.
+ /// import "google/protobuf/wrappers.proto";
/// </summary>
public sealed partial class BoolValue : pb::IMessage<BoolValue> {
private static readonly pb::MessageParser<BoolValue> _parser = new pb::MessageParser<BoolValue>(() => new BoolValue());
@@ -129,7 +129,7 @@ namespace Grpc.Testing {
public const int ValueFieldNumber = 1;
private bool value_;
/// <summary>
- /// The bool value.
+ /// The bool value.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Value {
@@ -214,7 +214,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// A block of data, to simply increase gRPC message size.
+ /// A block of data, to simply increase gRPC message size.
/// </summary>
public sealed partial class Payload : pb::IMessage<Payload> {
private static readonly pb::MessageParser<Payload> _parser = new pb::MessageParser<Payload>(() => new Payload());
@@ -253,8 +253,8 @@ namespace Grpc.Testing {
public const int TypeFieldNumber = 1;
private global::Grpc.Testing.PayloadType type_ = 0;
/// <summary>
- /// DEPRECATED, don't use. To be removed shortly.
- /// The type of data in body.
+ /// DEPRECATED, don't use. To be removed shortly.
+ /// The type of data in body.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.PayloadType Type {
@@ -268,7 +268,7 @@ namespace Grpc.Testing {
public const int BodyFieldNumber = 2;
private pb::ByteString body_ = pb::ByteString.Empty;
/// <summary>
- /// Primary contents of payload.
+ /// Primary contents of payload.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pb::ByteString Body {
@@ -369,8 +369,8 @@ namespace Grpc.Testing {
}
/// <summary>
- /// A protobuf representation for grpc status. This is used by test
- /// clients to specify a status that the server should attempt to return.
+ /// A protobuf representation for grpc status. This is used by test
+ /// clients to specify a status that the server should attempt to return.
/// </summary>
public sealed partial class EchoStatus : pb::IMessage<EchoStatus> {
private static readonly pb::MessageParser<EchoStatus> _parser = new pb::MessageParser<EchoStatus>(() => new EchoStatus());
@@ -518,7 +518,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Unary request.
+ /// Unary request.
/// </summary>
public sealed partial class SimpleRequest : pb::IMessage<SimpleRequest> {
private static readonly pb::MessageParser<SimpleRequest> _parser = new pb::MessageParser<SimpleRequest>(() => new SimpleRequest());
@@ -563,9 +563,9 @@ namespace Grpc.Testing {
public const int ResponseTypeFieldNumber = 1;
private global::Grpc.Testing.PayloadType responseType_ = 0;
/// <summary>
- /// DEPRECATED, don't use. To be removed shortly.
- /// Desired payload type in the response from the server.
- /// If response_type is RANDOM, server randomly chooses one from other formats.
+ /// DEPRECATED, don't use. To be removed shortly.
+ /// Desired payload type in the response from the server.
+ /// If response_type is RANDOM, server randomly chooses one from other formats.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.PayloadType ResponseType {
@@ -579,7 +579,7 @@ namespace Grpc.Testing {
public const int ResponseSizeFieldNumber = 2;
private int responseSize_;
/// <summary>
- /// Desired payload size in the response from the server.
+ /// Desired payload size in the response from the server.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int ResponseSize {
@@ -593,7 +593,7 @@ namespace Grpc.Testing {
public const int PayloadFieldNumber = 3;
private global::Grpc.Testing.Payload payload_;
/// <summary>
- /// Optional input payload sent along with the request.
+ /// Optional input payload sent along with the request.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.Payload Payload {
@@ -607,7 +607,7 @@ namespace Grpc.Testing {
public const int FillUsernameFieldNumber = 4;
private bool fillUsername_;
/// <summary>
- /// Whether SimpleResponse should include username.
+ /// Whether SimpleResponse should include username.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool FillUsername {
@@ -621,7 +621,7 @@ namespace Grpc.Testing {
public const int FillOauthScopeFieldNumber = 5;
private bool fillOauthScope_;
/// <summary>
- /// Whether SimpleResponse should include OAuth scope.
+ /// Whether SimpleResponse should include OAuth scope.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool FillOauthScope {
@@ -635,10 +635,10 @@ namespace Grpc.Testing {
public const int ResponseCompressedFieldNumber = 6;
private global::Grpc.Testing.BoolValue responseCompressed_;
/// <summary>
- /// Whether to request the server to compress the response. This field is
- /// "nullable" in order to interoperate seamlessly with clients not able to
- /// implement the full compression tests by introspecting the call to verify
- /// the response's compression status.
+ /// Whether to request the server to compress the response. This field is
+ /// "nullable" in order to interoperate seamlessly with clients not able to
+ /// implement the full compression tests by introspecting the call to verify
+ /// the response's compression status.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.BoolValue ResponseCompressed {
@@ -652,7 +652,7 @@ namespace Grpc.Testing {
public const int ResponseStatusFieldNumber = 7;
private global::Grpc.Testing.EchoStatus responseStatus_;
/// <summary>
- /// Whether server should return a given status
+ /// Whether server should return a given status
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.EchoStatus ResponseStatus {
@@ -666,7 +666,7 @@ namespace Grpc.Testing {
public const int ExpectCompressedFieldNumber = 8;
private global::Grpc.Testing.BoolValue expectCompressed_;
/// <summary>
- /// Whether the server should expect this request to be compressed.
+ /// Whether the server should expect this request to be compressed.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.BoolValue ExpectCompressed {
@@ -887,7 +887,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Unary response, as configured by the request.
+ /// Unary response, as configured by the request.
/// </summary>
public sealed partial class SimpleResponse : pb::IMessage<SimpleResponse> {
private static readonly pb::MessageParser<SimpleResponse> _parser = new pb::MessageParser<SimpleResponse>(() => new SimpleResponse());
@@ -927,7 +927,7 @@ namespace Grpc.Testing {
public const int PayloadFieldNumber = 1;
private global::Grpc.Testing.Payload payload_;
/// <summary>
- /// Payload to increase message size.
+ /// Payload to increase message size.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.Payload Payload {
@@ -941,8 +941,8 @@ namespace Grpc.Testing {
public const int UsernameFieldNumber = 2;
private string username_ = "";
/// <summary>
- /// The user the request came from, for verifying authentication was
- /// successful when the client expected it.
+ /// The user the request came from, for verifying authentication was
+ /// successful when the client expected it.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Username {
@@ -956,7 +956,7 @@ namespace Grpc.Testing {
public const int OauthScopeFieldNumber = 3;
private string oauthScope_ = "";
/// <summary>
- /// OAuth scope.
+ /// OAuth scope.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string OauthScope {
@@ -1079,7 +1079,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Client-streaming request.
+ /// Client-streaming request.
/// </summary>
public sealed partial class StreamingInputCallRequest : pb::IMessage<StreamingInputCallRequest> {
private static readonly pb::MessageParser<StreamingInputCallRequest> _parser = new pb::MessageParser<StreamingInputCallRequest>(() => new StreamingInputCallRequest());
@@ -1118,7 +1118,7 @@ namespace Grpc.Testing {
public const int PayloadFieldNumber = 1;
private global::Grpc.Testing.Payload payload_;
/// <summary>
- /// Optional input payload sent along with the request.
+ /// Optional input payload sent along with the request.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.Payload Payload {
@@ -1132,10 +1132,10 @@ namespace Grpc.Testing {
public const int ExpectCompressedFieldNumber = 2;
private global::Grpc.Testing.BoolValue expectCompressed_;
/// <summary>
- /// Whether the server should expect this request to be compressed. This field
- /// is "nullable" in order to interoperate seamlessly with servers not able to
- /// implement the full compression tests by introspecting the call to verify
- /// the request's compression status.
+ /// Whether the server should expect this request to be compressed. This field
+ /// is "nullable" in order to interoperate seamlessly with servers not able to
+ /// implement the full compression tests by introspecting the call to verify
+ /// the request's compression status.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.BoolValue ExpectCompressed {
@@ -1248,7 +1248,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Client-streaming response.
+ /// Client-streaming response.
/// </summary>
public sealed partial class StreamingInputCallResponse : pb::IMessage<StreamingInputCallResponse> {
private static readonly pb::MessageParser<StreamingInputCallResponse> _parser = new pb::MessageParser<StreamingInputCallResponse>(() => new StreamingInputCallResponse());
@@ -1286,7 +1286,7 @@ namespace Grpc.Testing {
public const int AggregatedPayloadSizeFieldNumber = 1;
private int aggregatedPayloadSize_;
/// <summary>
- /// Aggregated size of payloads received from the client.
+ /// Aggregated size of payloads received from the client.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int AggregatedPayloadSize {
@@ -1371,7 +1371,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Configuration for a particular response.
+ /// Configuration for a particular response.
/// </summary>
public sealed partial class ResponseParameters : pb::IMessage<ResponseParameters> {
private static readonly pb::MessageParser<ResponseParameters> _parser = new pb::MessageParser<ResponseParameters>(() => new ResponseParameters());
@@ -1411,7 +1411,7 @@ namespace Grpc.Testing {
public const int SizeFieldNumber = 1;
private int size_;
/// <summary>
- /// Desired payload sizes in responses from the server.
+ /// Desired payload sizes in responses from the server.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Size {
@@ -1425,8 +1425,8 @@ namespace Grpc.Testing {
public const int IntervalUsFieldNumber = 2;
private int intervalUs_;
/// <summary>
- /// Desired interval between consecutive responses in the response stream in
- /// microseconds.
+ /// Desired interval between consecutive responses in the response stream in
+ /// microseconds.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int IntervalUs {
@@ -1440,10 +1440,10 @@ namespace Grpc.Testing {
public const int CompressedFieldNumber = 3;
private global::Grpc.Testing.BoolValue compressed_;
/// <summary>
- /// Whether to request the server to compress the response. This field is
- /// "nullable" in order to interoperate seamlessly with clients not able to
- /// implement the full compression tests by introspecting the call to verify
- /// the response's compression status.
+ /// Whether to request the server to compress the response. This field is
+ /// "nullable" in order to interoperate seamlessly with clients not able to
+ /// implement the full compression tests by introspecting the call to verify
+ /// the response's compression status.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.BoolValue Compressed {
@@ -1566,7 +1566,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Server-streaming request.
+ /// Server-streaming request.
/// </summary>
public sealed partial class StreamingOutputCallRequest : pb::IMessage<StreamingOutputCallRequest> {
private static readonly pb::MessageParser<StreamingOutputCallRequest> _parser = new pb::MessageParser<StreamingOutputCallRequest>(() => new StreamingOutputCallRequest());
@@ -1607,11 +1607,11 @@ namespace Grpc.Testing {
public const int ResponseTypeFieldNumber = 1;
private global::Grpc.Testing.PayloadType responseType_ = 0;
/// <summary>
- /// DEPRECATED, don't use. To be removed shortly.
- /// Desired payload type in the response from the server.
- /// If response_type is RANDOM, the payload from each response in the stream
- /// might be of different types. This is to simulate a mixed type of payload
- /// stream.
+ /// DEPRECATED, don't use. To be removed shortly.
+ /// Desired payload type in the response from the server.
+ /// If response_type is RANDOM, the payload from each response in the stream
+ /// might be of different types. This is to simulate a mixed type of payload
+ /// stream.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.PayloadType ResponseType {
@@ -1627,7 +1627,7 @@ namespace Grpc.Testing {
= pb::FieldCodec.ForMessage(18, global::Grpc.Testing.ResponseParameters.Parser);
private readonly pbc::RepeatedField<global::Grpc.Testing.ResponseParameters> responseParameters_ = new pbc::RepeatedField<global::Grpc.Testing.ResponseParameters>();
/// <summary>
- /// Configuration for each expected response message.
+ /// Configuration for each expected response message.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<global::Grpc.Testing.ResponseParameters> ResponseParameters {
@@ -1638,7 +1638,7 @@ namespace Grpc.Testing {
public const int PayloadFieldNumber = 3;
private global::Grpc.Testing.Payload payload_;
/// <summary>
- /// Optional input payload sent along with the request.
+ /// Optional input payload sent along with the request.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.Payload Payload {
@@ -1652,7 +1652,7 @@ namespace Grpc.Testing {
public const int ResponseStatusFieldNumber = 7;
private global::Grpc.Testing.EchoStatus responseStatus_;
/// <summary>
- /// Whether server should return a given status
+ /// Whether server should return a given status
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.EchoStatus ResponseStatus {
@@ -1790,7 +1790,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Server-streaming response, as configured by the request and parameters.
+ /// Server-streaming response, as configured by the request and parameters.
/// </summary>
public sealed partial class StreamingOutputCallResponse : pb::IMessage<StreamingOutputCallResponse> {
private static readonly pb::MessageParser<StreamingOutputCallResponse> _parser = new pb::MessageParser<StreamingOutputCallResponse>(() => new StreamingOutputCallResponse());
@@ -1828,7 +1828,7 @@ namespace Grpc.Testing {
public const int PayloadFieldNumber = 1;
private global::Grpc.Testing.Payload payload_;
/// <summary>
- /// Payload to increase response size.
+ /// Payload to increase response size.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.Payload Payload {
@@ -1919,8 +1919,8 @@ namespace Grpc.Testing {
}
/// <summary>
- /// For reconnect interop test only.
- /// Client tells server what reconnection parameters it used.
+ /// For reconnect interop test only.
+ /// Client tells server what reconnection parameters it used.
/// </summary>
public sealed partial class ReconnectParams : pb::IMessage<ReconnectParams> {
private static readonly pb::MessageParser<ReconnectParams> _parser = new pb::MessageParser<ReconnectParams>(() => new ReconnectParams());
@@ -2040,9 +2040,9 @@ namespace Grpc.Testing {
}
/// <summary>
- /// For reconnect interop test only.
- /// Server tells client whether its reconnects are following the spec and the
- /// reconnect backoffs it saw.
+ /// For reconnect interop test only.
+ /// Server tells client whether its reconnects are following the spec and the
+ /// reconnect backoffs it saw.
/// </summary>
public sealed partial class ReconnectInfo : pb::IMessage<ReconnectInfo> {
private static readonly pb::MessageParser<ReconnectInfo> _parser = new pb::MessageParser<ReconnectInfo>(() => new ReconnectInfo());
diff --git a/src/csharp/Grpc.IntegrationTesting/Metrics.cs b/src/csharp/Grpc.IntegrationTesting/Metrics.cs
index 4de1847e5f..84eb09af4f 100644
--- a/src/csharp/Grpc.IntegrationTesting/Metrics.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Metrics.cs
@@ -44,7 +44,7 @@ namespace Grpc.Testing {
}
#region Messages
/// <summary>
- /// Reponse message containing the gauge name and value
+ /// Reponse message containing the gauge name and value
/// </summary>
public sealed partial class GaugeResponse : pb::IMessage<GaugeResponse> {
private static readonly pb::MessageParser<GaugeResponse> _parser = new pb::MessageParser<GaugeResponse>(() => new GaugeResponse());
@@ -282,7 +282,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Request message containing the gauge name
+ /// Request message containing the gauge name
/// </summary>
public sealed partial class GaugeRequest : pb::IMessage<GaugeRequest> {
private static readonly pb::MessageParser<GaugeRequest> _parser = new pb::MessageParser<GaugeRequest>(() => new GaugeRequest());
diff --git a/src/csharp/Grpc.IntegrationTesting/Payloads.cs b/src/csharp/Grpc.IntegrationTesting/Payloads.cs
index 7aef35cda3..f918b9576b 100644
--- a/src/csharp/Grpc.IntegrationTesting/Payloads.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Payloads.cs
@@ -335,8 +335,8 @@ namespace Grpc.Testing {
}
/// <summary>
- /// TODO (vpai): Fill this in once the details of complex, representative
- /// protos are decided
+ /// TODO (vpai): Fill this in once the details of complex, representative
+ /// protos are decided
/// </summary>
public sealed partial class ComplexProtoParams : pb::IMessage<ComplexProtoParams> {
private static readonly pb::MessageParser<ComplexProtoParams> _parser = new pb::MessageParser<ComplexProtoParams>(() => new ComplexProtoParams());
diff --git a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
index 62a7347d42..b17b2c2183 100644
--- a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
+++ b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
@@ -42,6 +42,7 @@ using System.Threading.Tasks;
using CommandLine;
using CommandLine.Text;
using Grpc.Core;
+using Grpc.Core.Logging;
using Grpc.Core.Utils;
using Grpc.Testing;
using NUnit.Framework;
@@ -65,6 +66,7 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args)
{
+ GrpcEnvironment.SetLogger(new ConsoleLogger());
var parserResult = Parser.Default.ParseArguments<ServerOptions>(args)
.WithNotParsed((x) => Environment.Exit(1))
.WithParsed(options =>
diff --git a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs
index f85e272711..377dad63f4 100644
--- a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs
@@ -37,6 +37,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Google.Protobuf;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Testing;
@@ -68,7 +69,7 @@ namespace Grpc.IntegrationTesting
server = new Server
{
- Services = { TestService.BindService(new TestServiceImpl()) },
+ Services = { TestService.BindService(new SslCredentialsTestServiceImpl()) },
Ports = { { Host, ServerPort.PickUnused, serverCredentials } }
};
server.Start();
@@ -95,5 +96,40 @@ namespace Grpc.IntegrationTesting
var response = client.UnaryCall(new SimpleRequest { ResponseSize = 10 });
Assert.AreEqual(10, response.Payload.Body.Length);
}
+
+ [Test]
+ public async Task AuthContextIsPopulated()
+ {
+ var call = client.StreamingInputCall();
+ await call.RequestStream.CompleteAsync();
+ var response = await call.ResponseAsync;
+ Assert.AreEqual(12345, response.AggregatedPayloadSize);
+ }
+
+ private class SslCredentialsTestServiceImpl : TestService.TestServiceBase
+ {
+ public override async Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
+ {
+ return new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) };
+ }
+
+ public override async Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream, ServerCallContext context)
+ {
+ var authContext = context.AuthContext;
+ await requestStream.ForEachAsync(async request => {});
+
+ Assert.IsTrue(authContext.IsPeerAuthenticated);
+ Assert.AreEqual("x509_subject_alternative_name", authContext.PeerIdentityPropertyName);
+ Assert.IsTrue(authContext.PeerIdentity.Count() > 0);
+ Assert.AreEqual("ssl", authContext.FindPropertiesByName("transport_security_type").First().Value);
+
+ return new StreamingInputCallResponse { AggregatedPayloadSize = 12345 };
+ }
+
+ private static Payload CreateZerosPayload(int size)
+ {
+ return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
+ }
+ }
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting/Stats.cs b/src/csharp/Grpc.IntegrationTesting/Stats.cs
index 504aa11d8a..79ff220436 100644
--- a/src/csharp/Grpc.IntegrationTesting/Stats.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Stats.cs
@@ -90,7 +90,7 @@ namespace Grpc.Testing {
public const int TimeElapsedFieldNumber = 1;
private double timeElapsed_;
/// <summary>
- /// wall clock time change in seconds since last reset
+ /// wall clock time change in seconds since last reset
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double TimeElapsed {
@@ -104,7 +104,7 @@ namespace Grpc.Testing {
public const int TimeUserFieldNumber = 2;
private double timeUser_;
/// <summary>
- /// change in user time (in seconds) used by the server since last reset
+ /// change in user time (in seconds) used by the server since last reset
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double TimeUser {
@@ -118,8 +118,8 @@ namespace Grpc.Testing {
public const int TimeSystemFieldNumber = 3;
private double timeSystem_;
/// <summary>
- /// change in server time (in seconds) used by the server process and all
- /// threads since last reset
+ /// change in server time (in seconds) used by the server process and all
+ /// threads since last reset
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double TimeSystem {
@@ -133,7 +133,7 @@ namespace Grpc.Testing {
public const int TotalCpuTimeFieldNumber = 4;
private ulong totalCpuTime_;
/// <summary>
- /// change in total cpu time of the server (data from proc/stat)
+ /// change in total cpu time of the server (data from proc/stat)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ulong TotalCpuTime {
@@ -147,7 +147,7 @@ namespace Grpc.Testing {
public const int IdleCpuTimeFieldNumber = 5;
private ulong idleCpuTime_;
/// <summary>
- /// change in idle time of the server (data from proc/stat)
+ /// change in idle time of the server (data from proc/stat)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ulong IdleCpuTime {
@@ -296,7 +296,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Histogram params based on grpc/support/histogram.c
+ /// Histogram params based on grpc/support/histogram.c
/// </summary>
public sealed partial class HistogramParams : pb::IMessage<HistogramParams> {
private static readonly pb::MessageParser<HistogramParams> _parser = new pb::MessageParser<HistogramParams>(() => new HistogramParams());
@@ -335,7 +335,7 @@ namespace Grpc.Testing {
public const int ResolutionFieldNumber = 1;
private double resolution_;
/// <summary>
- /// first bucket is [0, 1 + resolution)
+ /// first bucket is [0, 1 + resolution)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double Resolution {
@@ -349,7 +349,7 @@ namespace Grpc.Testing {
public const int MaxPossibleFieldNumber = 2;
private double maxPossible_;
/// <summary>
- /// use enough buckets to allow this value
+ /// use enough buckets to allow this value
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double MaxPossible {
@@ -450,7 +450,7 @@ namespace Grpc.Testing {
}
/// <summary>
- /// Histogram data based on grpc/support/histogram.c
+ /// Histogram data based on grpc/support/histogram.c
/// </summary>
public sealed partial class HistogramData : pb::IMessage<HistogramData> {
private static readonly pb::MessageParser<HistogramData> _parser = new pb::MessageParser<HistogramData>(() => new HistogramData());
@@ -887,7 +887,7 @@ namespace Grpc.Testing {
public const int LatenciesFieldNumber = 1;
private global::Grpc.Testing.HistogramData latencies_;
/// <summary>
- /// Latency histogram. Data points are in nanoseconds.
+ /// Latency histogram. Data points are in nanoseconds.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Testing.HistogramData Latencies {
@@ -901,7 +901,7 @@ namespace Grpc.Testing {
public const int TimeElapsedFieldNumber = 2;
private double timeElapsed_;
/// <summary>
- /// See ServerStats for details.
+ /// See ServerStats for details.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double TimeElapsed {
@@ -939,7 +939,7 @@ namespace Grpc.Testing {
= pb::FieldCodec.ForMessage(42, global::Grpc.Testing.RequestResultCount.Parser);
private readonly pbc::RepeatedField<global::Grpc.Testing.RequestResultCount> requestResults_ = new pbc::RepeatedField<global::Grpc.Testing.RequestResultCount>();
/// <summary>
- /// Number of failed requests (one row per status code seen)
+ /// Number of failed requests (one row per status code seen)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<global::Grpc.Testing.RequestResultCount> RequestResults {
diff --git a/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
index 750613b078..dbf8844265 100644
--- a/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
@@ -92,6 +92,7 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args)
{
+ GrpcEnvironment.SetLogger(new ConsoleLogger());
var parserResult = Parser.Default.ParseArguments<ClientOptions>(args)
.WithNotParsed((x) => Environment.Exit(1))
.WithParsed(options => {
diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config
index a03ee926f4..030f9d97b8 100644
--- a/src/csharp/Grpc.IntegrationTesting/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting/packages.config
@@ -1,17 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
- <package id="Castle.Core" version="3.3.3" targetFramework="net45" />
- <package id="CommandLineParser.Unofficial" version="2.0.275" targetFramework="net45" />
- <package id="Google.Apis" version="1.16.0" targetFramework="net45" />
- <package id="Google.Apis.Auth" version="1.16.0" targetFramework="net45" />
- <package id="Google.Apis.Core" version="1.16.0" targetFramework="net45" />
- <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
- <package id="log4net" version="2.0.3" targetFramework="net45" />
- <package id="Moq" version="4.6.38-alpha" targetFramework="net45" />
- <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
- <package id="NUnit" version="3.2.0" targetFramework="net45" />
- <package id="NUnitLite" version="3.2.0" targetFramework="net45" />
+ <package id="Castle.Core" version="4.0.0" targetFramework="net45" />
+ <package id="CommandLineParser" version="2.1.1-beta" targetFramework="net45" />
+ <package id="Google.Apis" version="1.21.0" targetFramework="net45" />
+ <package id="Google.Apis.Auth" version="1.21.0" targetFramework="net45" />
+ <package id="Google.Apis.Core" version="1.21.0" targetFramework="net45" />
+ <package id="Google.Protobuf" version="3.2.0" targetFramework="net45" />
+ <package id="Moq" version="4.7.0" targetFramework="net45" />
+ <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
+ <package id="NUnit" version="3.6.0" targetFramework="net45" />
+ <package id="NUnitLite" version="3.6.0" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
<package id="Zlib.Portable.Signed" version="1.11.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting/project.json b/src/csharp/Grpc.IntegrationTesting/project.json
index e47b5953da..40fc566adc 100644
--- a/src/csharp/Grpc.IntegrationTesting/project.json
+++ b/src/csharp/Grpc.IntegrationTesting/project.json
@@ -16,8 +16,8 @@
"data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
"data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
"data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
@@ -37,8 +37,8 @@
"data/ca.pem": "../Grpc.IntegrationTesting/data/ca.pem",
"data/server1.key": "../Grpc.IntegrationTesting/data/server1.key",
"data/server1.pem": "../Grpc.IntegrationTesting/data/server1.pem",
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
@@ -54,18 +54,15 @@
"Grpc.Core": {
"target": "project"
},
- "Google.Protobuf": "3.0.0",
- "CommandLineParser.Unofficial": "2.0.275",
- "Moq": "4.6.38-alpha",
- "NUnit": "3.2.0",
- "NUnitLite": "3.2.0-*"
+ "Google.Protobuf": "3.2.0",
+ "CommandLineParser": "2.1.1-beta",
+ "Moq": "4.7.0",
+ "NUnit": "3.6.0",
+ "NUnitLite": "3.6.0"
},
"frameworks": {
"net45": {
- "frameworkAssemblies": {
- "System.Runtime": "",
- "System.IO": ""
- }
+ "frameworkAssemblies": {}
},
"netcoreapp1.0": {
"imports": [
diff --git a/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj b/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj
index c5918b194e..7e2b551799 100644
--- a/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj
+++ b/src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj
@@ -35,17 +35,17 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
- <Reference Include="nunit.framework">
- <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
- </Reference>
- <Reference Include="nunitlite">
- <HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
+ <Reference Include="System.Interactive.Async">
+ <HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
<Reference Include="Google.Protobuf">
- <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
+ <HintPath>..\packages\Google.Protobuf.3.2.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
- <Reference Include="System.Interactive.Async">
- <HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
+ <Reference Include="nunit.framework">
+ <HintPath>..\packages\NUnit.3.6.0\lib\net45\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="nunitlite">
+ <HintPath>..\packages\NUnitLite.3.6.0\lib\net45\nunitlite.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
diff --git a/src/csharp/Grpc.Reflection.Tests/packages.config b/src/csharp/Grpc.Reflection.Tests/packages.config
index 0fed4dbd41..8a7f7a0652 100644
--- a/src/csharp/Grpc.Reflection.Tests/packages.config
+++ b/src/csharp/Grpc.Reflection.Tests/packages.config
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
- <package id="NUnit" version="3.2.0" targetFramework="net45" />
- <package id="NUnitLite" version="3.2.0" targetFramework="net45" />
+ <package id="Google.Protobuf" version="3.2.0" targetFramework="net45" />
+ <package id="NUnit" version="3.6.0" targetFramework="net45" />
+ <package id="NUnitLite" version="3.6.0" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Reflection.Tests/project.json b/src/csharp/Grpc.Reflection.Tests/project.json
index 61d3b7e47b..fc05557c88 100644
--- a/src/csharp/Grpc.Reflection.Tests/project.json
+++ b/src/csharp/Grpc.Reflection.Tests/project.json
@@ -13,8 +13,8 @@
},
"copyToOutput": {
"mappings": {
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Debug/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Debug/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
@@ -31,8 +31,8 @@
},
"copyToOutput": {
"mappings": {
- "grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
- "grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x64.dll": "../../../cmake/build/x64/Release/grpc_csharp_ext.dll",
+ "grpc_csharp_ext.x86.dll": "../../../cmake/build/Win32/Release/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
@@ -45,8 +45,8 @@
"Grpc.Reflection": {
"target": "project"
},
- "NUnit": "3.2.0",
- "NUnitLite": "3.2.0-*"
+ "NUnit": "3.6.0",
+ "NUnitLite": "3.6.0"
},
"frameworks": {
"net45": { },
diff --git a/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj b/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj
index 4e254a0b53..b0ab170e3f 100644
--- a/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj
+++ b/src/csharp/Grpc.Reflection/Grpc.Reflection.csproj
@@ -36,12 +36,12 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
- <Reference Include="Google.Protobuf">
- <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
- </Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
+ <Reference Include="Google.Protobuf">
+ <HintPath>..\packages\Google.Protobuf.3.2.0\lib\net45\Google.Protobuf.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
diff --git a/src/csharp/Grpc.Reflection/Reflection.cs b/src/csharp/Grpc.Reflection/Reflection.cs
index 06c5d08030..86e9aace8c 100644
--- a/src/csharp/Grpc.Reflection/Reflection.cs
+++ b/src/csharp/Grpc.Reflection/Reflection.cs
@@ -70,7 +70,7 @@ namespace Grpc.Reflection.V1Alpha {
}
#region Messages
/// <summary>
- /// The message sent by the client when calling ServerReflectionInfo method.
+ /// The message sent by the client when calling ServerReflectionInfo method.
/// </summary>
public sealed partial class ServerReflectionRequest : pb::IMessage<ServerReflectionRequest> {
private static readonly pb::MessageParser<ServerReflectionRequest> _parser = new pb::MessageParser<ServerReflectionRequest>(() => new ServerReflectionRequest());
@@ -136,7 +136,7 @@ namespace Grpc.Reflection.V1Alpha {
/// <summary>Field number for the "file_by_filename" field.</summary>
public const int FileByFilenameFieldNumber = 3;
/// <summary>
- /// Find a proto file by the file name.
+ /// Find a proto file by the file name.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string FileByFilename {
@@ -150,9 +150,9 @@ namespace Grpc.Reflection.V1Alpha {
/// <summary>Field number for the "file_containing_symbol" field.</summary>
public const int FileContainingSymbolFieldNumber = 4;
/// <summary>
- /// Find the proto file that declares the given fully-qualified symbol name.
- /// This field should be a fully-qualified symbol name
- /// (e.g. &lt;package>.&lt;service>[.&lt;method>] or &lt;package>.&lt;type>).
+ /// Find the proto file that declares the given fully-qualified symbol name.
+ /// This field should be a fully-qualified symbol name
+ /// (e.g. &lt;package>.&lt;service>[.&lt;method>] or &lt;package>.&lt;type>).
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string FileContainingSymbol {
@@ -166,8 +166,8 @@ namespace Grpc.Reflection.V1Alpha {
/// <summary>Field number for the "file_containing_extension" field.</summary>
public const int FileContainingExtensionFieldNumber = 5;
/// <summary>
- /// Find the proto file which defines an extension extending the given
- /// message type with the given field number.
+ /// Find the proto file which defines an extension extending the given
+ /// message type with the given field number.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Reflection.V1Alpha.ExtensionRequest FileContainingExtension {
@@ -181,14 +181,14 @@ namespace Grpc.Reflection.V1Alpha {
/// <summary>Field number for the "all_extension_numbers_of_type" field.</summary>
public const int AllExtensionNumbersOfTypeFieldNumber = 6;
/// <summary>
- /// Finds the tag numbers used by all known extensions of the given message
- /// type, and appends them to ExtensionNumberResponse in an undefined order.
- /// Its corresponding method is best-effort: it's not guaranteed that the
- /// reflection service will implement this method, and it's not guaranteed
- /// that this method will provide all extensions. Returns
- /// StatusCode::UNIMPLEMENTED if it's not implemented.
- /// This field should be a fully-qualified type name. The format is
- /// &lt;package>.&lt;type>
+ /// Finds the tag numbers used by all known extensions of the given message
+ /// type, and appends them to ExtensionNumberResponse in an undefined order.
+ /// Its corresponding method is best-effort: it's not guaranteed that the
+ /// reflection service will implement this method, and it's not guaranteed
+ /// that this method will provide all extensions. Returns
+ /// StatusCode::UNIMPLEMENTED if it's not implemented.
+ /// This field should be a fully-qualified type name. The format is
+ /// &lt;package>.&lt;type>
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string AllExtensionNumbersOfType {
@@ -202,8 +202,8 @@ namespace Grpc.Reflection.V1Alpha {
/// <summary>Field number for the "list_services" field.</summary>
public const int ListServicesFieldNumber = 7;
/// <summary>
- /// List the full names of registered services. The content will not be
- /// checked.
+ /// List the full names of registered services. The content will not be
+ /// checked.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string ListServices {
@@ -401,8 +401,8 @@ namespace Grpc.Reflection.V1Alpha {
}
/// <summary>
- /// The type name and extension number sent by the client when requesting
- /// file_containing_extension.
+ /// The type name and extension number sent by the client when requesting
+ /// file_containing_extension.
/// </summary>
public sealed partial class ExtensionRequest : pb::IMessage<ExtensionRequest> {
private static readonly pb::MessageParser<ExtensionRequest> _parser = new pb::MessageParser<ExtensionRequest>(() => new ExtensionRequest());
@@ -441,7 +441,7 @@ namespace Grpc.Reflection.V1Alpha {
public const int ContainingTypeFieldNumber = 1;
private string containingType_ = "";
/// <summary>
- /// Fully-qualified type name. The format should be &lt;package>.&lt;type>
+ /// Fully-qualified type name. The format should be &lt;package>.&lt;type>
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string ContainingType {
@@ -553,7 +553,7 @@ namespace Grpc.Reflection.V1Alpha {
}
/// <summary>
- /// The message sent by the server to answer ServerReflectionInfo method.
+ /// The message sent by the server to answer ServerReflectionInfo method.
/// </summary>
public sealed partial class ServerReflectionResponse : pb::IMessage<ServerReflectionResponse> {
private static readonly pb::MessageParser<ServerReflectionResponse> _parser = new pb::MessageParser<ServerReflectionResponse>(() => new ServerReflectionResponse());
@@ -628,12 +628,12 @@ namespace Grpc.Reflection.V1Alpha {
/// <summary>Field number for the "file_descriptor_response" field.</summary>
public const int FileDescriptorResponseFieldNumber = 4;
/// <summary>
- /// This message is used to answer file_by_filename, file_containing_symbol,
- /// file_containing_extension requests with transitive dependencies. As
- /// the repeated label is not allowed in oneof fields, we use a
- /// FileDescriptorResponse message to encapsulate the repeated fields.
- /// The reflection service is allowed to avoid sending FileDescriptorProtos
- /// that were previously sent in response to earlier requests in the stream.
+ /// This message is used to answer file_by_filename, file_containing_symbol,
+ /// file_containing_extension requests with transitive dependencies. As
+ /// the repeated label is not allowed in oneof fields, we use a
+ /// FileDescriptorResponse message to encapsulate the repeated fields.
+ /// The reflection service is allowed to avoid sending FileDescriptorProtos
+ /// that were previously sent in response to earlier requests in the stream.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Reflection.V1Alpha.FileDescriptorResponse FileDescriptorResponse {
@@ -647,7 +647,7 @@ namespace Grpc.Reflection.V1Alpha {
/// <summary>Field number for the "all_extension_numbers_response" field.</summary>
public const int AllExtensionNumbersResponseFieldNumber = 5;
/// <summary>
- /// This message is used to answer all_extension_numbers_of_type requst.
+ /// This message is used to answer all_extension_numbers_of_type requst.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse AllExtensionNumbersResponse {
@@ -661,7 +661,7 @@ namespace Grpc.Reflection.V1Alpha {
/// <summary>Field number for the "list_services_response" field.</summary>
public const int ListServicesResponseFieldNumber = 6;
/// <summary>
- /// This message is used to answer list_services request.
+ /// This message is used to answer list_services request.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Reflection.V1Alpha.ListServiceResponse ListServicesResponse {
@@ -675,7 +675,7 @@ namespace Grpc.Reflection.V1Alpha {
/// <summary>Field number for the "error_response" field.</summary>
public const int ErrorResponseFieldNumber = 7;
/// <summary>
- /// This message is used when an error occurs.
+ /// This message is used when an error occurs.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Grpc.Reflection.V1Alpha.ErrorResponse ErrorResponse {
@@ -893,9 +893,9 @@ namespace Grpc.Reflection.V1Alpha {
}
/// <summary>
- /// Serialized FileDescriptorProto messages sent by the server answering
- /// a file_by_filename, file_containing_symbol, or file_containing_extension
- /// request.
+ /// Serialized FileDescriptorProto messages sent by the server answering
+ /// a file_by_filename, file_containing_symbol, or file_containing_extension
+ /// request.
/// </summary>
public sealed partial class FileDescriptorResponse : pb::IMessage<FileDescriptorResponse> {
private static readonly pb::MessageParser<FileDescriptorResponse> _parser = new pb::MessageParser<FileDescriptorResponse>(() => new FileDescriptorResponse());
@@ -935,9 +935,9 @@ namespace Grpc.Reflection.V1Alpha {
= pb::FieldCodec.ForBytes(10);
private readonly pbc::RepeatedField<pb::ByteString> fileDescriptorProto_ = new pbc::RepeatedField<pb::ByteString>();
/// <summary>
- /// Serialized FileDescriptorProto messages. We avoid taking a dependency on
- /// descriptor.proto, which uses proto2 only features, by making them opaque
- /// bytes instead.
+ /// Serialized FileDescriptorProto messages. We avoid taking a dependency on
+ /// descriptor.proto, which uses proto2 only features, by making them opaque
+ /// bytes instead.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<pb::ByteString> FileDescriptorProto {
@@ -1012,8 +1012,8 @@ namespace Grpc.Reflection.V1Alpha {
}
/// <summary>
- /// A list of extension numbers sent by the server answering
- /// all_extension_numbers_of_type request.
+ /// A list of extension numbers sent by the server answering
+ /// all_extension_numbers_of_type request.
/// </summary>
public sealed partial class ExtensionNumberResponse : pb::IMessage<ExtensionNumberResponse> {
private static readonly pb::MessageParser<ExtensionNumberResponse> _parser = new pb::MessageParser<ExtensionNumberResponse>(() => new ExtensionNumberResponse());
@@ -1052,8 +1052,8 @@ namespace Grpc.Reflection.V1Alpha {
public const int BaseTypeNameFieldNumber = 1;
private string baseTypeName_ = "";
/// <summary>
- /// Full name of the base type, including the package name. The format
- /// is &lt;package>.&lt;type>
+ /// Full name of the base type, including the package name. The format
+ /// is &lt;package>.&lt;type>
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string BaseTypeName {
@@ -1158,7 +1158,7 @@ namespace Grpc.Reflection.V1Alpha {
}
/// <summary>
- /// A list of ServiceResponse sent by the server answering list_services request.
+ /// A list of ServiceResponse sent by the server answering list_services request.
/// </summary>
public sealed partial class ListServiceResponse : pb::IMessage<ListServiceResponse> {
private static readonly pb::MessageParser<ListServiceResponse> _parser = new pb::MessageParser<ListServiceResponse>(() => new ListServiceResponse());
@@ -1198,8 +1198,8 @@ namespace Grpc.Reflection.V1Alpha {
= pb::FieldCodec.ForMessage(10, global::Grpc.Reflection.V1Alpha.ServiceResponse.Parser);
private readonly pbc::RepeatedField<global::Grpc.Reflection.V1Alpha.ServiceResponse> service_ = new pbc::RepeatedField<global::Grpc.Reflection.V1Alpha.ServiceResponse>();
/// <summary>
- /// The information of each service may be expanded in the future, so we use
- /// ServiceResponse message to encapsulate it.
+ /// The information of each service may be expanded in the future, so we use
+ /// ServiceResponse message to encapsulate it.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<global::Grpc.Reflection.V1Alpha.ServiceResponse> Service {
@@ -1274,8 +1274,8 @@ namespace Grpc.Reflection.V1Alpha {
}
/// <summary>
- /// The information of a single service used by ListServiceResponse to answer
- /// list_services request.
+ /// The information of a single service used by ListServiceResponse to answer
+ /// list_services request.
/// </summary>
public sealed partial class ServiceResponse : pb::IMessage<ServiceResponse> {
private static readonly pb::MessageParser<ServiceResponse> _parser = new pb::MessageParser<ServiceResponse>(() => new ServiceResponse());
@@ -1313,8 +1313,8 @@ namespace Grpc.Reflection.V1Alpha {
public const int NameFieldNumber = 1;
private string name_ = "";
/// <summary>
- /// Full name of a registered service, including its package name. The format
- /// is &lt;package>.&lt;service>
+ /// Full name of a registered service, including its package name. The format
+ /// is &lt;package>.&lt;service>
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Name {
@@ -1399,7 +1399,7 @@ namespace Grpc.Reflection.V1Alpha {
}
/// <summary>
- /// The error code and error message sent by the server when an error occurs.
+ /// The error code and error message sent by the server when an error occurs.
/// </summary>
public sealed partial class ErrorResponse : pb::IMessage<ErrorResponse> {
private static readonly pb::MessageParser<ErrorResponse> _parser = new pb::MessageParser<ErrorResponse>(() => new ErrorResponse());
@@ -1438,7 +1438,7 @@ namespace Grpc.Reflection.V1Alpha {
public const int ErrorCodeFieldNumber = 1;
private int errorCode_;
/// <summary>
- /// This field uses the error codes defined in grpc::StatusCode.
+ /// This field uses the error codes defined in grpc::StatusCode.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int ErrorCode {
diff --git a/src/csharp/Grpc.Reflection/packages.config b/src/csharp/Grpc.Reflection/packages.config
index 5ab40b7a8c..eec292b306 100644
--- a/src/csharp/Grpc.Reflection/packages.config
+++ b/src/csharp/Grpc.Reflection/packages.config
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
+ <package id="Google.Protobuf" version="3.2.0" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Reflection/project.json b/src/csharp/Grpc.Reflection/project.json
index bfc57661eb..014c78e489 100644
--- a/src/csharp/Grpc.Reflection/project.json
+++ b/src/csharp/Grpc.Reflection/project.json
@@ -1,5 +1,5 @@
{
- "version": "1.2.0-dev",
+ "version": "1.3.0-dev",
"title": "gRPC C# Reflection",
"authors": [ "Google Inc." ],
"copyright": "Copyright 2016, Google Inc.",
@@ -21,16 +21,11 @@
}
},
"dependencies": {
- "Grpc.Core": "1.2.0-dev",
- "Google.Protobuf": "3.0.0"
+ "Grpc.Core": "1.3.0-dev",
+ "Google.Protobuf": "3.2.0"
},
"frameworks": {
- "net45": {
- "frameworkAssemblies": {
- "System.Runtime": "",
- "System.IO": ""
- }
- },
+ "net45": {},
"netstandard1.5": {
"dependencies": {
"NETStandard.Library": "1.6.0"
diff --git a/src/csharp/README.md b/src/csharp/README.md
index 0405ff88a0..a21b72f225 100644
--- a/src/csharp/README.md
+++ b/src/csharp/README.md
@@ -7,19 +7,19 @@ A C# implementation of gRPC.
SUPPORTED PLATFORMS
------------------
+- [.NET Core](https://dotnet.github.io/) on Linux, Windows and Mac OS X
- .NET Framework 4.5+ (Windows)
-- [.NET Core](https://dotnet.github.io/) on Linux, Windows and Mac OS X (starting from version 1.0.1)
- Mono 4+ on Linux, Windows and Mac OS X
-
PREREQUISITES
--------------
+When using gRPC C# under .NET Core you only need to [install .NET Core](https://www.microsoft.com/net/core).
+
- Windows: .NET Framework 4.5+, Visual Studio 2013 or 2015
- Linux: Mono 4+, MonoDevelop 5.9+ (with NuGet add-in installed)
- Mac OS X: Xamarin Studio 5.9+
-
HOW TO USE
--------------
@@ -27,7 +27,7 @@ HOW TO USE
- Open Visual Studio / MonoDevelop / Xamarin Studio and start a new project/solution.
-- Add the [Grpc](https://www.nuget.org/packages/Grpc/) NuGet package as a dependency (Project options -> Manage NuGet Packages).
+- Add the [Grpc](https://www.nuget.org/packages/Grpc/) NuGet package as a dependency (Project options -> Manage NuGet Packages).
- To be able to generate code from Protocol Buffer (`.proto`) file definitions, add the [Grpc.Tools](https://www.nuget.org/packages/Grpc.Tools/) NuGet package that contains Protocol Buffers compiler (_protoc_) and the gRPC _protoc_ plugin.
@@ -37,23 +37,15 @@ BUILD FROM SOURCE
You only need to go through these steps if you are planning to develop gRPC C#.
If you are a user of gRPC C#, go to Usage section above.
-**Windows**
-
-- The grpc_csharp_ext native library needs to be built so you can build the gRPC C# solution. Open the
- solution `vsprojects/grpc_csharp_ext.sln` in Visual Studio and build it.
+**Windows, Linux or Mac OS X**
-- Open `src\csharp\Grpc.sln` (path is relative to gRPC repository root)
- using Visual Studio
-
-**Linux and Mac OS X**
-
-- The grpc_csharp_ext native library needs to be built so you can build the gRPC C# solution:
- ```sh
+- The easiest way to build is using the `run_tests.py` script that will take care of building the `grpc_csharp_ext` native library:
+ ```
# from the gRPC repository root
- $ tools/run_tests/run_tests.py -c dbg -l csharp --build_only
+ $ python tools/run_tests/run_tests.py -c dbg -l csharp --build_only
```
-- Use MonoDevelop / Xamarin Studio to open the solution Grpc.sln
+- Use Visual Studio / MonoDevelop / Xamarin Studio to open the solution Grpc.sln
RUNNING TESTS
-------------
@@ -79,23 +71,10 @@ DOCUMENTATION
- [Helloworld Example][]
- [RouteGuide Tutorial][]
-CONTENTS
---------
-
-- ext:
- The extension library that wraps C API to be more digestible by C#.
-- Grpc.Auth:
- gRPC OAuth2/JWT support.
-- Grpc.Core:
- The main gRPC C# library.
-- Grpc.Examples:
- API examples for math.proto
-- Grpc.Examples.MathClient:
- An example client that sends requests to math server.
-- Grpc.Examples.MathServer:
- An example server that implements a simple math service.
-- Grpc.IntegrationTesting:
- Cross-language gRPC implementation testing (interop testing).
+PERFORMANCE
+-----------
+
+For best gRPC C# performance, use [.NET Core](https://dotnet.github.io/) and the Server GC mode `"System.GC.Server": true` for your applications.
THE NATIVE DEPENDENCY
---------------
diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat
index b99fdcbdfd..4fec2c71cf 100755
--- a/src/csharp/build_packages_dotnetcli.bat
+++ b/src/csharp/build_packages_dotnetcli.bat
@@ -28,7 +28,7 @@
@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@rem Current package versions
-set VERSION=1.2.0-dev
+set VERSION=1.3.0-dev
set PROTOBUF_VERSION=3.0.0
@rem Adjust the location of nuget.exe
diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh
index 442e3acad2..f51b42bc8c 100755
--- a/src/csharp/build_packages_dotnetcli.sh
+++ b/src/csharp/build_packages_dotnetcli.sh
@@ -66,7 +66,7 @@ dotnet pack --configuration Release Grpc.Auth/project.json --output ../../artifa
dotnet pack --configuration Release Grpc.HealthCheck/project.json --output ../../artifacts
dotnet pack --configuration Release Grpc.Reflection/project.json --output ../../artifacts
-nuget pack Grpc.nuspec -Version "1.2.0-dev" -OutputDirectory ../../artifacts
-nuget pack Grpc.Tools.nuspec -Version "1.2.0-dev" -OutputDirectory ../../artifacts
+nuget pack Grpc.nuspec -Version "1.3.0-dev" -OutputDirectory ../../artifacts
+nuget pack Grpc.Tools.nuspec -Version "1.3.0-dev" -OutputDirectory ../../artifacts
(cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg)
diff --git a/src/csharp/buildall.bat b/src/csharp/buildall.bat
deleted file mode 100644
index 0beb30c198..0000000000
--- a/src/csharp/buildall.bat
+++ /dev/null
@@ -1,59 +0,0 @@
-@rem Copyright 2016, Google Inc.
-@rem All rights reserved.
-@rem
-@rem Redistribution and use in source and binary forms, with or without
-@rem modification, are permitted provided that the following conditions are
-@rem met:
-@rem
-@rem * Redistributions of source code must retain the above copyright
-@rem notice, this list of conditions and the following disclaimer.
-@rem * Redistributions in binary form must reproduce the above
-@rem copyright notice, this list of conditions and the following disclaimer
-@rem in the documentation and/or other materials provided with the
-@rem distribution.
-@rem * Neither the name of Google Inc. nor the names of its
-@rem contributors may be used to endorse or promote products derived from
-@rem this software without specific prior written permission.
-@rem
-@rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-@rem "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-@rem LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-@rem A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-@rem OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-@rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-@rem LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-@rem DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-@rem THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-@rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-@rem Convenience script to build gRPC C# from command line
-
-setlocal
-
-@rem enter this directory
-cd /d %~dp0
-
-@rem Set VS variables (uses Visual Studio 2013)
-@call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86
-
-@rem Fetch all dependencies
-nuget restore ..\..\vsprojects\grpc.sln || goto :error
-nuget restore ..\..\vsprojects\grpc_csharp_ext.sln || goto :error
-nuget restore ..\..\vsprojects\grpc_protoc_plugins.sln || goto :error
-nuget restore Grpc.sln || goto :error
-
-@rem Build the C# native extension
-msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Debug /p:PlatformToolset=v120 || goto :error
-msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Release /p:PlatformToolset=v120 || goto :error
-
-msbuild Grpc.sln /p:Configuration=Debug || goto :error
-msbuild Grpc.sln /p:Configuration=Release || goto :error
-
-endlocal
-
-goto :EOF
-
-:error
-echo Failed!
-exit /b %errorlevel%
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index 6a241190b2..491df4de6a 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -1023,6 +1023,31 @@ GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_metadata_credentials_cr
return grpc_metadata_credentials_create_from_plugin(plugin, NULL);
}
+/* Auth context */
+
+GPR_EXPORT grpc_auth_context *GPR_CALLTYPE grpcsharp_call_auth_context(grpc_call *call) {
+ return grpc_call_auth_context(call);
+}
+
+GPR_EXPORT const char *GPR_CALLTYPE grpcsharp_auth_context_peer_identity_property_name(
+ const grpc_auth_context *ctx) {
+ return grpc_auth_context_peer_identity_property_name(ctx);
+}
+
+GPR_EXPORT grpc_auth_property_iterator GPR_CALLTYPE
+grpcsharp_auth_context_property_iterator(const grpc_auth_context *ctx) {
+ return grpc_auth_context_property_iterator(ctx);
+}
+
+GPR_EXPORT const grpc_auth_property *GPR_CALLTYPE grpcsharp_auth_property_iterator_next(
+ grpc_auth_property_iterator *it) {
+ return grpc_auth_property_iterator_next(it);
+}
+
+GPR_EXPORT void GPR_CALLTYPE grpcsharp_auth_context_release(grpc_auth_context *ctx) {
+ grpc_auth_context_release(ctx);
+}
+
/* Logging */
typedef void(GPR_CALLTYPE *grpcsharp_log_func)(const char *file, int32_t line,
diff --git a/src/csharp/global.json b/src/csharp/global.json
new file mode 100644
index 0000000000..32ff399ef9
--- /dev/null
+++ b/src/csharp/global.json
@@ -0,0 +1,5 @@
+{
+ "sdk": {
+ "version": "1.0.0-preview2-003121"
+ }
+} \ No newline at end of file
diff --git a/src/csharp/tests.json b/src/csharp/tests.json
index 4ce6769eee..707d140f62 100644
--- a/src/csharp/tests.json
+++ b/src/csharp/tests.json
@@ -8,6 +8,8 @@
"Grpc.Core.Internal.Tests.MetadataArraySafeHandleTest",
"Grpc.Core.Internal.Tests.TimespecTest",
"Grpc.Core.Tests.AppDomainUnloadTest",
+ "Grpc.Core.Tests.AuthContextTest",
+ "Grpc.Core.Tests.AuthPropertyTest",
"Grpc.Core.Tests.CallCredentialsTest",
"Grpc.Core.Tests.CallOptionsTest",
"Grpc.Core.Tests.ChannelCredentialsTest",
@@ -20,7 +22,6 @@
"Grpc.Core.Tests.HalfcloseTest",
"Grpc.Core.Tests.MarshallingErrorsTest",
"Grpc.Core.Tests.MetadataTest",
- "Grpc.Core.Tests.NUnitVersionTest",
"Grpc.Core.Tests.PerformanceTest",
"Grpc.Core.Tests.PInvokeTest",
"Grpc.Core.Tests.ResponseHeadersTest",
diff --git a/src/node/ext/completion_queue_threadpool.cc b/src/node/ext/completion_queue_threadpool.cc
index 6302e7a103..1917074dc2 100644
--- a/src/node/ext/completion_queue_threadpool.cc
+++ b/src/node/ext/completion_queue_threadpool.cc
@@ -78,6 +78,8 @@ class CompletionQueueAsyncWorker : public Nan::AsyncWorker {
void HandleErrorCallback();
private:
+ static void TryAddWorker();
+
grpc_event result;
static grpc_completion_queue *queue;
@@ -118,20 +120,21 @@ void CompletionQueueAsyncWorker::Execute() {
grpc_completion_queue *CompletionQueueAsyncWorker::GetQueue() { return queue; }
-void CompletionQueueAsyncWorker::Next() {
-#ifndef GRPC_UV
- Nan::HandleScope scope;
- if (current_threads < max_queue_threads) {
+void CompletionQueueAsyncWorker::TryAddWorker() {
+ if (current_threads < max_queue_threads && waiting_next_calls > 0) {
current_threads += 1;
+ waiting_next_calls -= 1;
CompletionQueueAsyncWorker *worker = new CompletionQueueAsyncWorker();
Nan::AsyncQueueWorker(worker);
- } else {
- waiting_next_calls += 1;
}
GPR_ASSERT(current_threads <= max_queue_threads);
GPR_ASSERT((current_threads == max_queue_threads) ||
(waiting_next_calls == 0));
-#endif
+}
+
+void CompletionQueueAsyncWorker::Next() {
+ waiting_next_calls += 1;
+ TryAddWorker();
}
void CompletionQueueAsyncWorker::Init(Local<Object> exports) {
@@ -143,17 +146,8 @@ void CompletionQueueAsyncWorker::Init(Local<Object> exports) {
void CompletionQueueAsyncWorker::HandleOKCallback() {
Nan::HandleScope scope;
- if (waiting_next_calls > 0) {
- waiting_next_calls -= 1;
- // Old worker removed, new worker added. current_threads += 0
- CompletionQueueAsyncWorker *worker = new CompletionQueueAsyncWorker();
- Nan::AsyncQueueWorker(worker);
- } else {
- current_threads -= 1;
- }
- GPR_ASSERT(current_threads <= max_queue_threads);
- GPR_ASSERT((current_threads == max_queue_threads) ||
- (waiting_next_calls == 0));
+ current_threads -= 1;
+ TryAddWorker();
Nan::Callback *callback = GetTagCallback(result.tag);
Local<Value> argv[] = {Nan::Null(), GetTagNodeValue(result.tag)};
callback->Call(2, argv);
@@ -162,18 +156,9 @@ void CompletionQueueAsyncWorker::HandleOKCallback() {
}
void CompletionQueueAsyncWorker::HandleErrorCallback() {
- if (waiting_next_calls > 0) {
- waiting_next_calls -= 1;
- // Old worker removed, new worker added. current_threads += 0
- CompletionQueueAsyncWorker *worker = new CompletionQueueAsyncWorker();
- Nan::AsyncQueueWorker(worker);
- } else {
- current_threads -= 1;
- }
- GPR_ASSERT(current_threads <= max_queue_threads);
- GPR_ASSERT((current_threads == max_queue_threads) ||
- (waiting_next_calls == 0));
Nan::HandleScope scope;
+ current_threads -= 1;
+ TryAddWorker();
Nan::Callback *callback = GetTagCallback(result.tag);
Local<Value> argv[] = {Nan::Error(ErrorMessage())};
diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc
index 4761b2867d..ccb55aa54c 100644
--- a/src/node/ext/server.cc
+++ b/src/node/ext/server.cc
@@ -78,8 +78,6 @@ using v8::Value;
Nan::Callback *Server::constructor;
Persistent<FunctionTemplate> Server::fun_tpl;
-static Callback *shutdown_callback;
-
class NewCallOp : public Op {
public:
NewCallOp() {
@@ -128,51 +126,6 @@ class NewCallOp : public Op {
std::string GetTypeString() const { return "new_call"; }
};
-class ServerShutdownOp : public Op {
- public:
- ServerShutdownOp(grpc_server *server): server(server) {
- }
-
- ~ServerShutdownOp() {
- }
-
- Local<Value> GetNodeValue() const {
- return Nan::New<External>(reinterpret_cast<void *>(server));
- }
-
- bool ParseOp(Local<Value> value, grpc_op *out) {
- return true;
- }
- bool IsFinalOp() {
- return false;
- }
-
- grpc_server *server;
-
- protected:
- std::string GetTypeString() const { return "shutdown"; }
-};
-
-NAN_METHOD(ServerShutdownCallback) {
- if (!info[0]->IsNull()) {
- return Nan::ThrowError("forceShutdown failed somehow");
- }
- MaybeLocal<Object> maybe_result = Nan::To<Object>(info[1]);
- Local<Object> result = maybe_result.ToLocalChecked();
- Local<Value> server_val = Nan::Get(
- result, Nan::New("shutdown").ToLocalChecked()).ToLocalChecked();
- Local<External> server_extern = server_val.As<External>();
- grpc_server *server = reinterpret_cast<grpc_server *>(server_extern->Value());
- grpc_server_destroy(server);
-}
-
-Server::Server(grpc_server *server) : wrapped_server(server) {
-}
-
-Server::~Server() {
- this->ShutdownServer();
-}
-
void Server::Init(Local<Object> exports) {
HandleScope scope;
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
@@ -187,11 +140,6 @@ void Server::Init(Local<Object> exports) {
Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked();
Nan::Set(exports, Nan::New("Server").ToLocalChecked(), ctr);
constructor = new Callback(ctr);
-
- Local<FunctionTemplate>callback_tpl =
- Nan::New<FunctionTemplate>(ServerShutdownCallback);
- shutdown_callback = new Callback(
- Nan::GetFunction(callback_tpl).ToLocalChecked());
}
bool Server::HasInstance(Local<Value> val) {
@@ -199,21 +147,6 @@ bool Server::HasInstance(Local<Value> val) {
return Nan::New(fun_tpl)->HasInstance(val);
}
-void Server::ShutdownServer() {
- if (this->wrapped_server != NULL) {
- ServerShutdownOp *op = new ServerShutdownOp(this->wrapped_server);
- unique_ptr<OpVec> ops(new OpVec());
- ops->push_back(unique_ptr<Op>(op));
-
- grpc_server_shutdown_and_notify(
- this->wrapped_server, GetCompletionQueue(),
- new struct tag(new Callback(**shutdown_callback), ops.release(), NULL));
- grpc_server_cancel_all_calls(this->wrapped_server);
- CompletionQueueNext();
- this->wrapped_server = NULL;
- }
-}
-
NAN_METHOD(Server::New) {
/* If this is not a constructor call, make a constructor call and return
the result */
diff --git a/src/node/ext/server.h b/src/node/ext/server.h
index 9e6a7bd1e0..ab5fc210e8 100644
--- a/src/node/ext/server.h
+++ b/src/node/ext/server.h
@@ -73,6 +73,7 @@ class Server : public Nan::ObjectWrap {
static Nan::Persistent<v8::FunctionTemplate> fun_tpl;
grpc_server *wrapped_server;
+ grpc_completion_queue *shutdown_queue;
};
} // namespace node
diff --git a/src/node/ext/server_generic.cc b/src/node/ext/server_generic.cc
new file mode 100644
index 0000000000..0cf20f754a
--- /dev/null
+++ b/src/node/ext/server_generic.cc
@@ -0,0 +1,73 @@
+/*
+ *
+ * Copyright 2017, 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.
+ *
+ */
+
+#ifndef GRPC_UV
+
+#include "server.h"
+
+#include <node.h>
+#include <nan.h>
+#include "grpc/grpc.h"
+#include "grpc/support/time.h"
+
+namespace grpc {
+namespace node {
+
+Server::Server(grpc_server *server) : wrapped_server(server) {
+ shutdown_queue = grpc_completion_queue_create(NULL);
+ grpc_server_register_non_listening_completion_queue(server, shutdown_queue,
+ NULL);
+}
+
+Server::~Server() {
+ this->ShutdownServer();
+ grpc_completion_queue_shutdown(this->shutdown_queue);
+ grpc_completion_queue_destroy(this->shutdown_queue);
+}
+
+void Server::ShutdownServer() {
+ if (this->wrapped_server != NULL) {
+ grpc_server_shutdown_and_notify(this->wrapped_server, this->shutdown_queue,
+ NULL);
+ grpc_server_cancel_all_calls(this->wrapped_server);
+ grpc_completion_queue_pluck(this->shutdown_queue, NULL,
+ gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+ grpc_server_destroy(this->wrapped_server);
+ this->wrapped_server = NULL;
+ }
+}
+
+} // namespace grpc
+} // namespace node
+
+#endif /* GRPC_UV */
diff --git a/src/node/ext/server_uv.cc b/src/node/ext/server_uv.cc
new file mode 100644
index 0000000000..bf8b609a63
--- /dev/null
+++ b/src/node/ext/server_uv.cc
@@ -0,0 +1,131 @@
+/*
+ *
+ * Copyright 2017, 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.
+ *
+ */
+
+#ifdef GRPC_UV
+
+#include "server.h"
+
+#include <node.h>
+#include <nan.h>
+#include "grpc/grpc.h"
+#include "grpc/support/time.h"
+
+#include "call.h"
+#include "completion_queue.h"
+
+namespace grpc {
+namespace node {
+
+using Nan::Callback;
+
+using v8::External;
+using v8::Function;
+using v8::FunctionTemplate;
+using v8::Local;
+using v8::MaybeLocal;
+using v8::Object;
+using v8::Value;
+
+static Callback *shutdown_callback = NULL;
+
+class ServerShutdownOp : public Op {
+ public:
+ ServerShutdownOp(grpc_server *server): server(server) {
+ }
+
+ ~ServerShutdownOp() {
+ }
+
+ Local<Value> GetNodeValue() const {
+ return Nan::New<External>(reinterpret_cast<void *>(server));
+ }
+
+ bool ParseOp(Local<Value> value, grpc_op *out) {
+ return true;
+ }
+ bool IsFinalOp() {
+ return false;
+ }
+
+ grpc_server *server;
+
+ protected:
+ std::string GetTypeString() const { return "shutdown"; }
+};
+
+Server::Server(grpc_server *server) : wrapped_server(server) {
+}
+
+Server::~Server() {
+ this->ShutdownServer();
+}
+
+NAN_METHOD(ServerShutdownCallback) {
+ if (!info[0]->IsNull()) {
+ return Nan::ThrowError("forceShutdown failed somehow");
+ }
+ MaybeLocal<Object> maybe_result = Nan::To<Object>(info[1]);
+ Local<Object> result = maybe_result.ToLocalChecked();
+ Local<Value> server_val = Nan::Get(
+ result, Nan::New("shutdown").ToLocalChecked()).ToLocalChecked();
+ Local<External> server_extern = server_val.As<External>();
+ grpc_server *server = reinterpret_cast<grpc_server *>(server_extern->Value());
+ grpc_server_destroy(server);
+}
+
+void Server::ShutdownServer() {
+ if (this->wrapped_server != NULL) {
+ if (shutdown_callback == NULL) {
+ Local<FunctionTemplate>callback_tpl =
+ Nan::New<FunctionTemplate>(ServerShutdownCallback);
+ shutdown_callback = new Callback(
+ Nan::GetFunction(callback_tpl).ToLocalChecked());
+ }
+
+ ServerShutdownOp *op = new ServerShutdownOp(this->wrapped_server);
+ unique_ptr<OpVec> ops(new OpVec());
+ ops->push_back(unique_ptr<Op>(op));
+
+ grpc_server_shutdown_and_notify(
+ this->wrapped_server, GetCompletionQueue(),
+ new struct tag(new Callback(**shutdown_callback), ops.release(), NULL));
+ grpc_server_cancel_all_calls(this->wrapped_server);
+ CompletionQueueNext();
+ this->wrapped_server = NULL;
+ }
+}
+
+} // namespace grpc
+} // namespace node
+
+#endif /* GRPC_UV */
diff --git a/src/node/health_check/package.json b/src/node/health_check/package.json
index 8376339deb..e218f5a406 100644
--- a/src/node/health_check/package.json
+++ b/src/node/health_check/package.json
@@ -1,6 +1,6 @@
{
"name": "grpc-health-check",
- "version": "1.2.0-dev",
+ "version": "1.3.0-dev",
"author": "Google Inc.",
"description": "Health check service for use with gRPC",
"repository": {
@@ -15,7 +15,7 @@
}
],
"dependencies": {
- "grpc": "^1.2.0-dev",
+ "grpc": "^1.3.0-dev",
"lodash": "^3.9.3",
"google-protobuf": "^3.0.0"
},
diff --git a/src/node/src/client.js b/src/node/src/client.js
index 134ef239c2..44081a3a6c 100644
--- a/src/node/src/client.js
+++ b/src/node/src/client.js
@@ -108,7 +108,7 @@ function _write(chunk, encoding, callback) {
but passing an object that causes a serialization failure is a misuse
of the API anyway, so that's OK. The primary purpose here is to give the
programmer a useful error and to stop the stream properly */
- this.call.cancelWithStatus(grpc.status.INTERNAL, "Serialization failure");
+ this.call.cancelWithStatus(grpc.status.INTERNAL, 'Serialization failure');
callback(e);
}
if (_.isFinite(encoding)) {
@@ -831,13 +831,12 @@ exports.waitForClientReady = function(client, deadline, callback) {
*/
exports.makeProtobufClientConstructor = function(service, options) {
var method_attrs = common.getProtobufServiceAttrs(service, options);
- var deprecatedArgumentOrder = false;
- if (options) {
- deprecatedArgumentOrder = options.deprecatedArgumentOrder;
+ if (!options) {
+ options = {deprecatedArgumentOrder: false};
}
var Client = exports.makeClientConstructor(
method_attrs, common.fullyQualifiedName(service),
- deprecatedArgumentOrder);
+ options);
Client.service = service;
Client.service.grpc_options = options;
return Client;
diff --git a/src/node/src/server.js b/src/node/src/server.js
index da9c6b2d7f..a5a0ea2642 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -121,20 +121,20 @@ function sendUnaryResponse(call, value, serialize, metadata, flags) {
if (metadata) {
statusMetadata = metadata;
}
- status.metadata = statusMetadata._getCoreRepresentation();
- if (!call.metadataSent) {
- end_batch[grpc.opType.SEND_INITIAL_METADATA] =
- (new Metadata())._getCoreRepresentation();
- call.metadataSent = true;
- }
var message;
try {
message = serialize(value);
} catch (e) {
e.code = grpc.status.INTERNAL;
- handleError(e);
+ handleError(call, e);
return;
}
+ status.metadata = statusMetadata._getCoreRepresentation();
+ if (!call.metadataSent) {
+ end_batch[grpc.opType.SEND_INITIAL_METADATA] =
+ (new Metadata())._getCoreRepresentation();
+ call.metadataSent = true;
+ }
message.grpcWriteFlags = flags;
end_batch[grpc.opType.SEND_MESSAGE] = message;
end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = status;
@@ -280,11 +280,6 @@ function _write(chunk, encoding, callback) {
/* jshint validthis: true */
var batch = {};
var self = this;
- if (!this.call.metadataSent) {
- batch[grpc.opType.SEND_INITIAL_METADATA] =
- (new Metadata())._getCoreRepresentation();
- this.call.metadataSent = true;
- }
var message;
try {
message = this.serialize(chunk);
@@ -293,6 +288,11 @@ function _write(chunk, encoding, callback) {
callback(e);
return;
}
+ if (!this.call.metadataSent) {
+ batch[grpc.opType.SEND_INITIAL_METADATA] =
+ (new Metadata())._getCoreRepresentation();
+ this.call.metadataSent = true;
+ }
if (_.isFinite(encoding)) {
/* Attach the encoding if it is a finite number. This is the closest we
* can get to checking that it is valid flags */
@@ -728,11 +728,17 @@ var defaultHandler = {
* method implementation for the provided service.
*/
Server.prototype.addService = function(service, implementation) {
+ if (!_.isObject(service) || !_.isObject(implementation)) {
+ throw new Error('addService requires two objects as arguments');
+ }
+ if (_.keys(service).length === 0) {
+ throw new Error('Cannot add an empty service to a server');
+ }
if (this.started) {
throw new Error('Can\'t add a service to a started server.');
}
var self = this;
- _.each(service, function(attrs, name) {
+ _.forOwn(service, function(attrs, name) {
var method_type;
if (attrs.requestStream) {
if (attrs.responseStream) {
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index e429a3648b..2636ea85ac 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -607,6 +607,113 @@ describe('Client malformed response handling', function() {
call.end();
});
});
+describe('Server serialization failure handling', function() {
+ function serializeFail(obj) {
+ throw new Error('Serialization failed');
+ }
+ var client;
+ var server;
+ before(function() {
+ var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
+ var test_service = test_proto.lookup('TestService');
+ var malformed_test_service = {
+ unary: {
+ path: '/TestService/Unary',
+ requestStream: false,
+ responseStream: false,
+ requestDeserialize: _.identity,
+ responseSerialize: serializeFail
+ },
+ clientStream: {
+ path: '/TestService/ClientStream',
+ requestStream: true,
+ responseStream: false,
+ requestDeserialize: _.identity,
+ responseSerialize: serializeFail
+ },
+ serverStream: {
+ path: '/TestService/ServerStream',
+ requestStream: false,
+ responseStream: true,
+ requestDeserialize: _.identity,
+ responseSerialize: serializeFail
+ },
+ bidiStream: {
+ path: '/TestService/BidiStream',
+ requestStream: true,
+ responseStream: true,
+ requestDeserialize: _.identity,
+ responseSerialize: serializeFail
+ }
+ };
+ server = new grpc.Server();
+ server.addService(malformed_test_service, {
+ unary: function(call, cb) {
+ cb(null, {});
+ },
+ clientStream: function(stream, cb) {
+ stream.on('data', function() {/* Ignore requests */});
+ stream.on('end', function() {
+ cb(null, {});
+ });
+ },
+ serverStream: function(stream) {
+ stream.write({});
+ stream.end();
+ },
+ bidiStream: function(stream) {
+ stream.on('data', function() {
+ // Ignore requests
+ stream.write({});
+ });
+ stream.on('end', function() {
+ stream.end();
+ });
+ }
+ });
+ var port = server.bind('localhost:0', server_insecure_creds);
+ var Client = surface_client.makeProtobufClientConstructor(test_service);
+ client = new Client('localhost:' + port, grpc.credentials.createInsecure());
+ server.start();
+ });
+ after(function() {
+ server.forceShutdown();
+ });
+ it('should get an INTERNAL status with a unary call', function(done) {
+ client.unary({}, function(err, data) {
+ assert(err);
+ assert.strictEqual(err.code, grpc.status.INTERNAL);
+ done();
+ });
+ });
+ it('should get an INTERNAL status with a client stream call', function(done) {
+ var call = client.clientStream(function(err, data) {
+ assert(err);
+ assert.strictEqual(err.code, grpc.status.INTERNAL);
+ done();
+ });
+ call.write({});
+ call.end();
+ });
+ it('should get an INTERNAL status with a server stream call', function(done) {
+ var call = client.serverStream({});
+ call.on('data', function(){});
+ call.on('error', function(err) {
+ assert.strictEqual(err.code, grpc.status.INTERNAL);
+ done();
+ });
+ });
+ it('should get an INTERNAL status with a bidi stream call', function(done) {
+ var call = client.bidiStream();
+ call.on('data', function(){});
+ call.on('error', function(err) {
+ assert.strictEqual(err.code, grpc.status.INTERNAL);
+ done();
+ });
+ call.write({});
+ call.end();
+ });
+});
describe('Other conditions', function() {
var test_service;
var Client;
diff --git a/src/node/tools/package.json b/src/node/tools/package.json
index 53dd53f539..3096c6e42a 100644
--- a/src/node/tools/package.json
+++ b/src/node/tools/package.json
@@ -1,6 +1,6 @@
{
"name": "grpc-tools",
- "version": "1.2.0-dev",
+ "version": "1.3.0-dev",
"author": "Google Inc.",
"description": "Tools for developing with gRPC on Node.js",
"homepage": "http://www.grpc.io/",
diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
index 1a3b775c60..ab8f82a39e 100644
--- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
+++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
@@ -42,7 +42,7 @@ Pod::Spec.new do |s|
# exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
# before them.
s.name = '!ProtoCompiler-gRPCPlugin'
- v = '1.2.0-dev'
+ v = '1.3.0-dev'
s.version = v
s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.'
s.description = <<-DESC
diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h
index e569faa25b..09155ee4d4 100644
--- a/src/objective-c/GRPCClient/private/version.h
+++ b/src/objective-c/GRPCClient/private/version.h
@@ -38,4 +38,4 @@
// `tools/buildgen/generate_projects.sh`.
-#define GRPC_OBJC_VERSION_STRING @"1.2.0-dev"
+#define GRPC_OBJC_VERSION_STRING @"1.3.0-dev"
diff --git a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
index 599f840567..e97f3d2d1a 100644
--- a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
+++ b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
@@ -32,13 +32,13 @@
*/
#import <XCTest/XCTest.h>
-#import <sys/socket.h>
#import <netinet/in.h>
+#import <sys/socket.h>
#import <Cronet/Cronet.h>
-#import <grpc/support/host_port.h>
-#import <grpc/grpc_cronet.h>
#import <grpc/grpc.h>
+#import <grpc/grpc_cronet.h>
+#import <grpc/support/host_port.h>
#import "test/core/end2end/cq_verifier.h"
#import "test/core/util/port.h"
@@ -49,16 +49,19 @@
#import "src/core/lib/support/env.h"
#import "src/core/lib/support/string.h"
#import "src/core/lib/support/tmpfile.h"
+#import "test/core/end2end/data/ssl_test_data.h"
#import "test/core/util/test_config.h"
+#import <BoringSSL/openssl/ssl.h>
+
static void drain_cq(grpc_completion_queue *cq) {
grpc_event ev;
do {
- ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5), NULL);
+ ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5),
+ NULL);
} while (ev.type != GRPC_QUEUE_SHUTDOWN);
}
-
@interface CronetUnitTests : XCTestCase
@end
@@ -68,47 +71,99 @@ static void drain_cq(grpc_completion_queue *cq) {
+ (void)setUp {
[super setUp];
-/*** FILE *roots_file;
- size_t roots_size = strlen(test_root_cert);*/
-
char *argv[] = {"CoreCronetEnd2EndTests"};
grpc_test_init(1, argv);
grpc_init();
[Cronet setHttp2Enabled:YES];
+ [Cronet setSslKeyLogFileName:@"Documents/key"];
+ [Cronet enableTestCertVerifierForTesting];
NSURL *url = [[[NSFileManager defaultManager]
- URLsForDirectory:NSDocumentDirectory
- inDomains:NSUserDomainMask] lastObject];
+ URLsForDirectory:NSDocumentDirectory
+ inDomains:NSUserDomainMask] lastObject];
NSLog(@"Documents directory: %@", url);
[Cronet start];
[Cronet startNetLogToFile:@"Documents/cronet_netlog.json" logBytes:YES];
+
+ init_ssl();
}
+ (void)tearDown {
grpc_shutdown();
+ cleanup_ssl();
[super tearDown];
}
+void init_ssl(void) {
+ SSL_load_error_strings();
+ OpenSSL_add_ssl_algorithms();
+}
+
+void cleanup_ssl(void) { EVP_cleanup(); }
+
+int alpn_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen, void *arg) {
+ // Always select "h2" as the ALPN protocol to be used
+ *out = (const unsigned char *)"h2";
+ *outlen = 2;
+ return SSL_TLSEXT_ERR_OK;
+}
+
+void init_ctx(SSL_CTX *ctx) {
+ // Install server certificate
+ BIO *pem = BIO_new_mem_buf((void *)test_server1_cert,
+ (int)strlen(test_server1_cert));
+ X509 *cert = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
+ SSL_CTX_use_certificate(ctx, cert);
+ X509_free(cert);
+ BIO_free(pem);
+
+ // Install server private key
+ pem =
+ BIO_new_mem_buf((void *)test_server1_key, (int)strlen(test_server1_key));
+ EVP_PKEY *key = PEM_read_bio_PrivateKey(pem, NULL, NULL, "");
+ SSL_CTX_use_PrivateKey(ctx, key);
+ EVP_PKEY_free(key);
+ BIO_free(pem);
+
+ // Select cipher suite
+ SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-GCM-SHA256");
+
+ // Select ALPN protocol
+ SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, NULL);
+}
+
+unsigned int parse_h2_length(const char *field) {
+ return ((unsigned int)(unsigned char)(field[0])) * 65536 +
+ ((unsigned int)(unsigned char)(field[1])) * 256 +
+ ((unsigned int)(unsigned char)(field[2]));
+}
+
- (void)testInternalError {
grpc_call *c;
grpc_slice request_payload_slice =
- grpc_slice_from_copied_string("hello world");
+ grpc_slice_from_copied_string("hello world");
grpc_byte_buffer *request_payload =
- grpc_raw_byte_buffer_create(&request_payload_slice, 1);
+ grpc_raw_byte_buffer_create(&request_payload_slice, 1);
gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5);
- grpc_metadata meta_c[2] = {
- {"key1", "val1", 4, 0, {{NULL, NULL, NULL, NULL}}},
- {"key2", "val2", 4, 0, {{NULL, NULL, NULL, NULL}}}};
+ grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+ grpc_slice_from_static_string("val1"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}},
+ {grpc_slice_from_static_string("key2"),
+ grpc_slice_from_static_string("val2"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}}};
int port = grpc_pick_unused_port_or_die();
char *addr;
gpr_join_host_port(&addr, "127.0.0.1", port);
grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
- cronet_engine *cronetEngine = [Cronet getGlobalEngine];
- grpc_channel *client = grpc_cronet_secure_channel_create(cronetEngine, addr,
- NULL, NULL);
+ stream_engine *cronetEngine = [Cronet getGlobalEngine];
+ grpc_channel *client =
+ grpc_cronet_secure_channel_create(cronetEngine, addr, NULL, NULL);
cq_verifier *cqv = cq_verifier_create(cq);
grpc_op ops[6];
@@ -120,12 +175,11 @@ static void drain_cq(grpc_completion_queue *cq) {
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
- char *details = NULL;
- size_t details_capacity = 0;
+ grpc_slice details;
- c = grpc_channel_create_call(
- client, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/foo",
- NULL, deadline, NULL);
+ c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+ grpc_slice_from_static_string("/foo"), NULL,
+ deadline, NULL);
GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv);
@@ -164,35 +218,221 @@ static void drain_cq(grpc_completion_queue *cq) {
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->data.recv_status_on_client.status_details_capacity = &details_capacity;
op->flags = 0;
op->reserved = NULL;
op++;
- error = grpc_call_start_batch(c, ops, (size_t)(op - ops), (void*)1, NULL);
+ error = grpc_call_start_batch(c, ops, (size_t)(op - ops), (void *)1, NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- int sl = socket(AF_INET, SOCK_STREAM, 0);
- GPR_ASSERT(sl >= 0);
- struct sockaddr_in s_addr;
- memset(&s_addr, 0, sizeof(s_addr));
- s_addr.sin_family = AF_INET;
- s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- s_addr.sin_port = htons(port);
- bind(sl, (struct sockaddr*)&s_addr, sizeof(s_addr));
- listen(sl, 5);
- int s = accept(sl, NULL, NULL);
- sleep(1);
- close(s);
- close(sl);
- });
-
- CQ_EXPECT_COMPLETION(cqv, (void*)1, 1);
+ dispatch_async(
+ dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ int sl = socket(AF_INET, SOCK_STREAM, 0);
+ GPR_ASSERT(sl >= 0);
+
+ // Make and TCP endpoint to accept the connection
+ struct sockaddr_in s_addr;
+ memset(&s_addr, 0, sizeof(s_addr));
+ s_addr.sin_family = AF_INET;
+ s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ s_addr.sin_port = htons(port);
+ GPR_ASSERT(0 == bind(sl, (struct sockaddr *)&s_addr, sizeof(s_addr)));
+ GPR_ASSERT(0 == listen(sl, 5));
+ int s = accept(sl, NULL, NULL);
+ GPR_ASSERT(s >= 0);
+
+ // Close the connection after 1 second to trigger Cronet's on_failed()
+ sleep(1);
+ close(s);
+ close(sl);
+ });
+
+ CQ_EXPECT_COMPLETION(cqv, (void *)1, 1);
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
- gpr_free(details);
+ 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_destroy(c);
+
+ cq_verifier_destroy(cqv);
+
+ grpc_byte_buffer_destroy(request_payload);
+ grpc_byte_buffer_destroy(response_payload_recv);
+
+ grpc_channel_destroy(client);
+ grpc_completion_queue_shutdown(cq);
+ drain_cq(cq);
+ grpc_completion_queue_destroy(cq);
+}
+
+- (void)packetCoalescing:(BOOL)useCoalescing {
+ grpc_arg arg;
+ arg.key = GRPC_ARG_USE_CRONET_PACKET_COALESCING;
+ arg.type = GRPC_ARG_INTEGER;
+ arg.value.integer = useCoalescing ? 1 : 0;
+ grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1);
+ grpc_call *c;
+ grpc_slice request_payload_slice =
+ grpc_slice_from_copied_string("hello world");
+ grpc_byte_buffer *request_payload =
+ grpc_raw_byte_buffer_create(&request_payload_slice, 1);
+ gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5);
+ grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
+ grpc_slice_from_static_string("val1"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}},
+ {grpc_slice_from_static_string("key2"),
+ grpc_slice_from_static_string("val2"),
+ 0,
+ {{NULL, NULL, NULL, NULL}}}};
+
+ int port = grpc_pick_unused_port_or_die();
+ char *addr;
+ gpr_join_host_port(&addr, "127.0.0.1", port);
+ grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
+ stream_engine *cronetEngine = [Cronet getGlobalEngine];
+ grpc_channel *client =
+ grpc_cronet_secure_channel_create(cronetEngine, addr, args, NULL);
+
+ cq_verifier *cqv = cq_verifier_create(cq);
+ grpc_op ops[6];
+ grpc_op *op;
+ grpc_metadata_array initial_metadata_recv;
+ grpc_metadata_array trailing_metadata_recv;
+ grpc_metadata_array request_metadata_recv;
+ grpc_byte_buffer *response_payload_recv = NULL;
+ grpc_call_details call_details;
+ grpc_status_code status;
+ grpc_call_error error;
+ grpc_slice details;
+
+ c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+ grpc_slice_from_static_string("/foo"), NULL,
+ deadline, NULL);
+ 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);
+
+ __weak XCTestExpectation *expectation =
+ [self expectationWithDescription:@"Coalescing"];
+
+ dispatch_async(
+ dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ int sl = socket(AF_INET, SOCK_STREAM, 0);
+ GPR_ASSERT(sl >= 0);
+ struct sockaddr_in s_addr;
+ memset(&s_addr, 0, sizeof(s_addr));
+ s_addr.sin_family = AF_INET;
+ s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ s_addr.sin_port = htons(port);
+ GPR_ASSERT(0 == bind(sl, (struct sockaddr *)&s_addr, sizeof(s_addr)));
+ GPR_ASSERT(0 == listen(sl, 5));
+ int s = accept(sl, NULL, NULL);
+ GPR_ASSERT(s >= 0);
+ struct timeval tv;
+ tv.tv_sec = 2;
+ tv.tv_usec = 0;
+ setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+
+ // Make an TLS endpoint to receive Cronet's transmission
+ SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_server_method());
+ init_ctx(ctx);
+ SSL *ssl = SSL_new(ctx);
+ SSL_set_fd(ssl, s);
+ SSL_accept(ssl);
+
+ const char magic[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
+
+ char buf[4096];
+ long len;
+ BOOL coalesced = NO;
+ while ((len = SSL_read(ssl, buf, sizeof(buf))) > 0) {
+ gpr_log(GPR_DEBUG, "Read len: %ld", len);
+
+ // Analyze the HTTP/2 frames in the same TLS PDU to identify if
+ // coalescing is successful
+ unsigned int p = 0;
+ while (p < len) {
+ if (len - p >= 24 && 0 == memcmp(&buf[p], magic, 24)) {
+ p += 24;
+ continue;
+ }
+
+ if (buf[p + 3] == 0 && // Type is DATA
+ parse_h2_length(&buf[p]) == 0x10 && // Length is correct
+ (buf[p + 4] & 1) != 0 && // EOS bit is set
+ 0 == memcmp("hello world", &buf[p + 14],
+ 11)) { // Message is correct
+ coalesced = YES;
+ break;
+ }
+ p += (parse_h2_length(&buf[p]) + 9);
+ }
+ if (coalesced) {
+ break;
+ }
+ }
+
+ XCTAssert(coalesced == useCoalescing);
+ SSL_free(ssl);
+ SSL_CTX_free(ctx);
+ close(s);
+ close(sl);
+ [expectation fulfill];
+ });
+
+ // Guarantees that server is listening to the port before client connects.
+ sleep(1);
+
+ memset(ops, 0, sizeof(ops));
+ op = ops;
+ op->op = GRPC_OP_SEND_INITIAL_METADATA;
+ op->data.send_initial_metadata.count = 2;
+ op->data.send_initial_metadata.metadata = meta_c;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_SEND_MESSAGE;
+ op->data.send_message.send_message = request_payload;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_RECV_INITIAL_METADATA;
+ op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
+ op->flags = 0;
+ op->reserved = NULL;
+ op++;
+ op->op = GRPC_OP_RECV_MESSAGE;
+ op->data.recv_message.recv_message = &response_payload_recv;
+ op->flags = 0;
+ op->reserved = NULL;
+ 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 = NULL;
+ op++;
+ error = grpc_call_start_batch(c, ops, (size_t)(op - ops), (void *)1, NULL);
+ GPR_ASSERT(GRPC_CALL_OK == error);
+
+ CQ_EXPECT_COMPLETION(cqv, (void *)1, 1);
+ cq_verify(cqv);
+
+ 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);
@@ -204,11 +444,18 @@ static void drain_cq(grpc_completion_queue *cq) {
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload_recv);
-
+
grpc_channel_destroy(client);
grpc_completion_queue_shutdown(cq);
drain_cq(cq);
grpc_completion_queue_destroy(cq);
+
+ [self waitForExpectationsWithTimeout:4 handler:nil];
+}
+
+- (void)testPacketCoalescing {
+ [self packetCoalescing:YES];
+ [self packetCoalescing:NO];
}
@end
diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m
index c9941fd37d..9105356869 100644
--- a/src/objective-c/tests/InteropTests.m
+++ b/src/objective-c/tests/InteropTests.m
@@ -93,6 +93,9 @@
return nil;
}
+// This number indicates how many bytes of overhead does Protocol Buffers encoding add onto the
+// message. The number varies as different message.proto is used on different servers. The actual
+// number for each interop server is overridden in corresponding derived test classes.
- (int32_t)encodingOverhead {
return 0;
}
@@ -356,8 +359,6 @@
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
}
-#ifndef GRPC_COMPILE_WITH_CRONET
-// TODO(makdharma@): Fix this test
- (void)testEmptyStreamRPC {
XCTAssertNotNil(self.class.host);
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"];
@@ -371,7 +372,6 @@
}];
[self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
}
-#endif
- (void)testCancelAfterBeginRPC {
XCTAssertNotNil(self.class.host);
diff --git a/src/objective-c/tests/InteropTestsLocalCleartext.m b/src/objective-c/tests/InteropTestsLocalCleartext.m
index 0b8a0e4775..94cdf85965 100644
--- a/src/objective-c/tests/InteropTestsLocalCleartext.m
+++ b/src/objective-c/tests/InteropTestsLocalCleartext.m
@@ -38,6 +38,10 @@
static NSString * const kLocalCleartextHost = @"localhost:5050";
+// The Protocol Buffers encoding overhead of local interop server. Acquired
+// by experiment. Adjust this when server's proto file changes.
+static int32_t kLocalInteropServerOverhead = 10;
+
/** Tests in InteropTests.m, sending the RPCs to a local cleartext server. */
@interface InteropTestsLocalCleartext : InteropTests
@end
@@ -49,7 +53,7 @@ static NSString * const kLocalCleartextHost = @"localhost:5050";
}
- (int32_t)encodingOverhead {
- return 10; // bytes
+ return kLocalInteropServerOverhead; // bytes
}
- (void)setUp {
diff --git a/src/objective-c/tests/InteropTestsLocalSSL.m b/src/objective-c/tests/InteropTestsLocalSSL.m
index d974c2db27..3c78b65ede 100644
--- a/src/objective-c/tests/InteropTestsLocalSSL.m
+++ b/src/objective-c/tests/InteropTestsLocalSSL.m
@@ -38,6 +38,10 @@
static NSString * const kLocalSSLHost = @"localhost:5051";
+// The Protocol Buffers encoding overhead of local interop server. Acquired
+// by experiment. Adjust this when server's proto file changes.
+static int32_t kLocalInteropServerOverhead = 10;
+
/** Tests in InteropTests.m, sending the RPCs to a local SSL server. */
@interface InteropTestsLocalSSL : InteropTests
@end
@@ -49,7 +53,7 @@ static NSString * const kLocalSSLHost = @"localhost:5051";
}
- (int32_t)encodingOverhead {
- return 10; // bytes
+ return kLocalInteropServerOverhead; // bytes
}
- (void)setUp {
diff --git a/src/objective-c/tests/InteropTestsRemote.m b/src/objective-c/tests/InteropTestsRemote.m
index ad7efebc81..ff1193302b 100644
--- a/src/objective-c/tests/InteropTestsRemote.m
+++ b/src/objective-c/tests/InteropTestsRemote.m
@@ -38,6 +38,10 @@
static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com";
+// The Protocol Buffers encoding overhead of remote interop server. Acquired
+// by experiment. Adjust this when server's proto file changes.
+static int32_t kRemoteInteropServerOverhead = 12;
+
/** Tests in InteropTests.m, sending the RPCs to a remote SSL server. */
@interface InteropTestsRemote : InteropTests
@end
@@ -49,7 +53,7 @@ static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com";
}
- (int32_t)encodingOverhead {
- return 12; // bytes
+ return kRemoteInteropServerOverhead; // bytes
}
@end
diff --git a/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m b/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m
index a6720e41dc..9edfbc2639 100644
--- a/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m
+++ b/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m
@@ -41,6 +41,10 @@
static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com";
+// The Protocol Buffers encoding overhead of remote interop server. Acquired
+// by experiment. Adjust this when server's proto file changes.
+static int32_t kRemoteInteropServerOverhead = 12;
+
/** Tests in InteropTests.m, sending the RPCs to a remote SSL server. */
@interface InteropTestsRemoteWithCronet : InteropTests
@end
@@ -51,4 +55,8 @@ static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com";
return kRemoteSSLHost;
}
+- (int32_t)encodingOverhead {
+ return kRemoteInteropServerOverhead; // bytes
+}
+
@end
diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme
index 7575609dd7..01eb70707f 100644
--- a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme
+++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme
@@ -59,6 +59,16 @@
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
</TestableReference>
+ <TestableReference
+ skipped = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "5EAD6D231E27047400002378"
+ BuildableName = "CronetUnitTests.xctest"
+ BlueprintName = "CronetUnitTests"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
@@ -100,6 +110,15 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "63423F431B150A5F006CF63C"
+ BuildableName = "AllTests.xctest"
+ BlueprintName = "AllTests"
+ ReferencedContainer = "container:Tests.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Test">
diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh
index 81c2885320..677459e082 100755
--- a/src/objective-c/tests/run_tests.sh
+++ b/src/objective-c/tests/run_tests.sh
@@ -61,3 +61,11 @@ xcodebuild \
test \
| egrep "$XCODEBUILD_FILTER" \
| egrep -v "(GPBDictionary|GPBArray)" -
+
+xcodebuild \
+ -workspace Tests.xcworkspace \
+ -scheme InteropTestsRemoteWithCronet \
+ -destination name="iPhone 6" \
+ test \
+ | egrep "$XCODEBUILD_FILTER" \
+ | egrep -v "(GPBDictionary|GPBArray)" -
diff --git a/src/php/README.md b/src/php/README.md
index ed91d2fbe5..f08541f16c 100644
--- a/src/php/README.md
+++ b/src/php/README.md
@@ -13,12 +13,24 @@ shared C library.
* `phpunit` (optional)
**Install PHP and PECL on Ubuntu/Debian:**
+
+For PHP5:
+
```sh
-$ sudo apt-get install php5 php5-dev php-pear
+$ sudo apt-get install php5 php5-dev php-pear phpunit
+```
-OR
+For PHP7:
+
+```sh
+$ sudo apt-get install php7.0 php7.0-dev php-pear phpunit
+```
-$ sudo apt-get install php7.0 php7.0-dev php-pear
+**Install PHP and PECL on CentOS/RHEL 7:**
+```sh
+$ sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
+$ sudo rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
+$ sudo yum install php56w php56w-devel php-pear phpunit gcc zlib-devel
```
**Install PECL on Mac:**
@@ -52,6 +64,10 @@ This will compile and install the gRPC PHP extension into the standard PHP
extension directory. You should be able to run the [unit tests](#unit-tests),
with the PHP extension installed.
+Note: For users on CentOS/RHEL 6, unfortunately this step won't work. Please
+follow the instructions below to compile the extension from source.
+
+
**Update php.ini**
Add this line to your `php.ini` file, e.g. `/etc/php5/cli/php.ini`
@@ -142,7 +158,7 @@ $ composer install
### Protobuf compiler
Again if you don't have it already, you need to install the protobuf compiler
-`protoc`, version 3.2.0+.
+`protoc`, version 3.1.0+ (the newer the better).
If `protoc` hasn't been installed, you can download the `protoc` binaries from
[the protocol buffers Github repository](https://github.com/google/protobuf/releases).
diff --git a/src/php/composer.json b/src/php/composer.json
index 8528304c81..2b140077cc 100644
--- a/src/php/composer.json
+++ b/src/php/composer.json
@@ -2,10 +2,10 @@
"name": "grpc/grpc-dev",
"description": "gRPC library for PHP - for Developement use only",
"license": "BSD-3-Clause",
- "version": "1.2.0",
+ "version": "1.3.0",
"require": {
"php": ">=5.5.0",
- "google/protobuf": "v3.1.0"
+ "google/protobuf": "^v3.1.0"
},
"require-dev": {
"google/auth": "v0.9"
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index be071903d0..48a374fa08 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -104,7 +104,8 @@ zval *grpc_parse_metadata_array(grpc_metadata_array
str_key = ecalloc(key_len + 1, sizeof(char));
memcpy(str_key, GRPC_SLICE_START_PTR(elem->key), key_len);
str_val = ecalloc(GRPC_SLICE_LENGTH(elem->value) + 1, sizeof(char));
- memcpy(str_val, GRPC_SLICE_START_PTR(elem->value), GRPC_SLICE_LENGTH(elem->value));
+ memcpy(str_val, GRPC_SLICE_START_PTR(elem->value),
+ GRPC_SLICE_LENGTH(elem->value));
if (php_grpc_zend_hash_find(array_hash, str_key, key_len, (void **)&data)
== SUCCESS) {
if (Z_TYPE_P(data) != IS_ARRAY) {
@@ -115,7 +116,8 @@ zval *grpc_parse_metadata_array(grpc_metadata_array
efree(str_val);
return NULL;
}
- php_grpc_add_next_index_stringl(data, str_val, GRPC_SLICE_LENGTH(elem->value),
+ php_grpc_add_next_index_stringl(data, str_val,
+ GRPC_SLICE_LENGTH(elem->value),
false);
} else {
PHP_GRPC_MAKE_STD_ZVAL(inner_array);
@@ -172,8 +174,10 @@ bool create_metadata_array(zval *array, grpc_metadata_array *metadata) {
if (Z_TYPE_P(value) != IS_STRING) {
return false;
}
- metadata->metadata[metadata->count].key = grpc_slice_from_copied_string(key1);
- metadata->metadata[metadata->count].value = grpc_slice_from_copied_buffer(Z_STRVAL_P(value), Z_STRLEN_P(value));
+ metadata->metadata[metadata->count].key =
+ grpc_slice_from_copied_string(key1);
+ metadata->metadata[metadata->count].value =
+ grpc_slice_from_copied_buffer(Z_STRVAL_P(value), Z_STRLEN_P(value));
metadata->count += 1;
PHP_GRPC_HASH_FOREACH_END()
PHP_GRPC_HASH_FOREACH_END()
@@ -233,7 +237,8 @@ PHP_METHOD(Call, __construct) {
grpc_slice_from_copied_string(host_override) : grpc_empty_slice();
call->wrapped =
grpc_channel_create_call(channel->wrapped, NULL, GRPC_PROPAGATE_DEFAULTS,
- completion_queue, method_slice, host_override != NULL ? &host_slice : NULL,
+ completion_queue, method_slice,
+ host_override != NULL ? &host_slice : NULL,
deadline->wrapped, NULL);
grpc_slice_unref(method_slice);
grpc_slice_unref(host_slice);
@@ -384,8 +389,10 @@ PHP_METHOD(Call, startBatch) {
1 TSRMLS_CC);
goto cleanup;
}
- send_status_details = grpc_slice_from_copied_string(Z_STRVAL_P(inner_value));
- ops[op_num].data.send_status_from_server.status_details = &send_status_details;
+ send_status_details = grpc_slice_from_copied_string(
+ Z_STRVAL_P(inner_value));
+ ops[op_num].data.send_status_from_server.status_details =
+ &send_status_details;
} else {
zend_throw_exception(spl_ce_InvalidArgumentException,
"String status details is required",
@@ -557,12 +564,33 @@ PHP_METHOD(Call, setCredentials) {
RETURN_LONG(error);
}
+ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 3)
+ ZEND_ARG_INFO(0, channel)
+ ZEND_ARG_INFO(0, method)
+ ZEND_ARG_INFO(0, deadline)
+ ZEND_ARG_INFO(0, host_override)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_startBatch, 0, 0, 1)
+ ZEND_ARG_INFO(0, ops)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getPeer, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_cancel, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_setCredentials, 0, 0, 1)
+ ZEND_ARG_INFO(0, credentials)
+ZEND_END_ARG_INFO()
+
static zend_function_entry call_methods[] = {
- PHP_ME(Call, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
- PHP_ME(Call, startBatch, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Call, getPeer, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Call, cancel, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Call, setCredentials, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Call, __construct, arginfo_construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
+ PHP_ME(Call, startBatch, arginfo_startBatch, ZEND_ACC_PUBLIC)
+ PHP_ME(Call, getPeer, arginfo_getPeer, ZEND_ACC_PUBLIC)
+ PHP_ME(Call, cancel, arginfo_cancel, ZEND_ACC_PUBLIC)
+ PHP_ME(Call, setCredentials, arginfo_setCredentials, ZEND_ACC_PUBLIC)
PHP_FE_END
};
diff --git a/src/php/ext/grpc/call_credentials.c b/src/php/ext/grpc/call_credentials.c
index 043817facd..625c0c62ae 100644
--- a/src/php/ext/grpc/call_credentials.c
+++ b/src/php/ext/grpc/call_credentials.c
@@ -212,10 +212,19 @@ void plugin_destroy_state(void *ptr) {
efree(state);
}
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createComposite, 0, 0, 2)
+ ZEND_ARG_INFO(0, creds1)
+ ZEND_ARG_INFO(0, creds2)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createFromPlugin, 0, 0, 1)
+ ZEND_ARG_INFO(0, callback)
+ZEND_END_ARG_INFO()
+
static zend_function_entry call_credentials_methods[] = {
- PHP_ME(CallCredentials, createComposite, NULL,
+ PHP_ME(CallCredentials, createComposite, arginfo_createComposite,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(CallCredentials, createFromPlugin, NULL,
+ PHP_ME(CallCredentials, createFromPlugin, arginfo_createFromPlugin,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_FE_END
};
diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c
index 4ce4f307b0..c26fe4a6fb 100644
--- a/src/php/ext/grpc/channel.c
+++ b/src/php/ext/grpc/channel.c
@@ -243,12 +243,37 @@ PHP_METHOD(Channel, close) {
}
}
+ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2)
+ ZEND_ARG_INFO(0, target)
+ ZEND_ARG_INFO(0, args)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getTarget, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getConnectivityState, 0, 0, 0)
+ ZEND_ARG_INFO(0, try_to_connect)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_watchConnectivityState, 0, 0, 2)
+ ZEND_ARG_INFO(0, last_state)
+ ZEND_ARG_INFO(0, deadline)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_close, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
static zend_function_entry channel_methods[] = {
- PHP_ME(Channel, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
- PHP_ME(Channel, getTarget, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Channel, getConnectivityState, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Channel, watchConnectivityState, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Channel, close, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Channel, __construct, arginfo_construct,
+ ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
+ PHP_ME(Channel, getTarget, arginfo_getTarget,
+ ZEND_ACC_PUBLIC)
+ PHP_ME(Channel, getConnectivityState, arginfo_getConnectivityState,
+ ZEND_ACC_PUBLIC)
+ PHP_ME(Channel, watchConnectivityState, arginfo_watchConnectivityState,
+ ZEND_ACC_PUBLIC)
+ PHP_ME(Channel, close, arginfo_close,
+ ZEND_ACC_PUBLIC)
PHP_FE_END
};
diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c
index 36a8223b88..2160a548c3 100644
--- a/src/php/ext/grpc/channel_credentials.c
+++ b/src/php/ext/grpc/channel_credentials.c
@@ -199,16 +199,37 @@ PHP_METHOD(ChannelCredentials, createInsecure) {
RETURN_NULL();
}
+ZEND_BEGIN_ARG_INFO_EX(arginfo_setDefaultRootsPem, 0, 0, 1)
+ ZEND_ARG_INFO(0, pem_roots)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createDefault, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createSsl, 0, 0, 0)
+ ZEND_ARG_INFO(0, pem_root_certs)
+ ZEND_ARG_INFO(0, pem_private_key)
+ ZEND_ARG_INFO(0, pem_cert_chain)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createComposite, 0, 0, 2)
+ ZEND_ARG_INFO(0, channel_creds)
+ ZEND_ARG_INFO(0, call_creds)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createInsecure, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
static zend_function_entry channel_credentials_methods[] = {
- PHP_ME(ChannelCredentials, setDefaultRootsPem, NULL,
+ PHP_ME(ChannelCredentials, setDefaultRootsPem, arginfo_setDefaultRootsPem,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(ChannelCredentials, createDefault, NULL,
+ PHP_ME(ChannelCredentials, createDefault, arginfo_createDefault,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(ChannelCredentials, createSsl, NULL,
+ PHP_ME(ChannelCredentials, createSsl, arginfo_createSsl,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(ChannelCredentials, createComposite, NULL,
+ PHP_ME(ChannelCredentials, createComposite, arginfo_createComposite,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(ChannelCredentials, createInsecure, NULL,
+ PHP_ME(ChannelCredentials, createInsecure, arginfo_createInsecure,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_FE_END
};
diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c
index 9ac5d2a3c3..87780e997e 100644
--- a/src/php/ext/grpc/server.c
+++ b/src/php/ext/grpc/server.c
@@ -116,8 +116,6 @@ PHP_METHOD(Server, __construct) {
/**
* Request a call on a server. Creates a single GRPC_SERVER_RPC_NEW event.
- * @param long $tag_new The tag to associate with the new request
- * @param long $tag_cancel The tag to use if the call is cancelled
* @return void
*/
PHP_METHOD(Server, requestCall) {
@@ -239,12 +237,36 @@ PHP_METHOD(Server, start) {
grpc_server_start(server->wrapped);
}
+ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 0)
+ ZEND_ARG_INFO(0, args)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_requestCall, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_addHttp2Port, 0, 0, 1)
+ ZEND_ARG_INFO(0, addr)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_addSecureHttp2Port, 0, 0, 2)
+ ZEND_ARG_INFO(0, addr)
+ ZEND_ARG_INFO(0, server_creds)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_start, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
static zend_function_entry server_methods[] = {
- PHP_ME(Server, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
- PHP_ME(Server, requestCall, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Server, addHttp2Port, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Server, addSecureHttp2Port, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Server, start, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(Server, __construct, arginfo_construct,
+ ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
+ PHP_ME(Server, requestCall, arginfo_requestCall,
+ ZEND_ACC_PUBLIC)
+ PHP_ME(Server, addHttp2Port, arginfo_addHttp2Port,
+ ZEND_ACC_PUBLIC)
+ PHP_ME(Server, addSecureHttp2Port, arginfo_addSecureHttp2Port,
+ ZEND_ACC_PUBLIC)
+ PHP_ME(Server, start, arginfo_start,
+ ZEND_ACC_PUBLIC)
PHP_FE_END
};
diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c
index 3e39fee246..ec29dfdc7c 100644
--- a/src/php/ext/grpc/server_credentials.c
+++ b/src/php/ext/grpc/server_credentials.c
@@ -117,8 +117,14 @@ PHP_METHOD(ServerCredentials, createSsl) {
RETURN_DESTROY_ZVAL(creds_object);
}
+ZEND_BEGIN_ARG_INFO_EX(arginfo_createSsl, 0, 0, 3)
+ ZEND_ARG_INFO(0, pem_root_certs)
+ ZEND_ARG_INFO(0, pem_private_key)
+ ZEND_ARG_INFO(0, pem_cert_chain)
+ZEND_END_ARG_INFO()
+
static zend_function_entry server_credentials_methods[] = {
- PHP_ME(ServerCredentials, createSsl, NULL,
+ PHP_ME(ServerCredentials, createSsl, arginfo_createSsl,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_FE_END
};
diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c
index 7ada915aad..78c29e385b 100644
--- a/src/php/ext/grpc/timeval.c
+++ b/src/php/ext/grpc/timeval.c
@@ -245,17 +245,65 @@ PHP_METHOD(Timeval, sleepUntil) {
gpr_sleep_until(this->wrapped);
}
+ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 1)
+ ZEND_ARG_INFO(0, microseconds)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_add, 0, 0, 1)
+ ZEND_ARG_INFO(0, timeval)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_compare, 0, 0, 2)
+ ZEND_ARG_INFO(0, a_timeval)
+ ZEND_ARG_INFO(0, b_timeval)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_infFuture, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_infPast, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_now, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_similar, 0, 0, 3)
+ ZEND_ARG_INFO(0, a_timeval)
+ ZEND_ARG_INFO(0, b_timeval)
+ ZEND_ARG_INFO(0, threshold_timeval)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sleepUntil, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_subtract, 0, 0, 1)
+ ZEND_ARG_INFO(0, timeval)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zero, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
static zend_function_entry timeval_methods[] = {
- PHP_ME(Timeval, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
- PHP_ME(Timeval, add, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Timeval, compare, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Timeval, infFuture, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Timeval, infPast, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Timeval, now, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Timeval, similar, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
- PHP_ME(Timeval, sleepUntil, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Timeval, subtract, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(Timeval, zero, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Timeval, __construct, arginfo_construct,
+ ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
+ PHP_ME(Timeval, add, arginfo_add,
+ ZEND_ACC_PUBLIC)
+ PHP_ME(Timeval, compare, arginfo_compare,
+ ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Timeval, infFuture, arginfo_infFuture,
+ ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Timeval, infPast, arginfo_infPast,
+ ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Timeval, now, arginfo_now,
+ ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Timeval, similar, arginfo_similar,
+ ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+ PHP_ME(Timeval, sleepUntil, arginfo_sleepUntil,
+ ZEND_ACC_PUBLIC)
+ PHP_ME(Timeval, subtract, arginfo_subtract,
+ ZEND_ACC_PUBLIC)
+ PHP_ME(Timeval, zero, arginfo_zero,
+ ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_FE_END
};
diff --git a/src/php/tests/qps/client.php b/src/php/tests/qps/client.php
new file mode 100644
index 0000000000..d9ca35ba43
--- /dev/null
+++ b/src/php/tests/qps/client.php
@@ -0,0 +1,166 @@
+<?php
+/*
+ *
+ * Copyright 2017, 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.
+ *
+ */
+
+/*
+ * PHP client for QPS testing works as follows:
+ * 1. Gets initiated by a call from a proxy that implements the worker service. The
+ * argument to this client is the proxy connection information
+ * 2. Initiate an RPC to the proxy to get ClientConfig
+ * 3. Initiate a client-side telemetry RPC to the proxy
+ * 4. Parse the client config, which includes server target information and then start
+ * a unary or streaming test as appropriate.
+ * 5. After each completed RPC, send its timing to the proxy. The proxy does all histogramming
+ * 6. Proxy will respond on the timing channel when it's time to complete. Our
+ * next timing write will fail and we know that it's time to stop
+ * The above complex dance is since threading and async are not idiomatic and we
+ * shouldn't ever be waiting to read a mark
+ *
+ * This test only supports a single channel since threading/async is not idiomatic
+ * This test supports unary or streaming ping-pongs, as well as open-loop
+ *
+ */
+
+require dirname(__FILE__).'/vendor/autoload.php';
+
+/**
+ * Assertion function that always exits with an error code if the assertion is
+ * falsy.
+ *
+ * @param $value Assertion value. Should be true.
+ * @param $error_message Message to display if the assertion is false
+ */
+function hardAssert($value, $error_message)
+{
+ if (!$value) {
+ echo $error_message."\n";
+ exit(1);
+ }
+}
+
+function hardAssertIfStatusOk($status)
+{
+ if ($status->code !== Grpc\STATUS_OK) {
+ echo "Call did not complete successfully. Status object:\n";
+ var_dump($status);
+ exit(1);
+ }
+}
+
+/* Start the actual client */
+
+function qps_client_main($proxy_address) {
+ echo "Initiating php client\n";
+
+ $proxystubopts = [];
+ $proxystubopts['credentials'] = Grpc\ChannelCredentials::createInsecure();
+ $proxystub = new Grpc\Testing\ProxyClientServiceClient($proxy_address, $proxystubopts);
+ list($config, $status) = $proxystub->GetConfig(new Grpc\Testing\Void())->wait();
+ hardAssertIfStatusOk($status);
+ hardAssert($config->getClientChannels() == 1, "Only 1 channel supported");
+ hardAssert($config->getOutstandingRpcsPerChannel() == 1, "Only 1 outstanding RPC supported");
+
+ echo "Got configuration from proxy, target is " . $config->getServerTargets()[0] . "\n";
+
+ $stubopts = [];
+ if ($config->getSecurityParams()) {
+ if ($config->getSecurityParams()->getUseTestCa()) {
+ $stubopts['credentials'] = Grpc\ChannelCredentials::createSsl(
+ file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
+ } else {
+ $stubopts['credentials'] = Grpc\ChannelCredentials::createSsl(null);
+ }
+ $override = $config->getSecurityParams()->getServerHostOverride();
+ if ($override) {
+ $stubopts['grpc.ssl_target_name_override'] = $override;
+ $stubopts['grpc.default_authority'] = $override;
+ }
+ } else {
+ $stubopts['credentials'] = Grpc\ChannelCredentials::createInsecure();
+ }
+ echo "Initiating php benchmarking client\n";
+
+ $stub = new Grpc\Testing\BenchmarkServiceClient(
+ $config->getServerTargets()[0], $stubopts);
+ $req = new Grpc\Testing\SimpleRequest();
+
+ $req->setResponseType(Grpc\Testing\PayloadType::COMPRESSABLE);
+ $req->setResponseSize($config->getPayloadConfig()->getSimpleParams()->getRespSize());
+ $payload = new Grpc\Testing\Payload();
+ $payload->setType(Grpc\Testing\PayloadType::COMPRESSABLE);
+ $payload->setBody(str_repeat("\0", $config->getPayloadConfig()->getSimpleParams()->getReqSize()));
+ $req->setPayload($payload);
+
+ /* TODO(stanley-cheung): Enable the following by removing the 0&& once protobuf
+ * properly supports oneof in PHP */
+ if (0 && $config->getLoadParams()->getLoad() == "poisson") {
+ $poisson = true;
+ $lamrecip = 1.0/($config->getLoadParams()->getPoisson()->getOfferedLoad());
+ $issue = microtime(true) + $lamrecip * -log(1.0-rand()/(getrandmax()+1));
+ } else {
+ $poisson = false;
+ }
+ $metric = new Grpc\Testing\ProxyStat;
+ $telemetry = $proxystub->ReportTime();
+ if ($config->getRpcType() == Grpc\Testing\RpcType::UNARY) {
+ while (1) {
+ if ($poisson) {
+ time_sleep_until($issue);
+ $issue = $issue + $lamrecip * -log(1.0-rand()/(getrandmax()+1));
+ }
+ $startreq = microtime(true);
+ list($resp,$status) = $stub->UnaryCall($req)->wait();
+ hardAssertIfStatusOk($status);
+ $metric->setLatency(microtime(true)-$startreq);
+ $telemetry->write($metric);
+ }
+ } else {
+ $stream = $stub->StreamingCall();
+ while (1) {
+ if ($poisson) {
+ time_sleep_until($issue);
+ $issue = $issue + $lamrecip * -log(1.0-rand()/(getrandmax()+1));
+ }
+ $startreq = microtime(true);
+ $stream->write($req);
+ $resp = $stream->read();
+ $metric->setLatency(microtime(true)-$startreq);
+ $telemetry->write($metric);
+ }
+ }
+}
+
+ini_set('display_startup_errors', 1);
+ini_set('display_errors', 1);
+error_reporting(-1);
+qps_client_main($argv[1]);
diff --git a/src/php/tests/qps/composer.json b/src/php/tests/qps/composer.json
new file mode 100644
index 0000000000..0fc87098f5
--- /dev/null
+++ b/src/php/tests/qps/composer.json
@@ -0,0 +1,11 @@
+{
+ "minimum-stability": "dev",
+ "require": {
+ "grpc/grpc": "dev-master"
+ },
+ "autoload": {
+ "psr-4": {
+ "": "generated_code/"
+ }
+ }
+}
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Control.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Control.php
new file mode 100644
index 0000000000..efca18a0cb
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Control.php
@@ -0,0 +1,127 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class Control
+{
+ public static $is_initialized = false;
+
+ public static function initOnce() {
+ $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+ if (static::$is_initialized == true) {
+ return;
+ }
+ \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce();
+ \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
+ $pool->internalAddGeneratedFile(hex2bin(
+ "0add170a247372632f70726f746f2f677270632f74657374696e672f636f" .
+ "6e74726f6c2e70726f746f120c677270632e74657374696e671a25737263" .
+ "2f70726f746f2f677270632f74657374696e672f7061796c6f6164732e70" .
+ "726f746f1a227372632f70726f746f2f677270632f74657374696e672f73" .
+ "746174732e70726f746f22250a0d506f6973736f6e506172616d7312140a" .
+ "0c6f6666657265645f6c6f616418012001280122120a10436c6f7365644c" .
+ "6f6f70506172616d73227b0a0a4c6f6164506172616d7312350a0b636c6f" .
+ "7365645f6c6f6f7018012001280b321e2e677270632e74657374696e672e" .
+ "436c6f7365644c6f6f70506172616d734800122e0a07706f6973736f6e18" .
+ "022001280b321b2e677270632e74657374696e672e506f6973736f6e5061" .
+ "72616d73480042060a046c6f616422430a0e536563757269747950617261" .
+ "6d7312130a0b7573655f746573745f6361180120012808121c0a14736572" .
+ "7665725f686f73745f6f76657272696465180220012809224d0a0a436861" .
+ "6e6e656c417267120c0a046e616d6518012001280912130a097374725f76" .
+ "616c7565180220012809480012130a09696e745f76616c75651803200128" .
+ "05480042070a0576616c756522a0040a0c436c69656e74436f6e66696712" .
+ "160a0e7365727665725f74617267657473180120032809122d0a0b636c69" .
+ "656e745f7479706518022001280e32182e677270632e74657374696e672e" .
+ "436c69656e745479706512350a0f73656375726974795f706172616d7318" .
+ "032001280b321c2e677270632e74657374696e672e536563757269747950" .
+ "6172616d7312240a1c6f75747374616e64696e675f727063735f7065725f" .
+ "6368616e6e656c18042001280512170a0f636c69656e745f6368616e6e65" .
+ "6c73180520012805121c0a146173796e635f636c69656e745f7468726561" .
+ "647318072001280512270a087270635f7479706518082001280e32152e67" .
+ "7270632e74657374696e672e52706354797065122d0a0b6c6f61645f7061" .
+ "72616d73180a2001280b32182e677270632e74657374696e672e4c6f6164" .
+ "506172616d7312330a0e7061796c6f61645f636f6e666967180b2001280b" .
+ "321b2e677270632e74657374696e672e5061796c6f6164436f6e66696712" .
+ "370a10686973746f6772616d5f706172616d73180c2001280b321d2e6772" .
+ "70632e74657374696e672e486973746f6772616d506172616d7312110a09" .
+ "636f72655f6c697374180d2003280512120a0a636f72655f6c696d697418" .
+ "0e2001280512180a106f746865725f636c69656e745f617069180f200128" .
+ "09122e0a0c6368616e6e656c5f6172677318102003280b32182e67727063" .
+ "2e74657374696e672e4368616e6e656c41726722380a0c436c69656e7453" .
+ "746174757312280a05737461747318012001280b32192e677270632e7465" .
+ "7374696e672e436c69656e74537461747322150a044d61726b120d0a0572" .
+ "6573657418012001280822680a0a436c69656e7441726773122b0a057365" .
+ "74757018012001280b321a2e677270632e74657374696e672e436c69656e" .
+ "74436f6e666967480012220a046d61726b18022001280b32122e67727063" .
+ "2e74657374696e672e4d61726b480042090a076172677479706522b4020a" .
+ "0c536572766572436f6e666967122d0a0b7365727665725f747970651801" .
+ "2001280e32182e677270632e74657374696e672e53657276657254797065" .
+ "12350a0f73656375726974795f706172616d7318022001280b321c2e6772" .
+ "70632e74657374696e672e5365637572697479506172616d73120c0a0470" .
+ "6f7274180420012805121c0a146173796e635f7365727665725f74687265" .
+ "61647318072001280512120a0a636f72655f6c696d697418082001280512" .
+ "330a0e7061796c6f61645f636f6e66696718092001280b321b2e67727063" .
+ "2e74657374696e672e5061796c6f6164436f6e66696712110a09636f7265" .
+ "5f6c697374180a2003280512180a106f746865725f7365727665725f6170" .
+ "69180b20012809121c0a137265736f757263655f71756f74615f73697a65" .
+ "18e9072001280522680a0a53657276657241726773122b0a057365747570" .
+ "18012001280b321a2e677270632e74657374696e672e536572766572436f" .
+ "6e666967480012220a046d61726b18022001280b32122e677270632e7465" .
+ "7374696e672e4d61726b480042090a076172677479706522550a0c536572" .
+ "76657253746174757312280a05737461747318012001280b32192e677270" .
+ "632e74657374696e672e5365727665725374617473120c0a04706f727418" .
+ "0220012805120d0a05636f726573180320012805220d0a0b436f72655265" .
+ "7175657374221d0a0c436f7265526573706f6e7365120d0a05636f726573" .
+ "18012001280522060a04566f696422fd010a085363656e6172696f120c0a" .
+ "046e616d6518012001280912310a0d636c69656e745f636f6e6669671802" .
+ "2001280b321a2e677270632e74657374696e672e436c69656e74436f6e66" .
+ "696712130a0b6e756d5f636c69656e747318032001280512310a0d736572" .
+ "7665725f636f6e66696718042001280b321a2e677270632e74657374696e" .
+ "672e536572766572436f6e66696712130a0b6e756d5f7365727665727318" .
+ "052001280512160a0e7761726d75705f7365636f6e647318062001280512" .
+ "190a1162656e63686d61726b5f7365636f6e647318072001280512200a18" .
+ "737061776e5f6c6f63616c5f776f726b65725f636f756e74180820012805" .
+ "22360a095363656e6172696f7312290a097363656e6172696f7318012003" .
+ "280b32162e677270632e74657374696e672e5363656e6172696f22f8020a" .
+ "155363656e6172696f526573756c7453756d6d617279120b0a0371707318" .
+ "0120012801121b0a137170735f7065725f7365727665725f636f72651802" .
+ "20012801121a0a127365727665725f73797374656d5f74696d6518032001" .
+ "280112180a107365727665725f757365725f74696d65180420012801121a" .
+ "0a12636c69656e745f73797374656d5f74696d6518052001280112180a10" .
+ "636c69656e745f757365725f74696d6518062001280112120a0a6c617465" .
+ "6e63795f353018072001280112120a0a6c6174656e63795f393018082001" .
+ "280112120a0a6c6174656e63795f393518092001280112120a0a6c617465" .
+ "6e63795f3939180a2001280112130a0b6c6174656e63795f393939180b20" .
+ "01280112180a107365727665725f6370755f7573616765180c2001280112" .
+ "260a1e7375636365737366756c5f72657175657374735f7065725f736563" .
+ "6f6e64180d2001280112220a1a6661696c65645f72657175657374735f70" .
+ "65725f7365636f6e64180e200128012283030a0e5363656e6172696f5265" .
+ "73756c7412280a087363656e6172696f18012001280b32162e677270632e" .
+ "74657374696e672e5363656e6172696f122e0a096c6174656e6369657318" .
+ "022001280b321b2e677270632e74657374696e672e486973746f6772616d" .
+ "44617461122f0a0c636c69656e745f737461747318032003280b32192e67" .
+ "7270632e74657374696e672e436c69656e745374617473122f0a0c736572" .
+ "7665725f737461747318042003280b32192e677270632e74657374696e67" .
+ "2e536572766572537461747312140a0c7365727665725f636f7265731805" .
+ "2003280512340a0773756d6d61727918062001280b32232e677270632e74" .
+ "657374696e672e5363656e6172696f526573756c7453756d6d6172791216" .
+ "0a0e636c69656e745f7375636365737318072003280812160a0e73657276" .
+ "65725f7375636365737318082003280812390a0f726571756573745f7265" .
+ "73756c747318092003280b32202e677270632e74657374696e672e526571" .
+ "75657374526573756c74436f756e742a410a0a436c69656e745479706512" .
+ "0f0a0b53594e435f434c49454e54100012100a0c4153594e435f434c4945" .
+ "4e54100112100a0c4f544845525f434c49454e5410022a5b0a0a53657276" .
+ "657254797065120f0a0b53594e435f534552564552100012100a0c415359" .
+ "4e435f534552564552100112180a144153594e435f47454e455249435f53" .
+ "4552564552100212100a0c4f544845525f53455256455210032a230a0752" .
+ "70635479706512090a05554e4152591000120d0a0953545245414d494e47" .
+ "1001620670726f746f33"
+ ));
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Messages.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Messages.php
new file mode 100644
index 0000000000..c088002626
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Messages.php
@@ -0,0 +1,69 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class Messages
+{
+ public static $is_initialized = false;
+
+ public static function initOnce() {
+ $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+ if (static::$is_initialized == true) {
+ return;
+ }
+ $pool->internalAddGeneratedFile(hex2bin(
+ "0ad50a0a257372632f70726f746f2f677270632f74657374696e672f6d65" .
+ "7373616765732e70726f746f120c677270632e74657374696e67221a0a09" .
+ "426f6f6c56616c7565120d0a0576616c756518012001280822400a075061" .
+ "796c6f616412270a047479706518012001280e32192e677270632e746573" .
+ "74696e672e5061796c6f616454797065120c0a04626f647918022001280c" .
+ "222b0a0a4563686f537461747573120c0a04636f6465180120012805120f" .
+ "0a076d65737361676518022001280922ce020a0d53696d706c6552657175" .
+ "65737412300a0d726573706f6e73655f7479706518012001280e32192e67" .
+ "7270632e74657374696e672e5061796c6f61645479706512150a0d726573" .
+ "706f6e73655f73697a6518022001280512260a077061796c6f6164180320" .
+ "01280b32152e677270632e74657374696e672e5061796c6f616412150a0d" .
+ "66696c6c5f757365726e616d6518042001280812180a1066696c6c5f6f61" .
+ "7574685f73636f706518052001280812340a13726573706f6e73655f636f" .
+ "6d7072657373656418062001280b32172e677270632e74657374696e672e" .
+ "426f6f6c56616c756512310a0f726573706f6e73655f7374617475731807" .
+ "2001280b32182e677270632e74657374696e672e4563686f537461747573" .
+ "12320a116578706563745f636f6d7072657373656418082001280b32172e" .
+ "677270632e74657374696e672e426f6f6c56616c7565225f0a0e53696d70" .
+ "6c65526573706f6e736512260a077061796c6f616418012001280b32152e" .
+ "677270632e74657374696e672e5061796c6f616412100a08757365726e61" .
+ "6d6518022001280912130a0b6f617574685f73636f706518032001280922" .
+ "770a1953747265616d696e67496e70757443616c6c526571756573741226" .
+ "0a077061796c6f616418012001280b32152e677270632e74657374696e67" .
+ "2e5061796c6f616412320a116578706563745f636f6d7072657373656418" .
+ "022001280b32172e677270632e74657374696e672e426f6f6c56616c7565" .
+ "223d0a1a53747265616d696e67496e70757443616c6c526573706f6e7365" .
+ "121f0a17616767726567617465645f7061796c6f61645f73697a65180120" .
+ "01280522640a12526573706f6e7365506172616d6574657273120c0a0473" .
+ "697a6518012001280512130a0b696e74657276616c5f7573180220012805" .
+ "122b0a0a636f6d7072657373656418032001280b32172e677270632e7465" .
+ "7374696e672e426f6f6c56616c756522e8010a1a53747265616d696e674f" .
+ "757470757443616c6c5265717565737412300a0d726573706f6e73655f74" .
+ "79706518012001280e32192e677270632e74657374696e672e5061796c6f" .
+ "616454797065123d0a13726573706f6e73655f706172616d657465727318" .
+ "022003280b32202e677270632e74657374696e672e526573706f6e736550" .
+ "6172616d657465727312260a077061796c6f616418032001280b32152e67" .
+ "7270632e74657374696e672e5061796c6f616412310a0f726573706f6e73" .
+ "655f73746174757318072001280b32182e677270632e74657374696e672e" .
+ "4563686f53746174757322450a1b53747265616d696e674f757470757443" .
+ "616c6c526573706f6e736512260a077061796c6f616418012001280b3215" .
+ "2e677270632e74657374696e672e5061796c6f616422330a0f5265636f6e" .
+ "6e656374506172616d7312200a186d61785f7265636f6e6e6563745f6261" .
+ "636b6f66665f6d7318012001280522330a0d5265636f6e6e656374496e66" .
+ "6f120e0a0670617373656418012001280812120a0a6261636b6f66665f6d" .
+ "731802200328052a1f0a0b5061796c6f61645479706512100a0c434f4d50" .
+ "5245535341424c451000620670726f746f33"
+ ));
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Payloads.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Payloads.php
new file mode 100644
index 0000000000..279fe00ac8
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Payloads.php
@@ -0,0 +1,37 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/payloads.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class Payloads
+{
+ public static $is_initialized = false;
+
+ public static function initOnce() {
+ $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+ if (static::$is_initialized == true) {
+ return;
+ }
+ $pool->internalAddGeneratedFile(hex2bin(
+ "0a93030a257372632f70726f746f2f677270632f74657374696e672f7061" .
+ "796c6f6164732e70726f746f120c677270632e74657374696e6722370a10" .
+ "42797465427566666572506172616d7312100a087265715f73697a651801" .
+ "2001280512110a09726573705f73697a6518022001280522380a1153696d" .
+ "706c6550726f746f506172616d7312100a087265715f73697a6518012001" .
+ "280512110a09726573705f73697a6518022001280522140a12436f6d706c" .
+ "657850726f746f506172616d7322ca010a0d5061796c6f6164436f6e6669" .
+ "6712380a0e627974656275665f706172616d7318012001280b321e2e6772" .
+ "70632e74657374696e672e42797465427566666572506172616d73480012" .
+ "380a0d73696d706c655f706172616d7318022001280b321f2e677270632e" .
+ "74657374696e672e53696d706c6550726f746f506172616d734800123a0a" .
+ "0e636f6d706c65785f706172616d7318032001280b32202e677270632e74" .
+ "657374696e672e436f6d706c657850726f746f506172616d73480042090a" .
+ "077061796c6f6164620670726f746f33"
+ ));
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/ProxyService.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/ProxyService.php
new file mode 100644
index 0000000000..e35944e1d8
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/ProxyService.php
@@ -0,0 +1,34 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/proxy-service.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class ProxyService
+{
+ public static $is_initialized = false;
+
+ public static function initOnce() {
+ $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+ if (static::$is_initialized == true) {
+ return;
+ }
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ $pool->internalAddGeneratedFile(hex2bin(
+ "0a97020a2a7372632f70726f746f2f677270632f74657374696e672f7072" .
+ "6f78792d736572766963652e70726f746f120c677270632e74657374696e" .
+ "671a247372632f70726f746f2f677270632f74657374696e672f636f6e74" .
+ "726f6c2e70726f746f221c0a0950726f787953746174120f0a076c617465" .
+ "6e6379180120012801328e010a1250726f7879436c69656e745365727669" .
+ "6365123b0a09476574436f6e66696712122e677270632e74657374696e67" .
+ "2e566f69641a1a2e677270632e74657374696e672e436c69656e74436f6e" .
+ "666967123b0a0a5265706f727454696d6512172e677270632e7465737469" .
+ "6e672e50726f7879537461741a122e677270632e74657374696e672e566f" .
+ "69642801620670726f746f33"
+ ));
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Services.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Services.php
new file mode 100644
index 0000000000..7a9439a5b9
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Services.php
@@ -0,0 +1,45 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/services.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class Services
+{
+ public static $is_initialized = false;
+
+ public static function initOnce() {
+ $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+ if (static::$is_initialized == true) {
+ return;
+ }
+ \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ $pool->internalAddGeneratedFile(hex2bin(
+ "0ad1040a257372632f70726f746f2f677270632f74657374696e672f7365" .
+ "7276696365732e70726f746f120c677270632e74657374696e671a257372" .
+ "632f70726f746f2f677270632f74657374696e672f6d657373616765732e" .
+ "70726f746f1a247372632f70726f746f2f677270632f74657374696e672f" .
+ "636f6e74726f6c2e70726f746f32aa010a1042656e63686d61726b536572" .
+ "7669636512460a09556e61727943616c6c121b2e677270632e7465737469" .
+ "6e672e53696d706c65526571756573741a1c2e677270632e74657374696e" .
+ "672e53696d706c65526573706f6e7365124e0a0d53747265616d696e6743" .
+ "616c6c121b2e677270632e74657374696e672e53696d706c655265717565" .
+ "73741a1c2e677270632e74657374696e672e53696d706c65526573706f6e" .
+ "7365280130013297020a0d576f726b65725365727669636512450a095275" .
+ "6e53657276657212182e677270632e74657374696e672e53657276657241" .
+ "7267731a1a2e677270632e74657374696e672e5365727665725374617475" .
+ "732801300112450a0952756e436c69656e7412182e677270632e74657374" .
+ "696e672e436c69656e74417267731a1a2e677270632e74657374696e672e" .
+ "436c69656e745374617475732801300112420a09436f7265436f756e7412" .
+ "192e677270632e74657374696e672e436f7265526571756573741a1a2e67" .
+ "7270632e74657374696e672e436f7265526573706f6e736512340a0a5175" .
+ "6974576f726b657212122e677270632e74657374696e672e566f69641a12" .
+ "2e677270632e74657374696e672e566f6964620670726f746f33"
+ ));
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Stats.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Stats.php
new file mode 100644
index 0000000000..99c0000a52
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Stats.php
@@ -0,0 +1,44 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/stats.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class Stats
+{
+ public static $is_initialized = false;
+
+ public static function initOnce() {
+ $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+ if (static::$is_initialized == true) {
+ return;
+ }
+ $pool->internalAddGeneratedFile(hex2bin(
+ "0adf040a227372632f70726f746f2f677270632f74657374696e672f7374" .
+ "6174732e70726f746f120c677270632e74657374696e67227a0a0b536572" .
+ "766572537461747312140a0c74696d655f656c6170736564180120012801" .
+ "12110a0974696d655f7573657218022001280112130a0b74696d655f7379" .
+ "7374656d18032001280112160a0e746f74616c5f6370755f74696d651804" .
+ "2001280412150a0d69646c655f6370755f74696d65180520012804223b0a" .
+ "0f486973746f6772616d506172616d7312120a0a7265736f6c7574696f6e" .
+ "18012001280112140a0c6d61785f706f737369626c651802200128012277" .
+ "0a0d486973746f6772616d44617461120e0a066275636b65741801200328" .
+ "0d12100a086d696e5f7365656e18022001280112100a086d61785f736565" .
+ "6e180320012801120b0a0373756d18042001280112160a0e73756d5f6f66" .
+ "5f73717561726573180520012801120d0a05636f756e7418062001280122" .
+ "380a1252657175657374526573756c74436f756e7412130a0b7374617475" .
+ "735f636f6465180120012805120d0a05636f756e7418022001280322b601" .
+ "0a0b436c69656e745374617473122e0a096c6174656e6369657318012001" .
+ "280b321b2e677270632e74657374696e672e486973746f6772616d446174" .
+ "6112140a0c74696d655f656c617073656418022001280112110a0974696d" .
+ "655f7573657218032001280112130a0b74696d655f73797374656d180420" .
+ "01280112390a0f726571756573745f726573756c747318052003280b3220" .
+ "2e677270632e74657374696e672e52657175657374526573756c74436f75" .
+ "6e74620670726f746f33"
+ ));
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/BenchmarkServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/BenchmarkServiceClient.php
new file mode 100644
index 0000000000..daf17800cd
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/BenchmarkServiceClient.php
@@ -0,0 +1,78 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// 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.
+//
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+namespace Grpc\Testing {
+
+ class BenchmarkServiceClient extends \Grpc\BaseStub {
+
+ /**
+ * @param string $hostname hostname
+ * @param array $opts channel options
+ * @param Grpc\Channel $channel (optional) re-use channel object
+ */
+ public function __construct($hostname, $opts, $channel = null) {
+ parent::__construct($hostname, $opts, $channel);
+ }
+
+ /**
+ * One request followed by one response.
+ * The server returns the client payload as-is.
+ * @param \Grpc\Testing\SimpleRequest $argument input argument
+ * @param array $metadata metadata
+ * @param array $options call options
+ */
+ public function UnaryCall(\Grpc\Testing\SimpleRequest $argument,
+ $metadata = [], $options = []) {
+ return $this->_simpleRequest('/grpc.testing.BenchmarkService/UnaryCall',
+ $argument,
+ ['\Grpc\Testing\SimpleResponse', 'decode'],
+ $metadata, $options);
+ }
+
+ /**
+ * One request followed by one response.
+ * The server returns the client payload as-is.
+ * @param array $metadata metadata
+ * @param array $options call options
+ */
+ public function StreamingCall($metadata = [], $options = []) {
+ return $this->_bidiRequest('/grpc.testing.BenchmarkService/StreamingCall',
+ ['\Grpc\Testing\SimpleResponse','decode'],
+ $metadata, $options);
+ }
+
+ }
+
+}
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/BoolValue.php b/src/php/tests/qps/generated_code/Grpc/Testing/BoolValue.php
new file mode 100644
index 0000000000..f0497accfb
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/BoolValue.php
@@ -0,0 +1,62 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * TODO(dgq): Go back to using well-known types once
+ * https://github.com/grpc/grpc/issues/6980 has been fixed.
+ * import "google/protobuf/wrappers.proto";
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.BoolValue</code>
+ */
+class BoolValue extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * The bool value.
+ * </pre>
+ *
+ * <code>bool value = 1;</code>
+ */
+ private $value = false;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * The bool value.
+ * </pre>
+ *
+ * <code>bool value = 1;</code>
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * <pre>
+ * The bool value.
+ * </pre>
+ *
+ * <code>bool value = 1;</code>
+ */
+ public function setValue($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->value = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ByteBufferParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/ByteBufferParams.php
new file mode 100644
index 0000000000..0057d38748
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ByteBufferParams.php
@@ -0,0 +1,65 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/payloads.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.ByteBufferParams</code>
+ */
+class ByteBufferParams extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>int32 req_size = 1;</code>
+ */
+ private $req_size = 0;
+ /**
+ * <code>int32 resp_size = 2;</code>
+ */
+ private $resp_size = 0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>int32 req_size = 1;</code>
+ */
+ public function getReqSize()
+ {
+ return $this->req_size;
+ }
+
+ /**
+ * <code>int32 req_size = 1;</code>
+ */
+ public function setReqSize($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->req_size = $var;
+ }
+
+ /**
+ * <code>int32 resp_size = 2;</code>
+ */
+ public function getRespSize()
+ {
+ return $this->resp_size;
+ }
+
+ /**
+ * <code>int32 resp_size = 2;</code>
+ */
+ public function setRespSize($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->resp_size = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ChannelArg.php b/src/php/tests/qps/generated_code/Grpc/Testing/ChannelArg.php
new file mode 100644
index 0000000000..d2fe3ae5ff
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ChannelArg.php
@@ -0,0 +1,84 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.ChannelArg</code>
+ */
+class ChannelArg extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>string name = 1;</code>
+ */
+ private $name = '';
+ protected $value;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>string name = 1;</code>
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * <code>string name = 1;</code>
+ */
+ public function setName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->name = $var;
+ }
+
+ /**
+ * <code>string str_value = 2;</code>
+ */
+ public function getStrValue()
+ {
+ return $this->readOneof(2);
+ }
+
+ /**
+ * <code>string str_value = 2;</code>
+ */
+ public function setStrValue($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->writeOneof(2, $var);
+ }
+
+ /**
+ * <code>int32 int_value = 3;</code>
+ */
+ public function getIntValue()
+ {
+ return $this->readOneof(3);
+ }
+
+ /**
+ * <code>int32 int_value = 3;</code>
+ */
+ public function setIntValue($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->writeOneof(3, $var);
+ }
+
+ public function getValue()
+ {
+ return $this->whichOneof("value");
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ClientArgs.php b/src/php/tests/qps/generated_code/Grpc/Testing/ClientArgs.php
new file mode 100644
index 0000000000..c878c5a7bc
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ClientArgs.php
@@ -0,0 +1,63 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.ClientArgs</code>
+ */
+class ClientArgs extends \Google\Protobuf\Internal\Message
+{
+ protected $argtype;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>.grpc.testing.ClientConfig setup = 1;</code>
+ */
+ public function getSetup()
+ {
+ return $this->readOneof(1);
+ }
+
+ /**
+ * <code>.grpc.testing.ClientConfig setup = 1;</code>
+ */
+ public function setSetup(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\ClientConfig::class);
+ $this->writeOneof(1, $var);
+ }
+
+ /**
+ * <code>.grpc.testing.Mark mark = 2;</code>
+ */
+ public function getMark()
+ {
+ return $this->readOneof(2);
+ }
+
+ /**
+ * <code>.grpc.testing.Mark mark = 2;</code>
+ */
+ public function setMark(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\Mark::class);
+ $this->writeOneof(2, $var);
+ }
+
+ public function getArgtype()
+ {
+ return $this->whichOneof("argtype");
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ClientConfig.php b/src/php/tests/qps/generated_code/Grpc/Testing/ClientConfig.php
new file mode 100644
index 0000000000..52d6a75fb0
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ClientConfig.php
@@ -0,0 +1,407 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.ClientConfig</code>
+ */
+class ClientConfig extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * List of targets to connect to. At least one target needs to be specified.
+ * </pre>
+ *
+ * <code>repeated string server_targets = 1;</code>
+ */
+ private $server_targets;
+ /**
+ * <code>.grpc.testing.ClientType client_type = 2;</code>
+ */
+ private $client_type = 0;
+ /**
+ * <code>.grpc.testing.SecurityParams security_params = 3;</code>
+ */
+ private $security_params = null;
+ /**
+ * <pre>
+ * How many concurrent RPCs to start for each channel.
+ * For synchronous client, use a separate thread for each outstanding RPC.
+ * </pre>
+ *
+ * <code>int32 outstanding_rpcs_per_channel = 4;</code>
+ */
+ private $outstanding_rpcs_per_channel = 0;
+ /**
+ * <pre>
+ * Number of independent client channels to create.
+ * i-th channel will connect to server_target[i % server_targets.size()]
+ * </pre>
+ *
+ * <code>int32 client_channels = 5;</code>
+ */
+ private $client_channels = 0;
+ /**
+ * <pre>
+ * Only for async client. Number of threads to use to start/manage RPCs.
+ * </pre>
+ *
+ * <code>int32 async_client_threads = 7;</code>
+ */
+ private $async_client_threads = 0;
+ /**
+ * <code>.grpc.testing.RpcType rpc_type = 8;</code>
+ */
+ private $rpc_type = 0;
+ /**
+ * <pre>
+ * The requested load for the entire client (aggregated over all the threads).
+ * </pre>
+ *
+ * <code>.grpc.testing.LoadParams load_params = 10;</code>
+ */
+ private $load_params = null;
+ /**
+ * <code>.grpc.testing.PayloadConfig payload_config = 11;</code>
+ */
+ private $payload_config = null;
+ /**
+ * <code>.grpc.testing.HistogramParams histogram_params = 12;</code>
+ */
+ private $histogram_params = null;
+ /**
+ * <pre>
+ * Specify the cores we should run the client on, if desired
+ * </pre>
+ *
+ * <code>repeated int32 core_list = 13;</code>
+ */
+ private $core_list;
+ /**
+ * <code>int32 core_limit = 14;</code>
+ */
+ private $core_limit = 0;
+ /**
+ * <pre>
+ * If we use an OTHER_CLIENT client_type, this string gives more detail
+ * </pre>
+ *
+ * <code>string other_client_api = 15;</code>
+ */
+ private $other_client_api = '';
+ /**
+ * <code>repeated .grpc.testing.ChannelArg channel_args = 16;</code>
+ */
+ private $channel_args;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * List of targets to connect to. At least one target needs to be specified.
+ * </pre>
+ *
+ * <code>repeated string server_targets = 1;</code>
+ */
+ public function getServerTargets()
+ {
+ return $this->server_targets;
+ }
+
+ /**
+ * <pre>
+ * List of targets to connect to. At least one target needs to be specified.
+ * </pre>
+ *
+ * <code>repeated string server_targets = 1;</code>
+ */
+ public function setServerTargets(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
+ $this->server_targets = $var;
+ }
+
+ /**
+ * <code>.grpc.testing.ClientType client_type = 2;</code>
+ */
+ public function getClientType()
+ {
+ return $this->client_type;
+ }
+
+ /**
+ * <code>.grpc.testing.ClientType client_type = 2;</code>
+ */
+ public function setClientType($var)
+ {
+ GPBUtil::checkEnum($var, \Grpc\Testing\ClientType::class);
+ $this->client_type = $var;
+ }
+
+ /**
+ * <code>.grpc.testing.SecurityParams security_params = 3;</code>
+ */
+ public function getSecurityParams()
+ {
+ return $this->security_params;
+ }
+
+ /**
+ * <code>.grpc.testing.SecurityParams security_params = 3;</code>
+ */
+ public function setSecurityParams(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\SecurityParams::class);
+ $this->security_params = $var;
+ }
+
+ /**
+ * <pre>
+ * How many concurrent RPCs to start for each channel.
+ * For synchronous client, use a separate thread for each outstanding RPC.
+ * </pre>
+ *
+ * <code>int32 outstanding_rpcs_per_channel = 4;</code>
+ */
+ public function getOutstandingRpcsPerChannel()
+ {
+ return $this->outstanding_rpcs_per_channel;
+ }
+
+ /**
+ * <pre>
+ * How many concurrent RPCs to start for each channel.
+ * For synchronous client, use a separate thread for each outstanding RPC.
+ * </pre>
+ *
+ * <code>int32 outstanding_rpcs_per_channel = 4;</code>
+ */
+ public function setOutstandingRpcsPerChannel($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->outstanding_rpcs_per_channel = $var;
+ }
+
+ /**
+ * <pre>
+ * Number of independent client channels to create.
+ * i-th channel will connect to server_target[i % server_targets.size()]
+ * </pre>
+ *
+ * <code>int32 client_channels = 5;</code>
+ */
+ public function getClientChannels()
+ {
+ return $this->client_channels;
+ }
+
+ /**
+ * <pre>
+ * Number of independent client channels to create.
+ * i-th channel will connect to server_target[i % server_targets.size()]
+ * </pre>
+ *
+ * <code>int32 client_channels = 5;</code>
+ */
+ public function setClientChannels($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->client_channels = $var;
+ }
+
+ /**
+ * <pre>
+ * Only for async client. Number of threads to use to start/manage RPCs.
+ * </pre>
+ *
+ * <code>int32 async_client_threads = 7;</code>
+ */
+ public function getAsyncClientThreads()
+ {
+ return $this->async_client_threads;
+ }
+
+ /**
+ * <pre>
+ * Only for async client. Number of threads to use to start/manage RPCs.
+ * </pre>
+ *
+ * <code>int32 async_client_threads = 7;</code>
+ */
+ public function setAsyncClientThreads($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->async_client_threads = $var;
+ }
+
+ /**
+ * <code>.grpc.testing.RpcType rpc_type = 8;</code>
+ */
+ public function getRpcType()
+ {
+ return $this->rpc_type;
+ }
+
+ /**
+ * <code>.grpc.testing.RpcType rpc_type = 8;</code>
+ */
+ public function setRpcType($var)
+ {
+ GPBUtil::checkEnum($var, \Grpc\Testing\RpcType::class);
+ $this->rpc_type = $var;
+ }
+
+ /**
+ * <pre>
+ * The requested load for the entire client (aggregated over all the threads).
+ * </pre>
+ *
+ * <code>.grpc.testing.LoadParams load_params = 10;</code>
+ */
+ public function getLoadParams()
+ {
+ return $this->load_params;
+ }
+
+ /**
+ * <pre>
+ * The requested load for the entire client (aggregated over all the threads).
+ * </pre>
+ *
+ * <code>.grpc.testing.LoadParams load_params = 10;</code>
+ */
+ public function setLoadParams(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\LoadParams::class);
+ $this->load_params = $var;
+ }
+
+ /**
+ * <code>.grpc.testing.PayloadConfig payload_config = 11;</code>
+ */
+ public function getPayloadConfig()
+ {
+ return $this->payload_config;
+ }
+
+ /**
+ * <code>.grpc.testing.PayloadConfig payload_config = 11;</code>
+ */
+ public function setPayloadConfig(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\PayloadConfig::class);
+ $this->payload_config = $var;
+ }
+
+ /**
+ * <code>.grpc.testing.HistogramParams histogram_params = 12;</code>
+ */
+ public function getHistogramParams()
+ {
+ return $this->histogram_params;
+ }
+
+ /**
+ * <code>.grpc.testing.HistogramParams histogram_params = 12;</code>
+ */
+ public function setHistogramParams(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\HistogramParams::class);
+ $this->histogram_params = $var;
+ }
+
+ /**
+ * <pre>
+ * Specify the cores we should run the client on, if desired
+ * </pre>
+ *
+ * <code>repeated int32 core_list = 13;</code>
+ */
+ public function getCoreList()
+ {
+ return $this->core_list;
+ }
+
+ /**
+ * <pre>
+ * Specify the cores we should run the client on, if desired
+ * </pre>
+ *
+ * <code>repeated int32 core_list = 13;</code>
+ */
+ public function setCoreList(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
+ $this->core_list = $var;
+ }
+
+ /**
+ * <code>int32 core_limit = 14;</code>
+ */
+ public function getCoreLimit()
+ {
+ return $this->core_limit;
+ }
+
+ /**
+ * <code>int32 core_limit = 14;</code>
+ */
+ public function setCoreLimit($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->core_limit = $var;
+ }
+
+ /**
+ * <pre>
+ * If we use an OTHER_CLIENT client_type, this string gives more detail
+ * </pre>
+ *
+ * <code>string other_client_api = 15;</code>
+ */
+ public function getOtherClientApi()
+ {
+ return $this->other_client_api;
+ }
+
+ /**
+ * <pre>
+ * If we use an OTHER_CLIENT client_type, this string gives more detail
+ * </pre>
+ *
+ * <code>string other_client_api = 15;</code>
+ */
+ public function setOtherClientApi($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->other_client_api = $var;
+ }
+
+ /**
+ * <code>repeated .grpc.testing.ChannelArg channel_args = 16;</code>
+ */
+ public function getChannelArgs()
+ {
+ return $this->channel_args;
+ }
+
+ /**
+ * <code>repeated .grpc.testing.ChannelArg channel_args = 16;</code>
+ */
+ public function setChannelArgs(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\ChannelArg::class);
+ $this->channel_args = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ClientStats.php b/src/php/tests/qps/generated_code/Grpc/Testing/ClientStats.php
new file mode 100644
index 0000000000..8b9a0c33a4
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ClientStats.php
@@ -0,0 +1,164 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/stats.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.ClientStats</code>
+ */
+class ClientStats extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * Latency histogram. Data points are in nanoseconds.
+ * </pre>
+ *
+ * <code>.grpc.testing.HistogramData latencies = 1;</code>
+ */
+ private $latencies = null;
+ /**
+ * <pre>
+ * See ServerStats for details.
+ * </pre>
+ *
+ * <code>double time_elapsed = 2;</code>
+ */
+ private $time_elapsed = 0.0;
+ /**
+ * <code>double time_user = 3;</code>
+ */
+ private $time_user = 0.0;
+ /**
+ * <code>double time_system = 4;</code>
+ */
+ private $time_system = 0.0;
+ /**
+ * <pre>
+ * Number of failed requests (one row per status code seen)
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.RequestResultCount request_results = 5;</code>
+ */
+ private $request_results;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * Latency histogram. Data points are in nanoseconds.
+ * </pre>
+ *
+ * <code>.grpc.testing.HistogramData latencies = 1;</code>
+ */
+ public function getLatencies()
+ {
+ return $this->latencies;
+ }
+
+ /**
+ * <pre>
+ * Latency histogram. Data points are in nanoseconds.
+ * </pre>
+ *
+ * <code>.grpc.testing.HistogramData latencies = 1;</code>
+ */
+ public function setLatencies(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\HistogramData::class);
+ $this->latencies = $var;
+ }
+
+ /**
+ * <pre>
+ * See ServerStats for details.
+ * </pre>
+ *
+ * <code>double time_elapsed = 2;</code>
+ */
+ public function getTimeElapsed()
+ {
+ return $this->time_elapsed;
+ }
+
+ /**
+ * <pre>
+ * See ServerStats for details.
+ * </pre>
+ *
+ * <code>double time_elapsed = 2;</code>
+ */
+ public function setTimeElapsed($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->time_elapsed = $var;
+ }
+
+ /**
+ * <code>double time_user = 3;</code>
+ */
+ public function getTimeUser()
+ {
+ return $this->time_user;
+ }
+
+ /**
+ * <code>double time_user = 3;</code>
+ */
+ public function setTimeUser($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->time_user = $var;
+ }
+
+ /**
+ * <code>double time_system = 4;</code>
+ */
+ public function getTimeSystem()
+ {
+ return $this->time_system;
+ }
+
+ /**
+ * <code>double time_system = 4;</code>
+ */
+ public function setTimeSystem($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->time_system = $var;
+ }
+
+ /**
+ * <pre>
+ * Number of failed requests (one row per status code seen)
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.RequestResultCount request_results = 5;</code>
+ */
+ public function getRequestResults()
+ {
+ return $this->request_results;
+ }
+
+ /**
+ * <pre>
+ * Number of failed requests (one row per status code seen)
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.RequestResultCount request_results = 5;</code>
+ */
+ public function setRequestResults(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\RequestResultCount::class);
+ $this->request_results = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ClientStatus.php b/src/php/tests/qps/generated_code/Grpc/Testing/ClientStatus.php
new file mode 100644
index 0000000000..a59f87a962
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ClientStatus.php
@@ -0,0 +1,44 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.ClientStatus</code>
+ */
+class ClientStatus extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>.grpc.testing.ClientStats stats = 1;</code>
+ */
+ private $stats = null;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>.grpc.testing.ClientStats stats = 1;</code>
+ */
+ public function getStats()
+ {
+ return $this->stats;
+ }
+
+ /**
+ * <code>.grpc.testing.ClientStats stats = 1;</code>
+ */
+ public function setStats(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\ClientStats::class);
+ $this->stats = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ClientType.php b/src/php/tests/qps/generated_code/Grpc/Testing/ClientType.php
new file mode 100644
index 0000000000..4f59da992f
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ClientType.php
@@ -0,0 +1,34 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+/**
+ * Protobuf enum <code>grpc.testing.ClientType</code>
+ */
+class ClientType
+{
+ /**
+ * <pre>
+ * Many languages support a basic distinction between using
+ * sync or async client, and this allows the specification
+ * </pre>
+ *
+ * <code>SYNC_CLIENT = 0;</code>
+ */
+ const SYNC_CLIENT = 0;
+ /**
+ * <code>ASYNC_CLIENT = 1;</code>
+ */
+ const ASYNC_CLIENT = 1;
+ /**
+ * <pre>
+ * used for some language-specific variants
+ * </pre>
+ *
+ * <code>OTHER_CLIENT = 2;</code>
+ */
+ const OTHER_CLIENT = 2;
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ClosedLoopParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/ClosedLoopParams.php
new file mode 100644
index 0000000000..53f2948af2
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ClosedLoopParams.php
@@ -0,0 +1,28 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Once an RPC finishes, immediately start a new one.
+ * No configuration parameters needed.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.ClosedLoopParams</code>
+ */
+class ClosedLoopParams extends \Google\Protobuf\Internal\Message
+{
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ComplexProtoParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/ComplexProtoParams.php
new file mode 100644
index 0000000000..6d990f1b06
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ComplexProtoParams.php
@@ -0,0 +1,28 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/payloads.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * TODO (vpai): Fill this in once the details of complex, representative
+ * protos are decided
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.ComplexProtoParams</code>
+ */
+class ComplexProtoParams extends \Google\Protobuf\Internal\Message
+{
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce();
+ parent::__construct();
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/CoreRequest.php b/src/php/tests/qps/generated_code/Grpc/Testing/CoreRequest.php
new file mode 100644
index 0000000000..2e078b3fcd
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/CoreRequest.php
@@ -0,0 +1,23 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.CoreRequest</code>
+ */
+class CoreRequest extends \Google\Protobuf\Internal\Message
+{
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/CoreResponse.php b/src/php/tests/qps/generated_code/Grpc/Testing/CoreResponse.php
new file mode 100644
index 0000000000..85cb3418ad
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/CoreResponse.php
@@ -0,0 +1,56 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.CoreResponse</code>
+ */
+class CoreResponse extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * Number of cores available on the server
+ * </pre>
+ *
+ * <code>int32 cores = 1;</code>
+ */
+ private $cores = 0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * Number of cores available on the server
+ * </pre>
+ *
+ * <code>int32 cores = 1;</code>
+ */
+ public function getCores()
+ {
+ return $this->cores;
+ }
+
+ /**
+ * <pre>
+ * Number of cores available on the server
+ * </pre>
+ *
+ * <code>int32 cores = 1;</code>
+ */
+ public function setCores($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->cores = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/EchoStatus.php b/src/php/tests/qps/generated_code/Grpc/Testing/EchoStatus.php
new file mode 100644
index 0000000000..27340fb0ef
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/EchoStatus.php
@@ -0,0 +1,70 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * A protobuf representation for grpc status. This is used by test
+ * clients to specify a status that the server should attempt to return.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.EchoStatus</code>
+ */
+class EchoStatus extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>int32 code = 1;</code>
+ */
+ private $code = 0;
+ /**
+ * <code>string message = 2;</code>
+ */
+ private $message = '';
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>int32 code = 1;</code>
+ */
+ public function getCode()
+ {
+ return $this->code;
+ }
+
+ /**
+ * <code>int32 code = 1;</code>
+ */
+ public function setCode($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->code = $var;
+ }
+
+ /**
+ * <code>string message = 2;</code>
+ */
+ public function getMessage()
+ {
+ return $this->message;
+ }
+
+ /**
+ * <code>string message = 2;</code>
+ */
+ public function setMessage($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->message = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/HistogramData.php b/src/php/tests/qps/generated_code/Grpc/Testing/HistogramData.php
new file mode 100644
index 0000000000..056da6e5de
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/HistogramData.php
@@ -0,0 +1,153 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/stats.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Histogram data based on grpc/support/histogram.c
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.HistogramData</code>
+ */
+class HistogramData extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>repeated uint32 bucket = 1;</code>
+ */
+ private $bucket;
+ /**
+ * <code>double min_seen = 2;</code>
+ */
+ private $min_seen = 0.0;
+ /**
+ * <code>double max_seen = 3;</code>
+ */
+ private $max_seen = 0.0;
+ /**
+ * <code>double sum = 4;</code>
+ */
+ private $sum = 0.0;
+ /**
+ * <code>double sum_of_squares = 5;</code>
+ */
+ private $sum_of_squares = 0.0;
+ /**
+ * <code>double count = 6;</code>
+ */
+ private $count = 0.0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>repeated uint32 bucket = 1;</code>
+ */
+ public function getBucket()
+ {
+ return $this->bucket;
+ }
+
+ /**
+ * <code>repeated uint32 bucket = 1;</code>
+ */
+ public function setBucket(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::UINT32);
+ $this->bucket = $var;
+ }
+
+ /**
+ * <code>double min_seen = 2;</code>
+ */
+ public function getMinSeen()
+ {
+ return $this->min_seen;
+ }
+
+ /**
+ * <code>double min_seen = 2;</code>
+ */
+ public function setMinSeen($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->min_seen = $var;
+ }
+
+ /**
+ * <code>double max_seen = 3;</code>
+ */
+ public function getMaxSeen()
+ {
+ return $this->max_seen;
+ }
+
+ /**
+ * <code>double max_seen = 3;</code>
+ */
+ public function setMaxSeen($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->max_seen = $var;
+ }
+
+ /**
+ * <code>double sum = 4;</code>
+ */
+ public function getSum()
+ {
+ return $this->sum;
+ }
+
+ /**
+ * <code>double sum = 4;</code>
+ */
+ public function setSum($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->sum = $var;
+ }
+
+ /**
+ * <code>double sum_of_squares = 5;</code>
+ */
+ public function getSumOfSquares()
+ {
+ return $this->sum_of_squares;
+ }
+
+ /**
+ * <code>double sum_of_squares = 5;</code>
+ */
+ public function setSumOfSquares($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->sum_of_squares = $var;
+ }
+
+ /**
+ * <code>double count = 6;</code>
+ */
+ public function getCount()
+ {
+ return $this->count;
+ }
+
+ /**
+ * <code>double count = 6;</code>
+ */
+ public function setCount($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->count = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/HistogramParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/HistogramParams.php
new file mode 100644
index 0000000000..836c94b01d
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/HistogramParams.php
@@ -0,0 +1,93 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/stats.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Histogram params based on grpc/support/histogram.c
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.HistogramParams</code>
+ */
+class HistogramParams extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * first bucket is [0, 1 + resolution)
+ * </pre>
+ *
+ * <code>double resolution = 1;</code>
+ */
+ private $resolution = 0.0;
+ /**
+ * <pre>
+ * use enough buckets to allow this value
+ * </pre>
+ *
+ * <code>double max_possible = 2;</code>
+ */
+ private $max_possible = 0.0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * first bucket is [0, 1 + resolution)
+ * </pre>
+ *
+ * <code>double resolution = 1;</code>
+ */
+ public function getResolution()
+ {
+ return $this->resolution;
+ }
+
+ /**
+ * <pre>
+ * first bucket is [0, 1 + resolution)
+ * </pre>
+ *
+ * <code>double resolution = 1;</code>
+ */
+ public function setResolution($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->resolution = $var;
+ }
+
+ /**
+ * <pre>
+ * use enough buckets to allow this value
+ * </pre>
+ *
+ * <code>double max_possible = 2;</code>
+ */
+ public function getMaxPossible()
+ {
+ return $this->max_possible;
+ }
+
+ /**
+ * <pre>
+ * use enough buckets to allow this value
+ * </pre>
+ *
+ * <code>double max_possible = 2;</code>
+ */
+ public function setMaxPossible($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->max_possible = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/LoadParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/LoadParams.php
new file mode 100644
index 0000000000..1f32e49c8a
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/LoadParams.php
@@ -0,0 +1,63 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.LoadParams</code>
+ */
+class LoadParams extends \Google\Protobuf\Internal\Message
+{
+ protected $load;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>.grpc.testing.ClosedLoopParams closed_loop = 1;</code>
+ */
+ public function getClosedLoop()
+ {
+ return $this->readOneof(1);
+ }
+
+ /**
+ * <code>.grpc.testing.ClosedLoopParams closed_loop = 1;</code>
+ */
+ public function setClosedLoop(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\ClosedLoopParams::class);
+ $this->writeOneof(1, $var);
+ }
+
+ /**
+ * <code>.grpc.testing.PoissonParams poisson = 2;</code>
+ */
+ public function getPoisson()
+ {
+ return $this->readOneof(2);
+ }
+
+ /**
+ * <code>.grpc.testing.PoissonParams poisson = 2;</code>
+ */
+ public function setPoisson(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\PoissonParams::class);
+ $this->writeOneof(2, $var);
+ }
+
+ public function getLoad()
+ {
+ return $this->whichOneof("load");
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/Mark.php b/src/php/tests/qps/generated_code/Grpc/Testing/Mark.php
new file mode 100644
index 0000000000..ce006efacd
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/Mark.php
@@ -0,0 +1,60 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Request current stats
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.Mark</code>
+ */
+class Mark extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * if true, the stats will be reset after taking their snapshot.
+ * </pre>
+ *
+ * <code>bool reset = 1;</code>
+ */
+ private $reset = false;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * if true, the stats will be reset after taking their snapshot.
+ * </pre>
+ *
+ * <code>bool reset = 1;</code>
+ */
+ public function getReset()
+ {
+ return $this->reset;
+ }
+
+ /**
+ * <pre>
+ * if true, the stats will be reset after taking their snapshot.
+ * </pre>
+ *
+ * <code>bool reset = 1;</code>
+ */
+ public function setReset($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->reset = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/Payload.php b/src/php/tests/qps/generated_code/Grpc/Testing/Payload.php
new file mode 100644
index 0000000000..d17c271af7
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/Payload.php
@@ -0,0 +1,96 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * A block of data, to simply increase gRPC message size.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.Payload</code>
+ */
+class Payload extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * DEPRECATED, don't use. To be removed shortly.
+ * The type of data in body.
+ * </pre>
+ *
+ * <code>.grpc.testing.PayloadType type = 1;</code>
+ */
+ private $type = 0;
+ /**
+ * <pre>
+ * Primary contents of payload.
+ * </pre>
+ *
+ * <code>bytes body = 2;</code>
+ */
+ private $body = '';
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * DEPRECATED, don't use. To be removed shortly.
+ * The type of data in body.
+ * </pre>
+ *
+ * <code>.grpc.testing.PayloadType type = 1;</code>
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * <pre>
+ * DEPRECATED, don't use. To be removed shortly.
+ * The type of data in body.
+ * </pre>
+ *
+ * <code>.grpc.testing.PayloadType type = 1;</code>
+ */
+ public function setType($var)
+ {
+ GPBUtil::checkEnum($var, \Grpc\Testing\PayloadType::class);
+ $this->type = $var;
+ }
+
+ /**
+ * <pre>
+ * Primary contents of payload.
+ * </pre>
+ *
+ * <code>bytes body = 2;</code>
+ */
+ public function getBody()
+ {
+ return $this->body;
+ }
+
+ /**
+ * <pre>
+ * Primary contents of payload.
+ * </pre>
+ *
+ * <code>bytes body = 2;</code>
+ */
+ public function setBody($var)
+ {
+ GPBUtil::checkString($var, False);
+ $this->body = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/PayloadConfig.php b/src/php/tests/qps/generated_code/Grpc/Testing/PayloadConfig.php
new file mode 100644
index 0000000000..a2fe7109ba
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/PayloadConfig.php
@@ -0,0 +1,80 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/payloads.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.PayloadConfig</code>
+ */
+class PayloadConfig extends \Google\Protobuf\Internal\Message
+{
+ protected $payload;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>.grpc.testing.ByteBufferParams bytebuf_params = 1;</code>
+ */
+ public function getBytebufParams()
+ {
+ return $this->readOneof(1);
+ }
+
+ /**
+ * <code>.grpc.testing.ByteBufferParams bytebuf_params = 1;</code>
+ */
+ public function setBytebufParams(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\ByteBufferParams::class);
+ $this->writeOneof(1, $var);
+ }
+
+ /**
+ * <code>.grpc.testing.SimpleProtoParams simple_params = 2;</code>
+ */
+ public function getSimpleParams()
+ {
+ return $this->readOneof(2);
+ }
+
+ /**
+ * <code>.grpc.testing.SimpleProtoParams simple_params = 2;</code>
+ */
+ public function setSimpleParams(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\SimpleProtoParams::class);
+ $this->writeOneof(2, $var);
+ }
+
+ /**
+ * <code>.grpc.testing.ComplexProtoParams complex_params = 3;</code>
+ */
+ public function getComplexParams()
+ {
+ return $this->readOneof(3);
+ }
+
+ /**
+ * <code>.grpc.testing.ComplexProtoParams complex_params = 3;</code>
+ */
+ public function setComplexParams(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\ComplexProtoParams::class);
+ $this->writeOneof(3, $var);
+ }
+
+ public function getPayload()
+ {
+ return $this->whichOneof("payload");
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/PayloadType.php b/src/php/tests/qps/generated_code/Grpc/Testing/PayloadType.php
new file mode 100644
index 0000000000..189ef034b4
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/PayloadType.php
@@ -0,0 +1,26 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+/**
+ * <pre>
+ * DEPRECATED, don't use. To be removed shortly.
+ * The type of payload that should be returned.
+ * </pre>
+ *
+ * Protobuf enum <code>grpc.testing.PayloadType</code>
+ */
+class PayloadType
+{
+ /**
+ * <pre>
+ * Compressable text format.
+ * </pre>
+ *
+ * <code>COMPRESSABLE = 0;</code>
+ */
+ const COMPRESSABLE = 0;
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/PoissonParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/PoissonParams.php
new file mode 100644
index 0000000000..d64edd45f0
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/PoissonParams.php
@@ -0,0 +1,61 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Parameters of poisson process distribution, which is a good representation
+ * of activity coming in from independent identical stationary sources.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.PoissonParams</code>
+ */
+class PoissonParams extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * The rate of arrivals (a.k.a. lambda parameter of the exp distribution).
+ * </pre>
+ *
+ * <code>double offered_load = 1;</code>
+ */
+ private $offered_load = 0.0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * The rate of arrivals (a.k.a. lambda parameter of the exp distribution).
+ * </pre>
+ *
+ * <code>double offered_load = 1;</code>
+ */
+ public function getOfferedLoad()
+ {
+ return $this->offered_load;
+ }
+
+ /**
+ * <pre>
+ * The rate of arrivals (a.k.a. lambda parameter of the exp distribution).
+ * </pre>
+ *
+ * <code>double offered_load = 1;</code>
+ */
+ public function setOfferedLoad($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->offered_load = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ProxyClientServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/ProxyClientServiceClient.php
new file mode 100644
index 0000000000..23c041b470
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ProxyClientServiceClient.php
@@ -0,0 +1,72 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// Copyright 2017, 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.
+//
+namespace Grpc\Testing {
+
+ class ProxyClientServiceClient extends \Grpc\BaseStub {
+
+ /**
+ * @param string $hostname hostname
+ * @param array $opts channel options
+ * @param Grpc\Channel $channel (optional) re-use channel object
+ */
+ public function __construct($hostname, $opts, $channel = null) {
+ parent::__construct($hostname, $opts, $channel);
+ }
+
+ /**
+ * @param \Grpc\Testing\Void $argument input argument
+ * @param array $metadata metadata
+ * @param array $options call options
+ */
+ public function GetConfig(\Grpc\Testing\Void $argument,
+ $metadata = [], $options = []) {
+ return $this->_simpleRequest('/grpc.testing.ProxyClientService/GetConfig',
+ $argument,
+ ['\Grpc\Testing\ClientConfig', 'decode'],
+ $metadata, $options);
+ }
+
+ /**
+ * @param array $metadata metadata
+ * @param array $options call options
+ */
+ public function ReportTime($metadata = [], $options = []) {
+ return $this->_clientStreamRequest('/grpc.testing.ProxyClientService/ReportTime',
+ ['\Grpc\Testing\Void','decode'],
+ $metadata, $options);
+ }
+
+ }
+
+}
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ProxyStat.php b/src/php/tests/qps/generated_code/Grpc/Testing/ProxyStat.php
new file mode 100644
index 0000000000..ed43be99ce
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ProxyStat.php
@@ -0,0 +1,44 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/proxy-service.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.ProxyStat</code>
+ */
+class ProxyStat extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>double latency = 1;</code>
+ */
+ private $latency = 0.0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\ProxyService::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>double latency = 1;</code>
+ */
+ public function getLatency()
+ {
+ return $this->latency;
+ }
+
+ /**
+ * <code>double latency = 1;</code>
+ */
+ public function setLatency($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->latency = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectInfo.php b/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectInfo.php
new file mode 100644
index 0000000000..dfaaa606c3
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectInfo.php
@@ -0,0 +1,71 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * For reconnect interop test only.
+ * Server tells client whether its reconnects are following the spec and the
+ * reconnect backoffs it saw.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.ReconnectInfo</code>
+ */
+class ReconnectInfo extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>bool passed = 1;</code>
+ */
+ private $passed = false;
+ /**
+ * <code>repeated int32 backoff_ms = 2;</code>
+ */
+ private $backoff_ms;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>bool passed = 1;</code>
+ */
+ public function getPassed()
+ {
+ return $this->passed;
+ }
+
+ /**
+ * <code>bool passed = 1;</code>
+ */
+ public function setPassed($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->passed = $var;
+ }
+
+ /**
+ * <code>repeated int32 backoff_ms = 2;</code>
+ */
+ public function getBackoffMs()
+ {
+ return $this->backoff_ms;
+ }
+
+ /**
+ * <code>repeated int32 backoff_ms = 2;</code>
+ */
+ public function setBackoffMs(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
+ $this->backoff_ms = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectParams.php
new file mode 100644
index 0000000000..9715855783
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectParams.php
@@ -0,0 +1,49 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * For reconnect interop test only.
+ * Client tells server what reconnection parameters it used.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.ReconnectParams</code>
+ */
+class ReconnectParams extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>int32 max_reconnect_backoff_ms = 1;</code>
+ */
+ private $max_reconnect_backoff_ms = 0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>int32 max_reconnect_backoff_ms = 1;</code>
+ */
+ public function getMaxReconnectBackoffMs()
+ {
+ return $this->max_reconnect_backoff_ms;
+ }
+
+ /**
+ * <code>int32 max_reconnect_backoff_ms = 1;</code>
+ */
+ public function setMaxReconnectBackoffMs($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->max_reconnect_backoff_ms = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/RequestResultCount.php b/src/php/tests/qps/generated_code/Grpc/Testing/RequestResultCount.php
new file mode 100644
index 0000000000..1be42b2ac9
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/RequestResultCount.php
@@ -0,0 +1,65 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/stats.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.RequestResultCount</code>
+ */
+class RequestResultCount extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>int32 status_code = 1;</code>
+ */
+ private $status_code = 0;
+ /**
+ * <code>int64 count = 2;</code>
+ */
+ private $count = 0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>int32 status_code = 1;</code>
+ */
+ public function getStatusCode()
+ {
+ return $this->status_code;
+ }
+
+ /**
+ * <code>int32 status_code = 1;</code>
+ */
+ public function setStatusCode($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->status_code = $var;
+ }
+
+ /**
+ * <code>int64 count = 2;</code>
+ */
+ public function getCount()
+ {
+ return $this->count;
+ }
+
+ /**
+ * <code>int64 count = 2;</code>
+ */
+ public function setCount($var)
+ {
+ GPBUtil::checkInt64($var);
+ $this->count = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ResponseParameters.php b/src/php/tests/qps/generated_code/Grpc/Testing/ResponseParameters.php
new file mode 100644
index 0000000000..b7a8e5ece7
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ResponseParameters.php
@@ -0,0 +1,138 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Configuration for a particular response.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.ResponseParameters</code>
+ */
+class ResponseParameters extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * Desired payload sizes in responses from the server.
+ * </pre>
+ *
+ * <code>int32 size = 1;</code>
+ */
+ private $size = 0;
+ /**
+ * <pre>
+ * Desired interval between consecutive responses in the response stream in
+ * microseconds.
+ * </pre>
+ *
+ * <code>int32 interval_us = 2;</code>
+ */
+ private $interval_us = 0;
+ /**
+ * <pre>
+ * Whether to request the server to compress the response. This field is
+ * "nullable" in order to interoperate seamlessly with clients not able to
+ * implement the full compression tests by introspecting the call to verify
+ * the response's compression status.
+ * </pre>
+ *
+ * <code>.grpc.testing.BoolValue compressed = 3;</code>
+ */
+ private $compressed = null;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * Desired payload sizes in responses from the server.
+ * </pre>
+ *
+ * <code>int32 size = 1;</code>
+ */
+ public function getSize()
+ {
+ return $this->size;
+ }
+
+ /**
+ * <pre>
+ * Desired payload sizes in responses from the server.
+ * </pre>
+ *
+ * <code>int32 size = 1;</code>
+ */
+ public function setSize($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->size = $var;
+ }
+
+ /**
+ * <pre>
+ * Desired interval between consecutive responses in the response stream in
+ * microseconds.
+ * </pre>
+ *
+ * <code>int32 interval_us = 2;</code>
+ */
+ public function getIntervalUs()
+ {
+ return $this->interval_us;
+ }
+
+ /**
+ * <pre>
+ * Desired interval between consecutive responses in the response stream in
+ * microseconds.
+ * </pre>
+ *
+ * <code>int32 interval_us = 2;</code>
+ */
+ public function setIntervalUs($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->interval_us = $var;
+ }
+
+ /**
+ * <pre>
+ * Whether to request the server to compress the response. This field is
+ * "nullable" in order to interoperate seamlessly with clients not able to
+ * implement the full compression tests by introspecting the call to verify
+ * the response's compression status.
+ * </pre>
+ *
+ * <code>.grpc.testing.BoolValue compressed = 3;</code>
+ */
+ public function getCompressed()
+ {
+ return $this->compressed;
+ }
+
+ /**
+ * <pre>
+ * Whether to request the server to compress the response. This field is
+ * "nullable" in order to interoperate seamlessly with clients not able to
+ * implement the full compression tests by introspecting the call to verify
+ * the response's compression status.
+ * </pre>
+ *
+ * <code>.grpc.testing.BoolValue compressed = 3;</code>
+ */
+ public function setCompressed(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class);
+ $this->compressed = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/RpcType.php b/src/php/tests/qps/generated_code/Grpc/Testing/RpcType.php
new file mode 100644
index 0000000000..2e664fff47
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/RpcType.php
@@ -0,0 +1,21 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+/**
+ * Protobuf enum <code>grpc.testing.RpcType</code>
+ */
+class RpcType
+{
+ /**
+ * <code>UNARY = 0;</code>
+ */
+ const UNARY = 0;
+ /**
+ * <code>STREAMING = 1;</code>
+ */
+ const STREAMING = 1;
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/Scenario.php b/src/php/tests/qps/generated_code/Grpc/Testing/Scenario.php
new file mode 100644
index 0000000000..136ed299ea
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/Scenario.php
@@ -0,0 +1,291 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * A single performance scenario: input to qps_json_driver
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.Scenario</code>
+ */
+class Scenario extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * Human readable name for this scenario
+ * </pre>
+ *
+ * <code>string name = 1;</code>
+ */
+ private $name = '';
+ /**
+ * <pre>
+ * Client configuration
+ * </pre>
+ *
+ * <code>.grpc.testing.ClientConfig client_config = 2;</code>
+ */
+ private $client_config = null;
+ /**
+ * <pre>
+ * Number of clients to start for the test
+ * </pre>
+ *
+ * <code>int32 num_clients = 3;</code>
+ */
+ private $num_clients = 0;
+ /**
+ * <pre>
+ * Server configuration
+ * </pre>
+ *
+ * <code>.grpc.testing.ServerConfig server_config = 4;</code>
+ */
+ private $server_config = null;
+ /**
+ * <pre>
+ * Number of servers to start for the test
+ * </pre>
+ *
+ * <code>int32 num_servers = 5;</code>
+ */
+ private $num_servers = 0;
+ /**
+ * <pre>
+ * Warmup period, in seconds
+ * </pre>
+ *
+ * <code>int32 warmup_seconds = 6;</code>
+ */
+ private $warmup_seconds = 0;
+ /**
+ * <pre>
+ * Benchmark time, in seconds
+ * </pre>
+ *
+ * <code>int32 benchmark_seconds = 7;</code>
+ */
+ private $benchmark_seconds = 0;
+ /**
+ * <pre>
+ * Number of workers to spawn locally (usually zero)
+ * </pre>
+ *
+ * <code>int32 spawn_local_worker_count = 8;</code>
+ */
+ private $spawn_local_worker_count = 0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * Human readable name for this scenario
+ * </pre>
+ *
+ * <code>string name = 1;</code>
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * <pre>
+ * Human readable name for this scenario
+ * </pre>
+ *
+ * <code>string name = 1;</code>
+ */
+ public function setName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->name = $var;
+ }
+
+ /**
+ * <pre>
+ * Client configuration
+ * </pre>
+ *
+ * <code>.grpc.testing.ClientConfig client_config = 2;</code>
+ */
+ public function getClientConfig()
+ {
+ return $this->client_config;
+ }
+
+ /**
+ * <pre>
+ * Client configuration
+ * </pre>
+ *
+ * <code>.grpc.testing.ClientConfig client_config = 2;</code>
+ */
+ public function setClientConfig(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\ClientConfig::class);
+ $this->client_config = $var;
+ }
+
+ /**
+ * <pre>
+ * Number of clients to start for the test
+ * </pre>
+ *
+ * <code>int32 num_clients = 3;</code>
+ */
+ public function getNumClients()
+ {
+ return $this->num_clients;
+ }
+
+ /**
+ * <pre>
+ * Number of clients to start for the test
+ * </pre>
+ *
+ * <code>int32 num_clients = 3;</code>
+ */
+ public function setNumClients($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->num_clients = $var;
+ }
+
+ /**
+ * <pre>
+ * Server configuration
+ * </pre>
+ *
+ * <code>.grpc.testing.ServerConfig server_config = 4;</code>
+ */
+ public function getServerConfig()
+ {
+ return $this->server_config;
+ }
+
+ /**
+ * <pre>
+ * Server configuration
+ * </pre>
+ *
+ * <code>.grpc.testing.ServerConfig server_config = 4;</code>
+ */
+ public function setServerConfig(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\ServerConfig::class);
+ $this->server_config = $var;
+ }
+
+ /**
+ * <pre>
+ * Number of servers to start for the test
+ * </pre>
+ *
+ * <code>int32 num_servers = 5;</code>
+ */
+ public function getNumServers()
+ {
+ return $this->num_servers;
+ }
+
+ /**
+ * <pre>
+ * Number of servers to start for the test
+ * </pre>
+ *
+ * <code>int32 num_servers = 5;</code>
+ */
+ public function setNumServers($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->num_servers = $var;
+ }
+
+ /**
+ * <pre>
+ * Warmup period, in seconds
+ * </pre>
+ *
+ * <code>int32 warmup_seconds = 6;</code>
+ */
+ public function getWarmupSeconds()
+ {
+ return $this->warmup_seconds;
+ }
+
+ /**
+ * <pre>
+ * Warmup period, in seconds
+ * </pre>
+ *
+ * <code>int32 warmup_seconds = 6;</code>
+ */
+ public function setWarmupSeconds($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->warmup_seconds = $var;
+ }
+
+ /**
+ * <pre>
+ * Benchmark time, in seconds
+ * </pre>
+ *
+ * <code>int32 benchmark_seconds = 7;</code>
+ */
+ public function getBenchmarkSeconds()
+ {
+ return $this->benchmark_seconds;
+ }
+
+ /**
+ * <pre>
+ * Benchmark time, in seconds
+ * </pre>
+ *
+ * <code>int32 benchmark_seconds = 7;</code>
+ */
+ public function setBenchmarkSeconds($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->benchmark_seconds = $var;
+ }
+
+ /**
+ * <pre>
+ * Number of workers to spawn locally (usually zero)
+ * </pre>
+ *
+ * <code>int32 spawn_local_worker_count = 8;</code>
+ */
+ public function getSpawnLocalWorkerCount()
+ {
+ return $this->spawn_local_worker_count;
+ }
+
+ /**
+ * <pre>
+ * Number of workers to spawn locally (usually zero)
+ * </pre>
+ *
+ * <code>int32 spawn_local_worker_count = 8;</code>
+ */
+ public function setSpawnLocalWorkerCount($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->spawn_local_worker_count = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResult.php b/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResult.php
new file mode 100644
index 0000000000..809cd96244
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResult.php
@@ -0,0 +1,312 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Results of a single benchmark scenario.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.ScenarioResult</code>
+ */
+class ScenarioResult extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * Inputs used to run the scenario.
+ * </pre>
+ *
+ * <code>.grpc.testing.Scenario scenario = 1;</code>
+ */
+ private $scenario = null;
+ /**
+ * <pre>
+ * Histograms from all clients merged into one histogram.
+ * </pre>
+ *
+ * <code>.grpc.testing.HistogramData latencies = 2;</code>
+ */
+ private $latencies = null;
+ /**
+ * <pre>
+ * Client stats for each client
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.ClientStats client_stats = 3;</code>
+ */
+ private $client_stats;
+ /**
+ * <pre>
+ * Server stats for each server
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.ServerStats server_stats = 4;</code>
+ */
+ private $server_stats;
+ /**
+ * <pre>
+ * Number of cores available to each server
+ * </pre>
+ *
+ * <code>repeated int32 server_cores = 5;</code>
+ */
+ private $server_cores;
+ /**
+ * <pre>
+ * An after-the-fact computed summary
+ * </pre>
+ *
+ * <code>.grpc.testing.ScenarioResultSummary summary = 6;</code>
+ */
+ private $summary = null;
+ /**
+ * <pre>
+ * Information on success or failure of each worker
+ * </pre>
+ *
+ * <code>repeated bool client_success = 7;</code>
+ */
+ private $client_success;
+ /**
+ * <code>repeated bool server_success = 8;</code>
+ */
+ private $server_success;
+ /**
+ * <pre>
+ * Number of failed requests (one row per status code seen)
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.RequestResultCount request_results = 9;</code>
+ */
+ private $request_results;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * Inputs used to run the scenario.
+ * </pre>
+ *
+ * <code>.grpc.testing.Scenario scenario = 1;</code>
+ */
+ public function getScenario()
+ {
+ return $this->scenario;
+ }
+
+ /**
+ * <pre>
+ * Inputs used to run the scenario.
+ * </pre>
+ *
+ * <code>.grpc.testing.Scenario scenario = 1;</code>
+ */
+ public function setScenario(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\Scenario::class);
+ $this->scenario = $var;
+ }
+
+ /**
+ * <pre>
+ * Histograms from all clients merged into one histogram.
+ * </pre>
+ *
+ * <code>.grpc.testing.HistogramData latencies = 2;</code>
+ */
+ public function getLatencies()
+ {
+ return $this->latencies;
+ }
+
+ /**
+ * <pre>
+ * Histograms from all clients merged into one histogram.
+ * </pre>
+ *
+ * <code>.grpc.testing.HistogramData latencies = 2;</code>
+ */
+ public function setLatencies(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\HistogramData::class);
+ $this->latencies = $var;
+ }
+
+ /**
+ * <pre>
+ * Client stats for each client
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.ClientStats client_stats = 3;</code>
+ */
+ public function getClientStats()
+ {
+ return $this->client_stats;
+ }
+
+ /**
+ * <pre>
+ * Client stats for each client
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.ClientStats client_stats = 3;</code>
+ */
+ public function setClientStats(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\ClientStats::class);
+ $this->client_stats = $var;
+ }
+
+ /**
+ * <pre>
+ * Server stats for each server
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.ServerStats server_stats = 4;</code>
+ */
+ public function getServerStats()
+ {
+ return $this->server_stats;
+ }
+
+ /**
+ * <pre>
+ * Server stats for each server
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.ServerStats server_stats = 4;</code>
+ */
+ public function setServerStats(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\ServerStats::class);
+ $this->server_stats = $var;
+ }
+
+ /**
+ * <pre>
+ * Number of cores available to each server
+ * </pre>
+ *
+ * <code>repeated int32 server_cores = 5;</code>
+ */
+ public function getServerCores()
+ {
+ return $this->server_cores;
+ }
+
+ /**
+ * <pre>
+ * Number of cores available to each server
+ * </pre>
+ *
+ * <code>repeated int32 server_cores = 5;</code>
+ */
+ public function setServerCores(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
+ $this->server_cores = $var;
+ }
+
+ /**
+ * <pre>
+ * An after-the-fact computed summary
+ * </pre>
+ *
+ * <code>.grpc.testing.ScenarioResultSummary summary = 6;</code>
+ */
+ public function getSummary()
+ {
+ return $this->summary;
+ }
+
+ /**
+ * <pre>
+ * An after-the-fact computed summary
+ * </pre>
+ *
+ * <code>.grpc.testing.ScenarioResultSummary summary = 6;</code>
+ */
+ public function setSummary(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\ScenarioResultSummary::class);
+ $this->summary = $var;
+ }
+
+ /**
+ * <pre>
+ * Information on success or failure of each worker
+ * </pre>
+ *
+ * <code>repeated bool client_success = 7;</code>
+ */
+ public function getClientSuccess()
+ {
+ return $this->client_success;
+ }
+
+ /**
+ * <pre>
+ * Information on success or failure of each worker
+ * </pre>
+ *
+ * <code>repeated bool client_success = 7;</code>
+ */
+ public function setClientSuccess(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::BOOL);
+ $this->client_success = $var;
+ }
+
+ /**
+ * <code>repeated bool server_success = 8;</code>
+ */
+ public function getServerSuccess()
+ {
+ return $this->server_success;
+ }
+
+ /**
+ * <code>repeated bool server_success = 8;</code>
+ */
+ public function setServerSuccess(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::BOOL);
+ $this->server_success = $var;
+ }
+
+ /**
+ * <pre>
+ * Number of failed requests (one row per status code seen)
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.RequestResultCount request_results = 9;</code>
+ */
+ public function getRequestResults()
+ {
+ return $this->request_results;
+ }
+
+ /**
+ * <pre>
+ * Number of failed requests (one row per status code seen)
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.RequestResultCount request_results = 9;</code>
+ */
+ public function setRequestResults(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\RequestResultCount::class);
+ $this->request_results = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResultSummary.php b/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResultSummary.php
new file mode 100644
index 0000000000..7520cff78e
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ScenarioResultSummary.php
@@ -0,0 +1,430 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Basic summary that can be computed from ClientStats and ServerStats
+ * once the scenario has finished.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.ScenarioResultSummary</code>
+ */
+class ScenarioResultSummary extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * Total number of operations per second over all clients.
+ * </pre>
+ *
+ * <code>double qps = 1;</code>
+ */
+ private $qps = 0.0;
+ /**
+ * <pre>
+ * QPS per one server core.
+ * </pre>
+ *
+ * <code>double qps_per_server_core = 2;</code>
+ */
+ private $qps_per_server_core = 0.0;
+ /**
+ * <pre>
+ * server load based on system_time (0.85 =&gt; 85%)
+ * </pre>
+ *
+ * <code>double server_system_time = 3;</code>
+ */
+ private $server_system_time = 0.0;
+ /**
+ * <pre>
+ * server load based on user_time (0.85 =&gt; 85%)
+ * </pre>
+ *
+ * <code>double server_user_time = 4;</code>
+ */
+ private $server_user_time = 0.0;
+ /**
+ * <pre>
+ * client load based on system_time (0.85 =&gt; 85%)
+ * </pre>
+ *
+ * <code>double client_system_time = 5;</code>
+ */
+ private $client_system_time = 0.0;
+ /**
+ * <pre>
+ * client load based on user_time (0.85 =&gt; 85%)
+ * </pre>
+ *
+ * <code>double client_user_time = 6;</code>
+ */
+ private $client_user_time = 0.0;
+ /**
+ * <pre>
+ * X% latency percentiles (in nanoseconds)
+ * </pre>
+ *
+ * <code>double latency_50 = 7;</code>
+ */
+ private $latency_50 = 0.0;
+ /**
+ * <code>double latency_90 = 8;</code>
+ */
+ private $latency_90 = 0.0;
+ /**
+ * <code>double latency_95 = 9;</code>
+ */
+ private $latency_95 = 0.0;
+ /**
+ * <code>double latency_99 = 10;</code>
+ */
+ private $latency_99 = 0.0;
+ /**
+ * <code>double latency_999 = 11;</code>
+ */
+ private $latency_999 = 0.0;
+ /**
+ * <pre>
+ * server cpu usage percentage
+ * </pre>
+ *
+ * <code>double server_cpu_usage = 12;</code>
+ */
+ private $server_cpu_usage = 0.0;
+ /**
+ * <pre>
+ * Number of requests that succeeded/failed
+ * </pre>
+ *
+ * <code>double successful_requests_per_second = 13;</code>
+ */
+ private $successful_requests_per_second = 0.0;
+ /**
+ * <code>double failed_requests_per_second = 14;</code>
+ */
+ private $failed_requests_per_second = 0.0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * Total number of operations per second over all clients.
+ * </pre>
+ *
+ * <code>double qps = 1;</code>
+ */
+ public function getQps()
+ {
+ return $this->qps;
+ }
+
+ /**
+ * <pre>
+ * Total number of operations per second over all clients.
+ * </pre>
+ *
+ * <code>double qps = 1;</code>
+ */
+ public function setQps($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->qps = $var;
+ }
+
+ /**
+ * <pre>
+ * QPS per one server core.
+ * </pre>
+ *
+ * <code>double qps_per_server_core = 2;</code>
+ */
+ public function getQpsPerServerCore()
+ {
+ return $this->qps_per_server_core;
+ }
+
+ /**
+ * <pre>
+ * QPS per one server core.
+ * </pre>
+ *
+ * <code>double qps_per_server_core = 2;</code>
+ */
+ public function setQpsPerServerCore($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->qps_per_server_core = $var;
+ }
+
+ /**
+ * <pre>
+ * server load based on system_time (0.85 =&gt; 85%)
+ * </pre>
+ *
+ * <code>double server_system_time = 3;</code>
+ */
+ public function getServerSystemTime()
+ {
+ return $this->server_system_time;
+ }
+
+ /**
+ * <pre>
+ * server load based on system_time (0.85 =&gt; 85%)
+ * </pre>
+ *
+ * <code>double server_system_time = 3;</code>
+ */
+ public function setServerSystemTime($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->server_system_time = $var;
+ }
+
+ /**
+ * <pre>
+ * server load based on user_time (0.85 =&gt; 85%)
+ * </pre>
+ *
+ * <code>double server_user_time = 4;</code>
+ */
+ public function getServerUserTime()
+ {
+ return $this->server_user_time;
+ }
+
+ /**
+ * <pre>
+ * server load based on user_time (0.85 =&gt; 85%)
+ * </pre>
+ *
+ * <code>double server_user_time = 4;</code>
+ */
+ public function setServerUserTime($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->server_user_time = $var;
+ }
+
+ /**
+ * <pre>
+ * client load based on system_time (0.85 =&gt; 85%)
+ * </pre>
+ *
+ * <code>double client_system_time = 5;</code>
+ */
+ public function getClientSystemTime()
+ {
+ return $this->client_system_time;
+ }
+
+ /**
+ * <pre>
+ * client load based on system_time (0.85 =&gt; 85%)
+ * </pre>
+ *
+ * <code>double client_system_time = 5;</code>
+ */
+ public function setClientSystemTime($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->client_system_time = $var;
+ }
+
+ /**
+ * <pre>
+ * client load based on user_time (0.85 =&gt; 85%)
+ * </pre>
+ *
+ * <code>double client_user_time = 6;</code>
+ */
+ public function getClientUserTime()
+ {
+ return $this->client_user_time;
+ }
+
+ /**
+ * <pre>
+ * client load based on user_time (0.85 =&gt; 85%)
+ * </pre>
+ *
+ * <code>double client_user_time = 6;</code>
+ */
+ public function setClientUserTime($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->client_user_time = $var;
+ }
+
+ /**
+ * <pre>
+ * X% latency percentiles (in nanoseconds)
+ * </pre>
+ *
+ * <code>double latency_50 = 7;</code>
+ */
+ public function getLatency50()
+ {
+ return $this->latency_50;
+ }
+
+ /**
+ * <pre>
+ * X% latency percentiles (in nanoseconds)
+ * </pre>
+ *
+ * <code>double latency_50 = 7;</code>
+ */
+ public function setLatency50($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->latency_50 = $var;
+ }
+
+ /**
+ * <code>double latency_90 = 8;</code>
+ */
+ public function getLatency90()
+ {
+ return $this->latency_90;
+ }
+
+ /**
+ * <code>double latency_90 = 8;</code>
+ */
+ public function setLatency90($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->latency_90 = $var;
+ }
+
+ /**
+ * <code>double latency_95 = 9;</code>
+ */
+ public function getLatency95()
+ {
+ return $this->latency_95;
+ }
+
+ /**
+ * <code>double latency_95 = 9;</code>
+ */
+ public function setLatency95($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->latency_95 = $var;
+ }
+
+ /**
+ * <code>double latency_99 = 10;</code>
+ */
+ public function getLatency99()
+ {
+ return $this->latency_99;
+ }
+
+ /**
+ * <code>double latency_99 = 10;</code>
+ */
+ public function setLatency99($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->latency_99 = $var;
+ }
+
+ /**
+ * <code>double latency_999 = 11;</code>
+ */
+ public function getLatency999()
+ {
+ return $this->latency_999;
+ }
+
+ /**
+ * <code>double latency_999 = 11;</code>
+ */
+ public function setLatency999($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->latency_999 = $var;
+ }
+
+ /**
+ * <pre>
+ * server cpu usage percentage
+ * </pre>
+ *
+ * <code>double server_cpu_usage = 12;</code>
+ */
+ public function getServerCpuUsage()
+ {
+ return $this->server_cpu_usage;
+ }
+
+ /**
+ * <pre>
+ * server cpu usage percentage
+ * </pre>
+ *
+ * <code>double server_cpu_usage = 12;</code>
+ */
+ public function setServerCpuUsage($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->server_cpu_usage = $var;
+ }
+
+ /**
+ * <pre>
+ * Number of requests that succeeded/failed
+ * </pre>
+ *
+ * <code>double successful_requests_per_second = 13;</code>
+ */
+ public function getSuccessfulRequestsPerSecond()
+ {
+ return $this->successful_requests_per_second;
+ }
+
+ /**
+ * <pre>
+ * Number of requests that succeeded/failed
+ * </pre>
+ *
+ * <code>double successful_requests_per_second = 13;</code>
+ */
+ public function setSuccessfulRequestsPerSecond($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->successful_requests_per_second = $var;
+ }
+
+ /**
+ * <code>double failed_requests_per_second = 14;</code>
+ */
+ public function getFailedRequestsPerSecond()
+ {
+ return $this->failed_requests_per_second;
+ }
+
+ /**
+ * <code>double failed_requests_per_second = 14;</code>
+ */
+ public function setFailedRequestsPerSecond($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->failed_requests_per_second = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/Scenarios.php b/src/php/tests/qps/generated_code/Grpc/Testing/Scenarios.php
new file mode 100644
index 0000000000..278f555b76
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/Scenarios.php
@@ -0,0 +1,48 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * A set of scenarios to be run with qps_json_driver
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.Scenarios</code>
+ */
+class Scenarios extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>repeated .grpc.testing.Scenario scenarios = 1;</code>
+ */
+ private $scenarios;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>repeated .grpc.testing.Scenario scenarios = 1;</code>
+ */
+ public function getScenarios()
+ {
+ return $this->scenarios;
+ }
+
+ /**
+ * <code>repeated .grpc.testing.Scenario scenarios = 1;</code>
+ */
+ public function setScenarios(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\Scenario::class);
+ $this->scenarios = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/SecurityParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/SecurityParams.php
new file mode 100644
index 0000000000..27a5b95cc9
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/SecurityParams.php
@@ -0,0 +1,69 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * presence of SecurityParams implies use of TLS
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.SecurityParams</code>
+ */
+class SecurityParams extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>bool use_test_ca = 1;</code>
+ */
+ private $use_test_ca = false;
+ /**
+ * <code>string server_host_override = 2;</code>
+ */
+ private $server_host_override = '';
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>bool use_test_ca = 1;</code>
+ */
+ public function getUseTestCa()
+ {
+ return $this->use_test_ca;
+ }
+
+ /**
+ * <code>bool use_test_ca = 1;</code>
+ */
+ public function setUseTestCa($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->use_test_ca = $var;
+ }
+
+ /**
+ * <code>string server_host_override = 2;</code>
+ */
+ public function getServerHostOverride()
+ {
+ return $this->server_host_override;
+ }
+
+ /**
+ * <code>string server_host_override = 2;</code>
+ */
+ public function setServerHostOverride($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->server_host_override = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ServerArgs.php b/src/php/tests/qps/generated_code/Grpc/Testing/ServerArgs.php
new file mode 100644
index 0000000000..0d84b80124
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ServerArgs.php
@@ -0,0 +1,63 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.ServerArgs</code>
+ */
+class ServerArgs extends \Google\Protobuf\Internal\Message
+{
+ protected $argtype;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>.grpc.testing.ServerConfig setup = 1;</code>
+ */
+ public function getSetup()
+ {
+ return $this->readOneof(1);
+ }
+
+ /**
+ * <code>.grpc.testing.ServerConfig setup = 1;</code>
+ */
+ public function setSetup(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\ServerConfig::class);
+ $this->writeOneof(1, $var);
+ }
+
+ /**
+ * <code>.grpc.testing.Mark mark = 2;</code>
+ */
+ public function getMark()
+ {
+ return $this->readOneof(2);
+ }
+
+ /**
+ * <code>.grpc.testing.Mark mark = 2;</code>
+ */
+ public function setMark(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\Mark::class);
+ $this->writeOneof(2, $var);
+ }
+
+ public function getArgtype()
+ {
+ return $this->whichOneof("argtype");
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ServerConfig.php b/src/php/tests/qps/generated_code/Grpc/Testing/ServerConfig.php
new file mode 100644
index 0000000000..e2bcede48c
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ServerConfig.php
@@ -0,0 +1,305 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.ServerConfig</code>
+ */
+class ServerConfig extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>.grpc.testing.ServerType server_type = 1;</code>
+ */
+ private $server_type = 0;
+ /**
+ * <code>.grpc.testing.SecurityParams security_params = 2;</code>
+ */
+ private $security_params = null;
+ /**
+ * <pre>
+ * Port on which to listen. Zero means pick unused port.
+ * </pre>
+ *
+ * <code>int32 port = 4;</code>
+ */
+ private $port = 0;
+ /**
+ * <pre>
+ * Only for async server. Number of threads used to serve the requests.
+ * </pre>
+ *
+ * <code>int32 async_server_threads = 7;</code>
+ */
+ private $async_server_threads = 0;
+ /**
+ * <pre>
+ * Specify the number of cores to limit server to, if desired
+ * </pre>
+ *
+ * <code>int32 core_limit = 8;</code>
+ */
+ private $core_limit = 0;
+ /**
+ * <pre>
+ * payload config, used in generic server.
+ * Note this must NOT be used in proto (non-generic) servers. For proto servers,
+ * 'response sizes' must be configured from the 'response_size' field of the
+ * 'SimpleRequest' objects in RPC requests.
+ * </pre>
+ *
+ * <code>.grpc.testing.PayloadConfig payload_config = 9;</code>
+ */
+ private $payload_config = null;
+ /**
+ * <pre>
+ * Specify the cores we should run the server on, if desired
+ * </pre>
+ *
+ * <code>repeated int32 core_list = 10;</code>
+ */
+ private $core_list;
+ /**
+ * <pre>
+ * If we use an OTHER_SERVER client_type, this string gives more detail
+ * </pre>
+ *
+ * <code>string other_server_api = 11;</code>
+ */
+ private $other_server_api = '';
+ /**
+ * <pre>
+ * Buffer pool size (no buffer pool specified if unset)
+ * </pre>
+ *
+ * <code>int32 resource_quota_size = 1001;</code>
+ */
+ private $resource_quota_size = 0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>.grpc.testing.ServerType server_type = 1;</code>
+ */
+ public function getServerType()
+ {
+ return $this->server_type;
+ }
+
+ /**
+ * <code>.grpc.testing.ServerType server_type = 1;</code>
+ */
+ public function setServerType($var)
+ {
+ GPBUtil::checkEnum($var, \Grpc\Testing\ServerType::class);
+ $this->server_type = $var;
+ }
+
+ /**
+ * <code>.grpc.testing.SecurityParams security_params = 2;</code>
+ */
+ public function getSecurityParams()
+ {
+ return $this->security_params;
+ }
+
+ /**
+ * <code>.grpc.testing.SecurityParams security_params = 2;</code>
+ */
+ public function setSecurityParams(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\SecurityParams::class);
+ $this->security_params = $var;
+ }
+
+ /**
+ * <pre>
+ * Port on which to listen. Zero means pick unused port.
+ * </pre>
+ *
+ * <code>int32 port = 4;</code>
+ */
+ public function getPort()
+ {
+ return $this->port;
+ }
+
+ /**
+ * <pre>
+ * Port on which to listen. Zero means pick unused port.
+ * </pre>
+ *
+ * <code>int32 port = 4;</code>
+ */
+ public function setPort($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->port = $var;
+ }
+
+ /**
+ * <pre>
+ * Only for async server. Number of threads used to serve the requests.
+ * </pre>
+ *
+ * <code>int32 async_server_threads = 7;</code>
+ */
+ public function getAsyncServerThreads()
+ {
+ return $this->async_server_threads;
+ }
+
+ /**
+ * <pre>
+ * Only for async server. Number of threads used to serve the requests.
+ * </pre>
+ *
+ * <code>int32 async_server_threads = 7;</code>
+ */
+ public function setAsyncServerThreads($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->async_server_threads = $var;
+ }
+
+ /**
+ * <pre>
+ * Specify the number of cores to limit server to, if desired
+ * </pre>
+ *
+ * <code>int32 core_limit = 8;</code>
+ */
+ public function getCoreLimit()
+ {
+ return $this->core_limit;
+ }
+
+ /**
+ * <pre>
+ * Specify the number of cores to limit server to, if desired
+ * </pre>
+ *
+ * <code>int32 core_limit = 8;</code>
+ */
+ public function setCoreLimit($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->core_limit = $var;
+ }
+
+ /**
+ * <pre>
+ * payload config, used in generic server.
+ * Note this must NOT be used in proto (non-generic) servers. For proto servers,
+ * 'response sizes' must be configured from the 'response_size' field of the
+ * 'SimpleRequest' objects in RPC requests.
+ * </pre>
+ *
+ * <code>.grpc.testing.PayloadConfig payload_config = 9;</code>
+ */
+ public function getPayloadConfig()
+ {
+ return $this->payload_config;
+ }
+
+ /**
+ * <pre>
+ * payload config, used in generic server.
+ * Note this must NOT be used in proto (non-generic) servers. For proto servers,
+ * 'response sizes' must be configured from the 'response_size' field of the
+ * 'SimpleRequest' objects in RPC requests.
+ * </pre>
+ *
+ * <code>.grpc.testing.PayloadConfig payload_config = 9;</code>
+ */
+ public function setPayloadConfig(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\PayloadConfig::class);
+ $this->payload_config = $var;
+ }
+
+ /**
+ * <pre>
+ * Specify the cores we should run the server on, if desired
+ * </pre>
+ *
+ * <code>repeated int32 core_list = 10;</code>
+ */
+ public function getCoreList()
+ {
+ return $this->core_list;
+ }
+
+ /**
+ * <pre>
+ * Specify the cores we should run the server on, if desired
+ * </pre>
+ *
+ * <code>repeated int32 core_list = 10;</code>
+ */
+ public function setCoreList(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
+ $this->core_list = $var;
+ }
+
+ /**
+ * <pre>
+ * If we use an OTHER_SERVER client_type, this string gives more detail
+ * </pre>
+ *
+ * <code>string other_server_api = 11;</code>
+ */
+ public function getOtherServerApi()
+ {
+ return $this->other_server_api;
+ }
+
+ /**
+ * <pre>
+ * If we use an OTHER_SERVER client_type, this string gives more detail
+ * </pre>
+ *
+ * <code>string other_server_api = 11;</code>
+ */
+ public function setOtherServerApi($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->other_server_api = $var;
+ }
+
+ /**
+ * <pre>
+ * Buffer pool size (no buffer pool specified if unset)
+ * </pre>
+ *
+ * <code>int32 resource_quota_size = 1001;</code>
+ */
+ public function getResourceQuotaSize()
+ {
+ return $this->resource_quota_size;
+ }
+
+ /**
+ * <pre>
+ * Buffer pool size (no buffer pool specified if unset)
+ * </pre>
+ *
+ * <code>int32 resource_quota_size = 1001;</code>
+ */
+ public function setResourceQuotaSize($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->resource_quota_size = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ServerStats.php b/src/php/tests/qps/generated_code/Grpc/Testing/ServerStats.php
new file mode 100644
index 0000000000..98b2af764c
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ServerStats.php
@@ -0,0 +1,191 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/stats.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.ServerStats</code>
+ */
+class ServerStats extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * wall clock time change in seconds since last reset
+ * </pre>
+ *
+ * <code>double time_elapsed = 1;</code>
+ */
+ private $time_elapsed = 0.0;
+ /**
+ * <pre>
+ * change in user time (in seconds) used by the server since last reset
+ * </pre>
+ *
+ * <code>double time_user = 2;</code>
+ */
+ private $time_user = 0.0;
+ /**
+ * <pre>
+ * change in server time (in seconds) used by the server process and all
+ * threads since last reset
+ * </pre>
+ *
+ * <code>double time_system = 3;</code>
+ */
+ private $time_system = 0.0;
+ /**
+ * <pre>
+ * change in total cpu time of the server (data from proc/stat)
+ * </pre>
+ *
+ * <code>uint64 total_cpu_time = 4;</code>
+ */
+ private $total_cpu_time = 0;
+ /**
+ * <pre>
+ * change in idle time of the server (data from proc/stat)
+ * </pre>
+ *
+ * <code>uint64 idle_cpu_time = 5;</code>
+ */
+ private $idle_cpu_time = 0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * wall clock time change in seconds since last reset
+ * </pre>
+ *
+ * <code>double time_elapsed = 1;</code>
+ */
+ public function getTimeElapsed()
+ {
+ return $this->time_elapsed;
+ }
+
+ /**
+ * <pre>
+ * wall clock time change in seconds since last reset
+ * </pre>
+ *
+ * <code>double time_elapsed = 1;</code>
+ */
+ public function setTimeElapsed($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->time_elapsed = $var;
+ }
+
+ /**
+ * <pre>
+ * change in user time (in seconds) used by the server since last reset
+ * </pre>
+ *
+ * <code>double time_user = 2;</code>
+ */
+ public function getTimeUser()
+ {
+ return $this->time_user;
+ }
+
+ /**
+ * <pre>
+ * change in user time (in seconds) used by the server since last reset
+ * </pre>
+ *
+ * <code>double time_user = 2;</code>
+ */
+ public function setTimeUser($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->time_user = $var;
+ }
+
+ /**
+ * <pre>
+ * change in server time (in seconds) used by the server process and all
+ * threads since last reset
+ * </pre>
+ *
+ * <code>double time_system = 3;</code>
+ */
+ public function getTimeSystem()
+ {
+ return $this->time_system;
+ }
+
+ /**
+ * <pre>
+ * change in server time (in seconds) used by the server process and all
+ * threads since last reset
+ * </pre>
+ *
+ * <code>double time_system = 3;</code>
+ */
+ public function setTimeSystem($var)
+ {
+ GPBUtil::checkDouble($var);
+ $this->time_system = $var;
+ }
+
+ /**
+ * <pre>
+ * change in total cpu time of the server (data from proc/stat)
+ * </pre>
+ *
+ * <code>uint64 total_cpu_time = 4;</code>
+ */
+ public function getTotalCpuTime()
+ {
+ return $this->total_cpu_time;
+ }
+
+ /**
+ * <pre>
+ * change in total cpu time of the server (data from proc/stat)
+ * </pre>
+ *
+ * <code>uint64 total_cpu_time = 4;</code>
+ */
+ public function setTotalCpuTime($var)
+ {
+ GPBUtil::checkUint64($var);
+ $this->total_cpu_time = $var;
+ }
+
+ /**
+ * <pre>
+ * change in idle time of the server (data from proc/stat)
+ * </pre>
+ *
+ * <code>uint64 idle_cpu_time = 5;</code>
+ */
+ public function getIdleCpuTime()
+ {
+ return $this->idle_cpu_time;
+ }
+
+ /**
+ * <pre>
+ * change in idle time of the server (data from proc/stat)
+ * </pre>
+ *
+ * <code>uint64 idle_cpu_time = 5;</code>
+ */
+ public function setIdleCpuTime($var)
+ {
+ GPBUtil::checkUint64($var);
+ $this->idle_cpu_time = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ServerStatus.php b/src/php/tests/qps/generated_code/Grpc/Testing/ServerStatus.php
new file mode 100644
index 0000000000..d293f03fbd
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ServerStatus.php
@@ -0,0 +1,110 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.ServerStatus</code>
+ */
+class ServerStatus extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>.grpc.testing.ServerStats stats = 1;</code>
+ */
+ private $stats = null;
+ /**
+ * <pre>
+ * the port bound by the server
+ * </pre>
+ *
+ * <code>int32 port = 2;</code>
+ */
+ private $port = 0;
+ /**
+ * <pre>
+ * Number of cores available to the server
+ * </pre>
+ *
+ * <code>int32 cores = 3;</code>
+ */
+ private $cores = 0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>.grpc.testing.ServerStats stats = 1;</code>
+ */
+ public function getStats()
+ {
+ return $this->stats;
+ }
+
+ /**
+ * <code>.grpc.testing.ServerStats stats = 1;</code>
+ */
+ public function setStats(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\ServerStats::class);
+ $this->stats = $var;
+ }
+
+ /**
+ * <pre>
+ * the port bound by the server
+ * </pre>
+ *
+ * <code>int32 port = 2;</code>
+ */
+ public function getPort()
+ {
+ return $this->port;
+ }
+
+ /**
+ * <pre>
+ * the port bound by the server
+ * </pre>
+ *
+ * <code>int32 port = 2;</code>
+ */
+ public function setPort($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->port = $var;
+ }
+
+ /**
+ * <pre>
+ * Number of cores available to the server
+ * </pre>
+ *
+ * <code>int32 cores = 3;</code>
+ */
+ public function getCores()
+ {
+ return $this->cores;
+ }
+
+ /**
+ * <pre>
+ * Number of cores available to the server
+ * </pre>
+ *
+ * <code>int32 cores = 3;</code>
+ */
+ public function setCores($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->cores = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ServerType.php b/src/php/tests/qps/generated_code/Grpc/Testing/ServerType.php
new file mode 100644
index 0000000000..605c83c3f7
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ServerType.php
@@ -0,0 +1,33 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+/**
+ * Protobuf enum <code>grpc.testing.ServerType</code>
+ */
+class ServerType
+{
+ /**
+ * <code>SYNC_SERVER = 0;</code>
+ */
+ const SYNC_SERVER = 0;
+ /**
+ * <code>ASYNC_SERVER = 1;</code>
+ */
+ const ASYNC_SERVER = 1;
+ /**
+ * <code>ASYNC_GENERIC_SERVER = 2;</code>
+ */
+ const ASYNC_GENERIC_SERVER = 2;
+ /**
+ * <pre>
+ * used for some language-specific variants
+ * </pre>
+ *
+ * <code>OTHER_SERVER = 3;</code>
+ */
+ const OTHER_SERVER = 3;
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/SimpleProtoParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/SimpleProtoParams.php
new file mode 100644
index 0000000000..29834a3be7
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/SimpleProtoParams.php
@@ -0,0 +1,65 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/payloads.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.SimpleProtoParams</code>
+ */
+class SimpleProtoParams extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <code>int32 req_size = 1;</code>
+ */
+ private $req_size = 0;
+ /**
+ * <code>int32 resp_size = 2;</code>
+ */
+ private $resp_size = 0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <code>int32 req_size = 1;</code>
+ */
+ public function getReqSize()
+ {
+ return $this->req_size;
+ }
+
+ /**
+ * <code>int32 req_size = 1;</code>
+ */
+ public function setReqSize($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->req_size = $var;
+ }
+
+ /**
+ * <code>int32 resp_size = 2;</code>
+ */
+ public function getRespSize()
+ {
+ return $this->resp_size;
+ }
+
+ /**
+ * <code>int32 resp_size = 2;</code>
+ */
+ public function setRespSize($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->resp_size = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/SimpleRequest.php b/src/php/tests/qps/generated_code/Grpc/Testing/SimpleRequest.php
new file mode 100644
index 0000000000..f84c95319f
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/SimpleRequest.php
@@ -0,0 +1,306 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Unary request.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.SimpleRequest</code>
+ */
+class SimpleRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * DEPRECATED, don't use. To be removed shortly.
+ * Desired payload type in the response from the server.
+ * If response_type is RANDOM, server randomly chooses one from other formats.
+ * </pre>
+ *
+ * <code>.grpc.testing.PayloadType response_type = 1;</code>
+ */
+ private $response_type = 0;
+ /**
+ * <pre>
+ * Desired payload size in the response from the server.
+ * </pre>
+ *
+ * <code>int32 response_size = 2;</code>
+ */
+ private $response_size = 0;
+ /**
+ * <pre>
+ * Optional input payload sent along with the request.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 3;</code>
+ */
+ private $payload = null;
+ /**
+ * <pre>
+ * Whether SimpleResponse should include username.
+ * </pre>
+ *
+ * <code>bool fill_username = 4;</code>
+ */
+ private $fill_username = false;
+ /**
+ * <pre>
+ * Whether SimpleResponse should include OAuth scope.
+ * </pre>
+ *
+ * <code>bool fill_oauth_scope = 5;</code>
+ */
+ private $fill_oauth_scope = false;
+ /**
+ * <pre>
+ * Whether to request the server to compress the response. This field is
+ * "nullable" in order to interoperate seamlessly with clients not able to
+ * implement the full compression tests by introspecting the call to verify
+ * the response's compression status.
+ * </pre>
+ *
+ * <code>.grpc.testing.BoolValue response_compressed = 6;</code>
+ */
+ private $response_compressed = null;
+ /**
+ * <pre>
+ * Whether server should return a given status
+ * </pre>
+ *
+ * <code>.grpc.testing.EchoStatus response_status = 7;</code>
+ */
+ private $response_status = null;
+ /**
+ * <pre>
+ * Whether the server should expect this request to be compressed.
+ * </pre>
+ *
+ * <code>.grpc.testing.BoolValue expect_compressed = 8;</code>
+ */
+ private $expect_compressed = null;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * DEPRECATED, don't use. To be removed shortly.
+ * Desired payload type in the response from the server.
+ * If response_type is RANDOM, server randomly chooses one from other formats.
+ * </pre>
+ *
+ * <code>.grpc.testing.PayloadType response_type = 1;</code>
+ */
+ public function getResponseType()
+ {
+ return $this->response_type;
+ }
+
+ /**
+ * <pre>
+ * DEPRECATED, don't use. To be removed shortly.
+ * Desired payload type in the response from the server.
+ * If response_type is RANDOM, server randomly chooses one from other formats.
+ * </pre>
+ *
+ * <code>.grpc.testing.PayloadType response_type = 1;</code>
+ */
+ public function setResponseType($var)
+ {
+ GPBUtil::checkEnum($var, \Grpc\Testing\PayloadType::class);
+ $this->response_type = $var;
+ }
+
+ /**
+ * <pre>
+ * Desired payload size in the response from the server.
+ * </pre>
+ *
+ * <code>int32 response_size = 2;</code>
+ */
+ public function getResponseSize()
+ {
+ return $this->response_size;
+ }
+
+ /**
+ * <pre>
+ * Desired payload size in the response from the server.
+ * </pre>
+ *
+ * <code>int32 response_size = 2;</code>
+ */
+ public function setResponseSize($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->response_size = $var;
+ }
+
+ /**
+ * <pre>
+ * Optional input payload sent along with the request.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 3;</code>
+ */
+ public function getPayload()
+ {
+ return $this->payload;
+ }
+
+ /**
+ * <pre>
+ * Optional input payload sent along with the request.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 3;</code>
+ */
+ public function setPayload(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class);
+ $this->payload = $var;
+ }
+
+ /**
+ * <pre>
+ * Whether SimpleResponse should include username.
+ * </pre>
+ *
+ * <code>bool fill_username = 4;</code>
+ */
+ public function getFillUsername()
+ {
+ return $this->fill_username;
+ }
+
+ /**
+ * <pre>
+ * Whether SimpleResponse should include username.
+ * </pre>
+ *
+ * <code>bool fill_username = 4;</code>
+ */
+ public function setFillUsername($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->fill_username = $var;
+ }
+
+ /**
+ * <pre>
+ * Whether SimpleResponse should include OAuth scope.
+ * </pre>
+ *
+ * <code>bool fill_oauth_scope = 5;</code>
+ */
+ public function getFillOauthScope()
+ {
+ return $this->fill_oauth_scope;
+ }
+
+ /**
+ * <pre>
+ * Whether SimpleResponse should include OAuth scope.
+ * </pre>
+ *
+ * <code>bool fill_oauth_scope = 5;</code>
+ */
+ public function setFillOauthScope($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->fill_oauth_scope = $var;
+ }
+
+ /**
+ * <pre>
+ * Whether to request the server to compress the response. This field is
+ * "nullable" in order to interoperate seamlessly with clients not able to
+ * implement the full compression tests by introspecting the call to verify
+ * the response's compression status.
+ * </pre>
+ *
+ * <code>.grpc.testing.BoolValue response_compressed = 6;</code>
+ */
+ public function getResponseCompressed()
+ {
+ return $this->response_compressed;
+ }
+
+ /**
+ * <pre>
+ * Whether to request the server to compress the response. This field is
+ * "nullable" in order to interoperate seamlessly with clients not able to
+ * implement the full compression tests by introspecting the call to verify
+ * the response's compression status.
+ * </pre>
+ *
+ * <code>.grpc.testing.BoolValue response_compressed = 6;</code>
+ */
+ public function setResponseCompressed(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class);
+ $this->response_compressed = $var;
+ }
+
+ /**
+ * <pre>
+ * Whether server should return a given status
+ * </pre>
+ *
+ * <code>.grpc.testing.EchoStatus response_status = 7;</code>
+ */
+ public function getResponseStatus()
+ {
+ return $this->response_status;
+ }
+
+ /**
+ * <pre>
+ * Whether server should return a given status
+ * </pre>
+ *
+ * <code>.grpc.testing.EchoStatus response_status = 7;</code>
+ */
+ public function setResponseStatus(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\EchoStatus::class);
+ $this->response_status = $var;
+ }
+
+ /**
+ * <pre>
+ * Whether the server should expect this request to be compressed.
+ * </pre>
+ *
+ * <code>.grpc.testing.BoolValue expect_compressed = 8;</code>
+ */
+ public function getExpectCompressed()
+ {
+ return $this->expect_compressed;
+ }
+
+ /**
+ * <pre>
+ * Whether the server should expect this request to be compressed.
+ * </pre>
+ *
+ * <code>.grpc.testing.BoolValue expect_compressed = 8;</code>
+ */
+ public function setExpectCompressed(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class);
+ $this->expect_compressed = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/SimpleResponse.php b/src/php/tests/qps/generated_code/Grpc/Testing/SimpleResponse.php
new file mode 100644
index 0000000000..ccc628ec4c
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/SimpleResponse.php
@@ -0,0 +1,129 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Unary response, as configured by the request.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.SimpleResponse</code>
+ */
+class SimpleResponse extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * Payload to increase message size.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 1;</code>
+ */
+ private $payload = null;
+ /**
+ * <pre>
+ * The user the request came from, for verifying authentication was
+ * successful when the client expected it.
+ * </pre>
+ *
+ * <code>string username = 2;</code>
+ */
+ private $username = '';
+ /**
+ * <pre>
+ * OAuth scope.
+ * </pre>
+ *
+ * <code>string oauth_scope = 3;</code>
+ */
+ private $oauth_scope = '';
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * Payload to increase message size.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 1;</code>
+ */
+ public function getPayload()
+ {
+ return $this->payload;
+ }
+
+ /**
+ * <pre>
+ * Payload to increase message size.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 1;</code>
+ */
+ public function setPayload(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class);
+ $this->payload = $var;
+ }
+
+ /**
+ * <pre>
+ * The user the request came from, for verifying authentication was
+ * successful when the client expected it.
+ * </pre>
+ *
+ * <code>string username = 2;</code>
+ */
+ public function getUsername()
+ {
+ return $this->username;
+ }
+
+ /**
+ * <pre>
+ * The user the request came from, for verifying authentication was
+ * successful when the client expected it.
+ * </pre>
+ *
+ * <code>string username = 2;</code>
+ */
+ public function setUsername($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->username = $var;
+ }
+
+ /**
+ * <pre>
+ * OAuth scope.
+ * </pre>
+ *
+ * <code>string oauth_scope = 3;</code>
+ */
+ public function getOauthScope()
+ {
+ return $this->oauth_scope;
+ }
+
+ /**
+ * <pre>
+ * OAuth scope.
+ * </pre>
+ *
+ * <code>string oauth_scope = 3;</code>
+ */
+ public function setOauthScope($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->oauth_scope = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallRequest.php b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallRequest.php
new file mode 100644
index 0000000000..d7bbc70779
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallRequest.php
@@ -0,0 +1,102 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Client-streaming request.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.StreamingInputCallRequest</code>
+ */
+class StreamingInputCallRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * Optional input payload sent along with the request.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 1;</code>
+ */
+ private $payload = null;
+ /**
+ * <pre>
+ * Whether the server should expect this request to be compressed. This field
+ * is "nullable" in order to interoperate seamlessly with servers not able to
+ * implement the full compression tests by introspecting the call to verify
+ * the request's compression status.
+ * </pre>
+ *
+ * <code>.grpc.testing.BoolValue expect_compressed = 2;</code>
+ */
+ private $expect_compressed = null;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * Optional input payload sent along with the request.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 1;</code>
+ */
+ public function getPayload()
+ {
+ return $this->payload;
+ }
+
+ /**
+ * <pre>
+ * Optional input payload sent along with the request.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 1;</code>
+ */
+ public function setPayload(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class);
+ $this->payload = $var;
+ }
+
+ /**
+ * <pre>
+ * Whether the server should expect this request to be compressed. This field
+ * is "nullable" in order to interoperate seamlessly with servers not able to
+ * implement the full compression tests by introspecting the call to verify
+ * the request's compression status.
+ * </pre>
+ *
+ * <code>.grpc.testing.BoolValue expect_compressed = 2;</code>
+ */
+ public function getExpectCompressed()
+ {
+ return $this->expect_compressed;
+ }
+
+ /**
+ * <pre>
+ * Whether the server should expect this request to be compressed. This field
+ * is "nullable" in order to interoperate seamlessly with servers not able to
+ * implement the full compression tests by introspecting the call to verify
+ * the request's compression status.
+ * </pre>
+ *
+ * <code>.grpc.testing.BoolValue expect_compressed = 2;</code>
+ */
+ public function setExpectCompressed(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\BoolValue::class);
+ $this->expect_compressed = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallResponse.php b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallResponse.php
new file mode 100644
index 0000000000..fdd1d0dbf8
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingInputCallResponse.php
@@ -0,0 +1,60 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Client-streaming response.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.StreamingInputCallResponse</code>
+ */
+class StreamingInputCallResponse extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * Aggregated size of payloads received from the client.
+ * </pre>
+ *
+ * <code>int32 aggregated_payload_size = 1;</code>
+ */
+ private $aggregated_payload_size = 0;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * Aggregated size of payloads received from the client.
+ * </pre>
+ *
+ * <code>int32 aggregated_payload_size = 1;</code>
+ */
+ public function getAggregatedPayloadSize()
+ {
+ return $this->aggregated_payload_size;
+ }
+
+ /**
+ * <pre>
+ * Aggregated size of payloads received from the client.
+ * </pre>
+ *
+ * <code>int32 aggregated_payload_size = 1;</code>
+ */
+ public function setAggregatedPayloadSize($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->aggregated_payload_size = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallRequest.php b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallRequest.php
new file mode 100644
index 0000000000..2aab5fadad
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallRequest.php
@@ -0,0 +1,171 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Server-streaming request.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.StreamingOutputCallRequest</code>
+ */
+class StreamingOutputCallRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * DEPRECATED, don't use. To be removed shortly.
+ * Desired payload type in the response from the server.
+ * If response_type is RANDOM, the payload from each response in the stream
+ * might be of different types. This is to simulate a mixed type of payload
+ * stream.
+ * </pre>
+ *
+ * <code>.grpc.testing.PayloadType response_type = 1;</code>
+ */
+ private $response_type = 0;
+ /**
+ * <pre>
+ * Configuration for each expected response message.
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.ResponseParameters response_parameters = 2;</code>
+ */
+ private $response_parameters;
+ /**
+ * <pre>
+ * Optional input payload sent along with the request.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 3;</code>
+ */
+ private $payload = null;
+ /**
+ * <pre>
+ * Whether server should return a given status
+ * </pre>
+ *
+ * <code>.grpc.testing.EchoStatus response_status = 7;</code>
+ */
+ private $response_status = null;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * DEPRECATED, don't use. To be removed shortly.
+ * Desired payload type in the response from the server.
+ * If response_type is RANDOM, the payload from each response in the stream
+ * might be of different types. This is to simulate a mixed type of payload
+ * stream.
+ * </pre>
+ *
+ * <code>.grpc.testing.PayloadType response_type = 1;</code>
+ */
+ public function getResponseType()
+ {
+ return $this->response_type;
+ }
+
+ /**
+ * <pre>
+ * DEPRECATED, don't use. To be removed shortly.
+ * Desired payload type in the response from the server.
+ * If response_type is RANDOM, the payload from each response in the stream
+ * might be of different types. This is to simulate a mixed type of payload
+ * stream.
+ * </pre>
+ *
+ * <code>.grpc.testing.PayloadType response_type = 1;</code>
+ */
+ public function setResponseType($var)
+ {
+ GPBUtil::checkEnum($var, \Grpc\Testing\PayloadType::class);
+ $this->response_type = $var;
+ }
+
+ /**
+ * <pre>
+ * Configuration for each expected response message.
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.ResponseParameters response_parameters = 2;</code>
+ */
+ public function getResponseParameters()
+ {
+ return $this->response_parameters;
+ }
+
+ /**
+ * <pre>
+ * Configuration for each expected response message.
+ * </pre>
+ *
+ * <code>repeated .grpc.testing.ResponseParameters response_parameters = 2;</code>
+ */
+ public function setResponseParameters(&$var)
+ {
+ GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Grpc\Testing\ResponseParameters::class);
+ $this->response_parameters = $var;
+ }
+
+ /**
+ * <pre>
+ * Optional input payload sent along with the request.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 3;</code>
+ */
+ public function getPayload()
+ {
+ return $this->payload;
+ }
+
+ /**
+ * <pre>
+ * Optional input payload sent along with the request.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 3;</code>
+ */
+ public function setPayload(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class);
+ $this->payload = $var;
+ }
+
+ /**
+ * <pre>
+ * Whether server should return a given status
+ * </pre>
+ *
+ * <code>.grpc.testing.EchoStatus response_status = 7;</code>
+ */
+ public function getResponseStatus()
+ {
+ return $this->response_status;
+ }
+
+ /**
+ * <pre>
+ * Whether server should return a given status
+ * </pre>
+ *
+ * <code>.grpc.testing.EchoStatus response_status = 7;</code>
+ */
+ public function setResponseStatus(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\EchoStatus::class);
+ $this->response_status = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallResponse.php b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallResponse.php
new file mode 100644
index 0000000000..c06c78c9d8
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/StreamingOutputCallResponse.php
@@ -0,0 +1,60 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * <pre>
+ * Server-streaming response, as configured by the request and parameters.
+ * </pre>
+ *
+ * Protobuf type <code>grpc.testing.StreamingOutputCallResponse</code>
+ */
+class StreamingOutputCallResponse extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * <pre>
+ * Payload to increase response size.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 1;</code>
+ */
+ private $payload = null;
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+ parent::__construct();
+ }
+
+ /**
+ * <pre>
+ * Payload to increase response size.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 1;</code>
+ */
+ public function getPayload()
+ {
+ return $this->payload;
+ }
+
+ /**
+ * <pre>
+ * Payload to increase response size.
+ * </pre>
+ *
+ * <code>.grpc.testing.Payload payload = 1;</code>
+ */
+ public function setPayload(&$var)
+ {
+ GPBUtil::checkMessage($var, \Grpc\Testing\Payload::class);
+ $this->payload = $var;
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/Void.php b/src/php/tests/qps/generated_code/Grpc/Testing/Void.php
new file mode 100644
index 0000000000..38c100845a
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/Void.php
@@ -0,0 +1,23 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Protobuf type <code>grpc.testing.Void</code>
+ */
+class Void extends \Google\Protobuf\Internal\Message
+{
+
+ public function __construct() {
+ \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+ parent::__construct();
+ }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/WorkerServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/WorkerServiceClient.php
new file mode 100644
index 0000000000..0a68e41269
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/WorkerServiceClient.php
@@ -0,0 +1,111 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// 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.
+//
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+namespace Grpc\Testing {
+
+ class WorkerServiceClient extends \Grpc\BaseStub {
+
+ /**
+ * @param string $hostname hostname
+ * @param array $opts channel options
+ * @param Grpc\Channel $channel (optional) re-use channel object
+ */
+ public function __construct($hostname, $opts, $channel = null) {
+ parent::__construct($hostname, $opts, $channel);
+ }
+
+ /**
+ * Start server with specified workload.
+ * First request sent specifies the ServerConfig followed by ServerStatus
+ * response. After that, a "Mark" can be sent anytime to request the latest
+ * stats. Closing the stream will initiate shutdown of the test server
+ * and once the shutdown has finished, the OK status is sent to terminate
+ * this RPC.
+ * @param array $metadata metadata
+ * @param array $options call options
+ */
+ public function RunServer($metadata = [], $options = []) {
+ return $this->_bidiRequest('/grpc.testing.WorkerService/RunServer',
+ ['\Grpc\Testing\ServerStatus','decode'],
+ $metadata, $options);
+ }
+
+ /**
+ * Start client with specified workload.
+ * First request sent specifies the ClientConfig followed by ClientStatus
+ * response. After that, a "Mark" can be sent anytime to request the latest
+ * stats. Closing the stream will initiate shutdown of the test client
+ * and once the shutdown has finished, the OK status is sent to terminate
+ * this RPC.
+ * @param array $metadata metadata
+ * @param array $options call options
+ */
+ public function RunClient($metadata = [], $options = []) {
+ return $this->_bidiRequest('/grpc.testing.WorkerService/RunClient',
+ ['\Grpc\Testing\ClientStatus','decode'],
+ $metadata, $options);
+ }
+
+ /**
+ * Just return the core count - unary call
+ * @param \Grpc\Testing\CoreRequest $argument input argument
+ * @param array $metadata metadata
+ * @param array $options call options
+ */
+ public function CoreCount(\Grpc\Testing\CoreRequest $argument,
+ $metadata = [], $options = []) {
+ return $this->_simpleRequest('/grpc.testing.WorkerService/CoreCount',
+ $argument,
+ ['\Grpc\Testing\CoreResponse', 'decode'],
+ $metadata, $options);
+ }
+
+ /**
+ * Quit this worker
+ * @param \Grpc\Testing\Void $argument input argument
+ * @param array $metadata metadata
+ * @param array $options call options
+ */
+ public function QuitWorker(\Grpc\Testing\Void $argument,
+ $metadata = [], $options = []) {
+ return $this->_simpleRequest('/grpc.testing.WorkerService/QuitWorker',
+ $argument,
+ ['\Grpc\Testing\Void', 'decode'],
+ $metadata, $options);
+ }
+
+ }
+
+}
diff --git a/src/proto/grpc/health/v1/health.options b/src/proto/grpc/health/v1/health.options
new file mode 100644
index 0000000000..240b498b58
--- /dev/null
+++ b/src/proto/grpc/health/v1/health.options
@@ -0,0 +1 @@
+grpc.health.v1.HealthCheckRequest.service max_size:200
diff --git a/src/proto/grpc/reflection/v1alpha/BUILD b/src/proto/grpc/reflection/v1alpha/BUILD
new file mode 100644
index 0000000000..92dd3d7f68
--- /dev/null
+++ b/src/proto/grpc/reflection/v1alpha/BUILD
@@ -0,0 +1,39 @@
+# Copyright 2017, 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.
+
+licenses(["notice"]) # 3-clause BSD
+
+package(default_visibility = ["//visibility:public"])
+
+load("//bazel:grpc_build_system.bzl", "grpc_proto_library")
+
+grpc_proto_library(
+ name = "reflection_proto",
+ srcs = ["reflection.proto"],
+)
diff --git a/src/proto/grpc/testing/control.proto b/src/proto/grpc/testing/control.proto
index 529313cfb1..8f0d25c2c9 100644
--- a/src/proto/grpc/testing/control.proto
+++ b/src/proto/grpc/testing/control.proto
@@ -139,7 +139,10 @@ message ServerConfig {
int32 async_server_threads = 7;
// Specify the number of cores to limit server to, if desired
int32 core_limit = 8;
- // payload config, used in generic server
+ // payload config, used in generic server.
+ // Note this must NOT be used in proto (non-generic) servers. For proto servers,
+ // 'response sizes' must be configured from the 'response_size' field of the
+ // 'SimpleRequest' objects in RPC requests.
PayloadConfig payload_config = 9;
// Specify the cores we should run the server on, if desired
diff --git a/src/proto/grpc/testing/echo_messages.proto b/src/proto/grpc/testing/echo_messages.proto
index b405acf043..efb6f4d493 100644
--- a/src/proto/grpc/testing/echo_messages.proto
+++ b/src/proto/grpc/testing/echo_messages.proto
@@ -50,6 +50,7 @@ message RequestParams {
bool skip_cancelled_check = 9;
string expected_transport_security_type = 10;
DebugInfo debug_info = 11;
+ bool server_die = 12; // Server should not see a request with this set.
}
message EchoRequest {
diff --git a/src/csharp/Grpc.Core.Tests/NUnitVersionTest.cs b/src/proto/grpc/testing/proxy-service.proto
index 1a9e441611..7b7de8d549 100644
--- a/src/csharp/Grpc.Core.Tests/NUnitVersionTest.cs
+++ b/src/proto/grpc/testing/proxy-service.proto
@@ -1,6 +1,4 @@
-#region Copyright notice and license
-
-// Copyright 2015, Google Inc.
+// Copyright 2017, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -29,49 +27,18 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#endregion
-
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-using Grpc.Core;
-using Grpc.Core.Internal;
-using Grpc.Core.Utils;
-using NUnit.Framework;
+syntax = "proto3";
-namespace Grpc.Core.Tests
-{
- /// <summary>
- /// Tests if the version of nunit-console used is sufficient to run async tests.
- /// </summary>
- public class NUnitVersionTest
- {
- private int testRunCount = 0;
+import "src/proto/grpc/testing/control.proto";
- [TestFixtureTearDown]
- public void Cleanup()
- {
- if (testRunCount != 2)
- {
- Console.Error.WriteLine("You are using and old version of NUnit that doesn't support async tests and skips them instead. " +
- "This test has failed to indicate that.");
- Console.Error.Flush();
- throw new Exception("NUnitVersionTest has failed.");
- }
- }
+package grpc.testing;
- [Test]
- public void NUnitVersionTest1()
- {
- testRunCount++;
- }
+message ProxyStat {
+ double latency = 1;
+}
- // Old version of NUnit will skip this test
- [Test]
- public async Task NUnitVersionTest2()
- {
- testRunCount++;
- await Task.Delay(10);
- }
- }
+service ProxyClientService {
+ rpc GetConfig(Void) returns (ClientConfig);
+ rpc ReportTime(stream ProxyStat) returns (Void);
}
+
diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py
index b64a708cc7..a4481b2ac3 100644
--- a/src/python/grpcio/grpc/__init__.py
+++ b/src/python/grpcio/grpc/__init__.py
@@ -1004,7 +1004,7 @@ def unary_unary_rpc_method_handler(behavior,
An RpcMethodHandler for a unary-unary RPC method constructed from the given
parameters.
"""
- from grpc import _utilities
+ from grpc import _utilities # pylint: disable=cyclic-import
return _utilities.RpcMethodHandler(False, False, request_deserializer,
response_serializer, behavior, None,
None, None)
@@ -1025,7 +1025,7 @@ def unary_stream_rpc_method_handler(behavior,
An RpcMethodHandler for a unary-stream RPC method constructed from the
given parameters.
"""
- from grpc import _utilities
+ from grpc import _utilities # pylint: disable=cyclic-import
return _utilities.RpcMethodHandler(False, True, request_deserializer,
response_serializer, None, behavior,
None, None)
@@ -1046,7 +1046,7 @@ def stream_unary_rpc_method_handler(behavior,
An RpcMethodHandler for a stream-unary RPC method constructed from the
given parameters.
"""
- from grpc import _utilities
+ from grpc import _utilities # pylint: disable=cyclic-import
return _utilities.RpcMethodHandler(True, False, request_deserializer,
response_serializer, None, None,
behavior, None)
@@ -1068,7 +1068,7 @@ def stream_stream_rpc_method_handler(behavior,
An RpcMethodHandler for a stream-stream RPC method constructed from the
given parameters.
"""
- from grpc import _utilities
+ from grpc import _utilities # pylint: disable=cyclic-import
return _utilities.RpcMethodHandler(True, True, request_deserializer,
response_serializer, None, None, None,
behavior)
@@ -1085,7 +1085,7 @@ def method_handlers_generic_handler(service, method_handlers):
Returns:
A GenericRpcHandler constructed from the given parameters.
"""
- from grpc import _utilities
+ from grpc import _utilities # pylint: disable=cyclic-import
return _utilities.DictionaryGenericHandler(service, method_handlers)
@@ -1124,7 +1124,7 @@ def metadata_call_credentials(metadata_plugin, name=None):
Returns:
A CallCredentials.
"""
- from grpc import _plugin_wrapping
+ from grpc import _plugin_wrapping # pylint: disable=cyclic-import
if name is None:
try:
effective_name = metadata_plugin.__name__
@@ -1147,7 +1147,7 @@ def access_token_call_credentials(access_token):
Returns:
A CallCredentials.
"""
- from grpc import _auth
+ from grpc import _auth # pylint: disable=cyclic-import
return metadata_call_credentials(
_auth.AccessTokenCallCredentials(access_token))
@@ -1161,7 +1161,7 @@ def composite_call_credentials(*call_credentials):
Returns:
A CallCredentials object composed of the given CallCredentials objects.
"""
- from grpc import _credential_composition
+ from grpc import _credential_composition # pylint: disable=cyclic-import
cygrpc_call_credentials = tuple(
single_call_credentials._credentials
for single_call_credentials in call_credentials)
@@ -1180,7 +1180,7 @@ def composite_channel_credentials(channel_credentials, *call_credentials):
A ChannelCredentials composed of the given ChannelCredentials and
CallCredentials objects.
"""
- from grpc import _credential_composition
+ from grpc import _credential_composition # pylint: disable=cyclic-import
cygrpc_call_credentials = tuple(
single_call_credentials._credentials
for single_call_credentials in call_credentials)
@@ -1237,7 +1237,7 @@ def channel_ready_future(channel):
A Future that matures when the given Channel has connectivity
ChannelConnectivity.READY.
"""
- from grpc import _utilities
+ from grpc import _utilities # pylint: disable=cyclic-import
return _utilities.channel_ready_future(channel)
@@ -1252,7 +1252,7 @@ def insecure_channel(target, options=None):
Returns:
A Channel to the target through which RPCs may be conducted.
"""
- from grpc import _channel
+ from grpc import _channel # pylint: disable=cyclic-import
return _channel.Channel(target, () if options is None else options, None)
@@ -1268,7 +1268,7 @@ def secure_channel(target, credentials, options=None):
Returns:
A Channel to the target through which RPCs may be conducted.
"""
- from grpc import _channel
+ from grpc import _channel # pylint: disable=cyclic-import
return _channel.Channel(target, () if options is None else options,
credentials._credentials)
@@ -1290,7 +1290,7 @@ def server(thread_pool, handlers=None, options=None):
Returns:
A Server with which RPCs can be serviced.
"""
- from grpc import _server
+ from grpc import _server # pylint: disable=cyclic-import
return _server.Server(thread_pool, () if handlers is None else handlers, ()
if options is None else options)
diff --git a/src/python/grpcio/grpc/_auth.py b/src/python/grpcio/grpc/_auth.py
index e8a90cf504..cb7c6fe4fd 100644
--- a/src/python/grpcio/grpc/_auth.py
+++ b/src/python/grpcio/grpc/_auth.py
@@ -39,6 +39,19 @@ def _sign_request(callback, token, error):
callback(metadata, error)
+def _create_get_token_callback(callback):
+
+ def get_token_callback(future):
+ try:
+ access_token = future.result().access_token
+ except Exception as exception: # pylint: disable=broad-except
+ _sign_request(callback, None, exception)
+ else:
+ _sign_request(callback, access_token, None)
+
+ return get_token_callback
+
+
class GoogleCallCredentials(grpc.AuthMetadataPlugin):
"""Metadata wrapper for GoogleCredentials from the oauth2client library."""
@@ -48,11 +61,8 @@ class GoogleCallCredentials(grpc.AuthMetadataPlugin):
# Hack to determine if these are JWT creds and we need to pass
# additional_claims when getting a token
- if 'additional_claims' in inspect.getargspec(
- credentials.get_access_token).args:
- self._is_jwt = True
- else:
- self._is_jwt = False
+ self._is_jwt = 'additional_claims' in inspect.getargspec(
+ credentials.get_access_token).args
def __call__(self, context, callback):
# MetadataPlugins cannot block (see grpc.beta.interfaces.py)
@@ -62,16 +72,7 @@ class GoogleCallCredentials(grpc.AuthMetadataPlugin):
additional_claims={'aud': context.service_url})
else:
future = self._pool.submit(self._credentials.get_access_token)
- future.add_done_callback(
- lambda x: self._get_token_callback(callback, x))
-
- def _get_token_callback(self, callback, future):
- try:
- access_token = future.result().access_token
- except Exception as e:
- _sign_request(callback, None, e)
- else:
- _sign_request(callback, access_token, None)
+ future.add_done_callback(_create_get_token_callback(callback))
def __del__(self):
self._pool.shutdown(wait=False)
diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py
index 691e96a322..4316449ac6 100644
--- a/src/python/grpcio/grpc/_channel.py
+++ b/src/python/grpcio/grpc/_channel.py
@@ -39,11 +39,10 @@ from grpc import _grpcio_metadata
from grpc._cython import cygrpc
from grpc.framework.foundation import callable_util
-_USER_AGENT = 'Python-gRPC-{}'.format(_grpcio_metadata.__version__)
+_USER_AGENT = 'grpc-python/{}'.format(_grpcio_metadata.__version__)
_EMPTY_FLAGS = 0
_INFINITE_FUTURE = cygrpc.Timespec(float('+inf'))
-_EMPTY_METADATA = cygrpc.Metadata(())
_UNARY_UNARY_INITIAL_DUE = (cygrpc.OperationType.send_initial_metadata,
cygrpc.OperationType.send_message,
@@ -138,8 +137,8 @@ def _abort(state, code, details):
state.code = code
state.details = details
if state.initial_metadata is None:
- state.initial_metadata = _EMPTY_METADATA
- state.trailing_metadata = _EMPTY_METADATA
+ state.initial_metadata = _common.EMPTY_METADATA
+ state.trailing_metadata = _common.EMPTY_METADATA
def _handle_event(event, state, response_deserializer):
@@ -201,7 +200,7 @@ def _consume_request_iterator(request_iterator, state, call,
request = next(request_iterator)
except StopIteration:
break
- except Exception as e:
+ except Exception: # pylint: disable=broad-except
logging.exception("Exception iterating requests!")
call.cancel()
_abort(state, grpc.StatusCode.UNKNOWN,
@@ -238,7 +237,7 @@ def _consume_request_iterator(request_iterator, state, call,
cygrpc.Operations(operations), event_handler)
state.due.add(cygrpc.OperationType.send_close_from_client)
- def stop_consumption_thread(timeout):
+ def stop_consumption_thread(timeout): # pylint: disable=unused-argument
with state.condition:
if state.code is None:
call.cancel()
@@ -388,13 +387,14 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call):
with self._state.condition:
while self._state.initial_metadata is None:
self._state.condition.wait()
- return _common.application_metadata(self._state.initial_metadata)
+ return _common.to_application_metadata(self._state.initial_metadata)
def trailing_metadata(self):
with self._state.condition:
while self._state.trailing_metadata is None:
self._state.condition.wait()
- return _common.application_metadata(self._state.trailing_metadata)
+ return _common.to_application_metadata(
+ self._state.trailing_metadata)
def code(self):
with self._state.condition:
@@ -435,7 +435,7 @@ def _start_unary_request(request, timeout, request_serializer):
deadline, deadline_timespec = _deadline(timeout)
serialized_request = _common.serialize(request, request_serializer)
if serialized_request is None:
- state = _RPCState((), _EMPTY_METADATA, _EMPTY_METADATA,
+ state = _RPCState((), _common.EMPTY_METADATA, _common.EMPTY_METADATA,
grpc.StatusCode.INTERNAL,
'Exception serializing request!')
rendezvous = _Rendezvous(state, None, None, deadline)
@@ -444,10 +444,10 @@ def _start_unary_request(request, timeout, request_serializer):
return deadline, deadline_timespec, serialized_request, None
-def _end_unary_response_blocking(state, with_call, deadline):
+def _end_unary_response_blocking(state, call, with_call, deadline):
if state.code is grpc.StatusCode.OK:
if with_call:
- rendezvous = _Rendezvous(state, None, None, deadline)
+ rendezvous = _Rendezvous(state, call, None, deadline)
return state.response, rendezvous
else:
return state.response
@@ -474,7 +474,7 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable):
state = _RPCState(_UNARY_UNARY_INITIAL_DUE, None, None, None, None)
operations = (
cygrpc.operation_send_initial_metadata(
- _common.cygrpc_metadata(metadata), _EMPTY_FLAGS),
+ _common.to_cygrpc_metadata(metadata), _EMPTY_FLAGS),
cygrpc.operation_send_message(serialized_request, _EMPTY_FLAGS),
cygrpc.operation_send_close_from_client(_EMPTY_FLAGS),
cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),
@@ -499,17 +499,17 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable):
_check_call_error(call_error, metadata)
_handle_event(completion_queue.poll(), state,
self._response_deserializer)
- return state, deadline
+ return state, call, deadline
def __call__(self, request, timeout=None, metadata=None, credentials=None):
- state, deadline, = self._blocking(request, timeout, metadata,
- credentials)
- return _end_unary_response_blocking(state, False, deadline)
+ state, call, deadline = self._blocking(request, timeout, metadata,
+ credentials)
+ return _end_unary_response_blocking(state, call, False, deadline)
def with_call(self, request, timeout=None, metadata=None, credentials=None):
- state, deadline, = self._blocking(request, timeout, metadata,
- credentials)
- return _end_unary_response_blocking(state, True, deadline)
+ state, call, deadline = self._blocking(request, timeout, metadata,
+ credentials)
+ return _end_unary_response_blocking(state, call, True, deadline)
def future(self, request, timeout=None, metadata=None, credentials=None):
state, operations, deadline, deadline_timespec, rendezvous = self._prepare(
@@ -564,7 +564,7 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable):
)), event_handler)
operations = (
cygrpc.operation_send_initial_metadata(
- _common.cygrpc_metadata(metadata),
+ _common.to_cygrpc_metadata(metadata),
_EMPTY_FLAGS), cygrpc.operation_send_message(
serialized_request, _EMPTY_FLAGS),
cygrpc.operation_send_close_from_client(_EMPTY_FLAGS),
@@ -604,7 +604,7 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable):
None)
operations = (
cygrpc.operation_send_initial_metadata(
- _common.cygrpc_metadata(metadata), _EMPTY_FLAGS),
+ _common.to_cygrpc_metadata(metadata), _EMPTY_FLAGS),
cygrpc.operation_receive_message(_EMPTY_FLAGS),
cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),)
call_error = call.start_client_batch(
@@ -619,25 +619,25 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable):
state.condition.notify_all()
if not state.due:
break
- return state, deadline
+ return state, call, deadline
def __call__(self,
request_iterator,
timeout=None,
metadata=None,
credentials=None):
- state, deadline, = self._blocking(request_iterator, timeout, metadata,
- credentials)
- return _end_unary_response_blocking(state, False, deadline)
+ state, call, deadline = self._blocking(request_iterator, timeout,
+ metadata, credentials)
+ return _end_unary_response_blocking(state, call, False, deadline)
def with_call(self,
request_iterator,
timeout=None,
metadata=None,
credentials=None):
- state, deadline, = self._blocking(request_iterator, timeout, metadata,
- credentials)
- return _end_unary_response_blocking(state, True, deadline)
+ state, call, deadline = self._blocking(request_iterator, timeout,
+ metadata, credentials)
+ return _end_unary_response_blocking(state, call, True, deadline)
def future(self,
request_iterator,
@@ -658,7 +658,7 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable):
event_handler)
operations = (
cygrpc.operation_send_initial_metadata(
- _common.cygrpc_metadata(metadata), _EMPTY_FLAGS),
+ _common.to_cygrpc_metadata(metadata), _EMPTY_FLAGS),
cygrpc.operation_receive_message(_EMPTY_FLAGS),
cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),)
call_error = call.start_client_batch(
@@ -701,7 +701,7 @@ class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable):
event_handler)
operations = (
cygrpc.operation_send_initial_metadata(
- _common.cygrpc_metadata(metadata), _EMPTY_FLAGS),
+ _common.to_cygrpc_metadata(metadata), _EMPTY_FLAGS),
cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),)
call_error = call.start_client_batch(
cygrpc.Operations(operations), event_handler)
@@ -736,7 +736,7 @@ def _run_channel_spin_thread(state):
state.managed_calls = None
return
- def stop_channel_spin(timeout):
+ def stop_channel_spin(timeout): # pylint: disable=unused-argument
with state.lock:
if state.managed_calls is not None:
for call in state.managed_calls:
@@ -877,12 +877,8 @@ def _moot(state):
def _subscribe(state, callback, try_to_connect):
with state.lock:
if not state.callbacks_and_connectivities and not state.polling:
-
- def cancel_all_subscriptions(timeout):
- _moot(state)
-
polling_thread = _common.CleanupThread(
- cancel_all_subscriptions,
+ lambda timeout: _moot(state),
target=_poll_connectivity,
args=(state, state.channel, bool(try_to_connect)))
polling_thread.start()
diff --git a/src/python/grpcio/grpc/_common.py b/src/python/grpcio/grpc/_common.py
index a5f1f38ea9..2e369013f5 100644
--- a/src/python/grpcio/grpc/_common.py
+++ b/src/python/grpcio/grpc/_common.py
@@ -37,7 +37,7 @@ import six
import grpc
from grpc._cython import cygrpc
-_EMPTY_METADATA = cygrpc.Metadata(())
+EMPTY_METADATA = cygrpc.Metadata(())
CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = {
cygrpc.ConnectivityState.idle:
@@ -92,27 +92,27 @@ def decode(b):
try:
return b.decode('utf8')
except UnicodeDecodeError:
- logging.exception('Invalid encoding on {}'.format(b))
+ logging.exception('Invalid encoding on %s', b)
return b.decode('latin1')
def channel_args(options):
- channel_args = []
+ cygrpc_args = []
for key, value in options:
if isinstance(value, six.string_types):
- channel_args.append(cygrpc.ChannelArg(encode(key), encode(value)))
+ cygrpc_args.append(cygrpc.ChannelArg(encode(key), encode(value)))
else:
- channel_args.append(cygrpc.ChannelArg(encode(key), value))
- return cygrpc.ChannelArgs(channel_args)
+ cygrpc_args.append(cygrpc.ChannelArg(encode(key), value))
+ return cygrpc.ChannelArgs(cygrpc_args)
-def cygrpc_metadata(application_metadata):
- return _EMPTY_METADATA if application_metadata is None else cygrpc.Metadata(
+def to_cygrpc_metadata(application_metadata):
+ return EMPTY_METADATA if application_metadata is None else cygrpc.Metadata(
cygrpc.Metadatum(encode(key), encode(value))
for key, value in application_metadata)
-def application_metadata(cygrpc_metadata):
+def to_application_metadata(cygrpc_metadata):
if cygrpc_metadata is None:
return ()
else:
@@ -148,36 +148,23 @@ def fully_qualified_method(group, method):
class CleanupThread(threading.Thread):
"""A threading.Thread subclass supporting custom behavior on join().
- On Python Interpreter exit, Python will attempt to join outstanding threads
- prior to garbage collection. We may need to do additional cleanup, and
- we accomplish this by overriding the join() method.
- """
-
- def __init__(self,
- behavior,
- group=None,
- target=None,
- name=None,
- args=(),
- kwargs={}):
+ On Python Interpreter exit, Python will attempt to join outstanding threads
+ prior to garbage collection. We may need to do additional cleanup, and
+ we accomplish this by overriding the join() method.
+ """
+
+ def __init__(self, behavior, *args, **kwargs):
"""Constructor.
- Args:
- behavior (function): Function called on join() with a single
- argument, timeout, indicating the maximum duration of
- `behavior`, or None indicating `behavior` has no deadline.
- `behavior` must be idempotent.
- group (None): should be None. Reseved for future extensions
- when ThreadGroup is implemented.
- target (function): The function to invoke when this thread is
- run. Defaults to None.
- name (str): The name of this thread. Defaults to None.
- args (tuple[object]): A tuple of arguments to pass to `target`.
- kwargs (dict[str,object]): A dictionary of keyword arguments to
- pass to `target`.
- """
- super(CleanupThread, self).__init__(
- group=group, target=target, name=name, args=args, kwargs=kwargs)
+ Args:
+ behavior (function): Function called on join() with a single
+ argument, timeout, indicating the maximum duration of
+ `behavior`, or None indicating `behavior` has no deadline.
+ `behavior` must be idempotent.
+ args: Positional arguments passed to threading.Thread constructor.
+ kwargs: Keyword arguments passed to threading.Thread constructor.
+ """
+ super(CleanupThread, self).__init__(*args, **kwargs)
self._behavior = behavior
def join(self, timeout=None):
diff --git a/src/python/grpcio/grpc/_plugin_wrapping.py b/src/python/grpcio/grpc/_plugin_wrapping.py
index 69c46aa546..1e44561c97 100644
--- a/src/python/grpcio/grpc/_plugin_wrapping.py
+++ b/src/python/grpcio/grpc/_plugin_wrapping.py
@@ -66,9 +66,9 @@ class _WrappedCygrpcCallback(object):
def _invoke_success(self, metadata):
try:
- cygrpc_metadata = _common.cygrpc_metadata(metadata)
- except Exception as error:
- self._invoke_failure(error)
+ cygrpc_metadata = _common.to_cygrpc_metadata(metadata)
+ except Exception as exception: # pylint: disable=broad-except
+ self._invoke_failure(exception)
return
self.cygrpc_callback(cygrpc_metadata, cygrpc.StatusCode.ok, b'')
diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py
index bf2743c16b..84e096d4c0 100644
--- a/src/python/grpcio/grpc/_server.py
+++ b/src/python/grpcio/grpc/_server.py
@@ -57,7 +57,6 @@ _CLOSED = 'closed'
_CANCELLED = 'cancelled'
_EMPTY_FLAGS = 0
-_EMPTY_METADATA = cygrpc.Metadata(())
_UNEXPECTED_EXIT_SERVER_GRACE = 1.0
@@ -143,14 +142,14 @@ def _abort(state, call, code, details):
effective_details = details if state.details is None else state.details
if state.initial_metadata_allowed:
operations = (cygrpc.operation_send_initial_metadata(
- _EMPTY_METADATA, _EMPTY_FLAGS),
- cygrpc.operation_send_status_from_server(
- _common.cygrpc_metadata(state.trailing_metadata),
- effective_code, effective_details, _EMPTY_FLAGS),)
+ _common.EMPTY_METADATA,
+ _EMPTY_FLAGS), cygrpc.operation_send_status_from_server(
+ _common.to_cygrpc_metadata(state.trailing_metadata),
+ effective_code, effective_details, _EMPTY_FLAGS),)
token = _SEND_INITIAL_METADATA_AND_SEND_STATUS_FROM_SERVER_TOKEN
else:
operations = (cygrpc.operation_send_status_from_server(
- _common.cygrpc_metadata(state.trailing_metadata),
+ _common.to_cygrpc_metadata(state.trailing_metadata),
effective_code, effective_details, _EMPTY_FLAGS),)
token = _SEND_STATUS_FROM_SERVER_TOKEN
call.start_server_batch(
@@ -251,7 +250,7 @@ class _Context(grpc.ServicerContext):
self._state.disable_next_compression = True
def invocation_metadata(self):
- return _common.application_metadata(self._rpc_event.request_metadata)
+ return _common.to_application_metadata(self._rpc_event.request_metadata)
def peer(self):
return _common.decode(self._rpc_event.operation_call.peer())
@@ -263,7 +262,8 @@ class _Context(grpc.ServicerContext):
else:
if self._state.initial_metadata_allowed:
operation = cygrpc.operation_send_initial_metadata(
- _common.cygrpc_metadata(initial_metadata), _EMPTY_FLAGS)
+ _common.to_cygrpc_metadata(initial_metadata),
+ _EMPTY_FLAGS)
self._rpc_event.operation_call.start_server_batch(
cygrpc.Operations((operation,)),
_send_initial_metadata(self._state))
@@ -274,7 +274,7 @@ class _Context(grpc.ServicerContext):
def set_trailing_metadata(self, trailing_metadata):
with self._state.condition:
- self._state.trailing_metadata = _common.cygrpc_metadata(
+ self._state.trailing_metadata = _common.to_cygrpc_metadata(
trailing_metadata)
def set_code(self, code):
@@ -343,7 +343,7 @@ def _unary_request(rpc_event, state, request_deserializer):
if state.client is _CANCELLED or state.statused:
return None
else:
- start_server_batch_result = rpc_event.operation_call.start_server_batch(
+ rpc_event.operation_call.start_server_batch(
cygrpc.Operations(
(cygrpc.operation_receive_message(_EMPTY_FLAGS),)),
_receive_message(state, rpc_event.operation_call,
@@ -416,7 +416,7 @@ def _send_response(rpc_event, state, serialized_response):
else:
if state.initial_metadata_allowed:
operations = (cygrpc.operation_send_initial_metadata(
- _EMPTY_METADATA, _EMPTY_FLAGS),
+ _common.EMPTY_METADATA, _EMPTY_FLAGS),
cygrpc.operation_send_message(serialized_response,
_EMPTY_FLAGS),)
state.initial_metadata_allowed = False
@@ -437,7 +437,8 @@ def _send_response(rpc_event, state, serialized_response):
def _status(rpc_event, state, serialized_response):
with state.condition:
if state.client is not _CANCELLED:
- trailing_metadata = _common.cygrpc_metadata(state.trailing_metadata)
+ trailing_metadata = _common.to_cygrpc_metadata(
+ state.trailing_metadata)
code = _completion_code(state)
details = _details(state)
operations = [
@@ -446,8 +447,8 @@ def _status(rpc_event, state, serialized_response):
]
if state.initial_metadata_allowed:
operations.append(
- cygrpc.operation_send_initial_metadata(_EMPTY_METADATA,
- _EMPTY_FLAGS))
+ cygrpc.operation_send_initial_metadata(
+ _common.EMPTY_METADATA, _EMPTY_FLAGS))
if serialized_response is not None:
operations.append(
cygrpc.operation_send_message(serialized_response,
@@ -549,12 +550,12 @@ def _find_method_handler(rpc_event, generic_handlers):
def _handle_unrecognized_method(rpc_event):
- operations = (
- cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, _EMPTY_FLAGS),
- cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),
- cygrpc.operation_send_status_from_server(
- _EMPTY_METADATA, cygrpc.StatusCode.unimplemented,
- b'Method not found!', _EMPTY_FLAGS),)
+ operations = (cygrpc.operation_send_initial_metadata(_common.EMPTY_METADATA,
+ _EMPTY_FLAGS),
+ cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),
+ cygrpc.operation_send_status_from_server(
+ _common.EMPTY_METADATA, cygrpc.StatusCode.unimplemented,
+ b'Method not found!', _EMPTY_FLAGS),)
rpc_state = _RPCState()
rpc_event.operation_call.start_server_batch(
operations, lambda ignored_event: (rpc_state, (),))
diff --git a/src/python/grpcio/grpc/beta/_client_adaptations.py b/src/python/grpcio/grpc/beta/_client_adaptations.py
index b53395e2a2..3c69acc019 100644
--- a/src/python/grpcio/grpc/beta/_client_adaptations.py
+++ b/src/python/grpcio/grpc/beta/_client_adaptations.py
@@ -30,12 +30,13 @@
import grpc
from grpc import _common
-from grpc._cython import cygrpc
from grpc.beta import interfaces
from grpc.framework.common import cardinality
from grpc.framework.foundation import future
from grpc.framework.interfaces.face import face
+# pylint: disable=too-many-arguments,too-many-locals,unused-argument
+
_STATUS_CODE_TO_ABORTION_KIND_AND_ABORTION_ERROR_CLASS = {
grpc.StatusCode.CANCELLED: (face.Abortion.Kind.CANCELLED,
face.CancellationError),
@@ -621,8 +622,8 @@ class _GenericStub(face.GenericStub):
class _DynamicStub(face.DynamicStub):
- def __init__(self, generic_stub, group, cardinalities):
- self._generic_stub = generic_stub
+ def __init__(self, backing_generic_stub, group, cardinalities):
+ self._generic_stub = backing_generic_stub
self._group = group
self._cardinalities = cardinalities
diff --git a/src/python/grpcio/grpc/beta/_connectivity_channel.py b/src/python/grpcio/grpc/beta/_connectivity_channel.py
deleted file mode 100644
index bfb847f80a..0000000000
--- a/src/python/grpcio/grpc/beta/_connectivity_channel.py
+++ /dev/null
@@ -1,159 +0,0 @@
-# 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.
-"""Affords a connectivity-state-listenable channel."""
-
-import threading
-import time
-
-from grpc._adapter import _low
-from grpc._adapter import _types
-from grpc.beta import interfaces
-from grpc.framework.foundation import callable_util
-
-_CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE = (
- 'Exception calling channel subscription callback!')
-
-_LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = {
- state: connectivity
- for state, connectivity in zip(_types.ConnectivityState,
- interfaces.ChannelConnectivity)
-}
-
-
-class ConnectivityChannel(object):
-
- def __init__(self, low_channel):
- self._lock = threading.Lock()
- self._low_channel = low_channel
-
- self._polling = False
- self._connectivity = None
- self._try_to_connect = False
- self._callbacks_and_connectivities = []
- self._delivering = False
-
- def _deliveries(self, connectivity):
- callbacks_needing_update = []
- for callback_and_connectivity in self._callbacks_and_connectivities:
- callback, callback_connectivity = callback_and_connectivity
- if callback_connectivity is not connectivity:
- callbacks_needing_update.append(callback)
- callback_and_connectivity[1] = connectivity
- return callbacks_needing_update
-
- def _deliver(self, initial_connectivity, initial_callbacks):
- connectivity = initial_connectivity
- callbacks = initial_callbacks
- while True:
- for callback in callbacks:
- callable_util.call_logging_exceptions(
- callback, _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE,
- connectivity)
- with self._lock:
- callbacks = self._deliveries(self._connectivity)
- if callbacks:
- connectivity = self._connectivity
- else:
- self._delivering = False
- return
-
- def _spawn_delivery(self, connectivity, callbacks):
- delivering_thread = threading.Thread(
- target=self._deliver, args=(connectivity, callbacks,))
- delivering_thread.start()
- self._delivering = True
-
- # TODO(issue 3064): Don't poll.
- def _poll_connectivity(self, low_channel, initial_try_to_connect):
- try_to_connect = initial_try_to_connect
- low_connectivity = low_channel.check_connectivity_state(try_to_connect)
- with self._lock:
- self._connectivity = _LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[
- low_connectivity]
- callbacks = tuple(
- callback
- for callback, unused_but_known_to_be_none_connectivity in
- self._callbacks_and_connectivities)
- for callback_and_connectivity in self._callbacks_and_connectivities:
- callback_and_connectivity[1] = self._connectivity
- if callbacks:
- self._spawn_delivery(self._connectivity, callbacks)
- completion_queue = _low.CompletionQueue()
- while True:
- low_channel.watch_connectivity_state(low_connectivity,
- time.time() + 0.2,
- completion_queue, None)
- event = completion_queue.next()
- with self._lock:
- if not self._callbacks_and_connectivities and not self._try_to_connect:
- self._polling = False
- self._connectivity = None
- completion_queue.shutdown()
- break
- try_to_connect = self._try_to_connect
- self._try_to_connect = False
- if event.success or try_to_connect:
- low_connectivity = low_channel.check_connectivity_state(
- try_to_connect)
- with self._lock:
- self._connectivity = _LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[
- low_connectivity]
- if not self._delivering:
- callbacks = self._deliveries(self._connectivity)
- if callbacks:
- self._spawn_delivery(self._connectivity, callbacks)
-
- def subscribe(self, callback, try_to_connect):
- with self._lock:
- if not self._callbacks_and_connectivities and not self._polling:
- polling_thread = threading.Thread(
- target=self._poll_connectivity,
- args=(self._low_channel, bool(try_to_connect)))
- polling_thread.start()
- self._polling = True
- self._callbacks_and_connectivities.append([callback, None])
- elif not self._delivering and self._connectivity is not None:
- self._spawn_delivery(self._connectivity, (callback,))
- self._try_to_connect |= bool(try_to_connect)
- self._callbacks_and_connectivities.append(
- [callback, self._connectivity])
- else:
- self._try_to_connect |= bool(try_to_connect)
- self._callbacks_and_connectivities.append([callback, None])
-
- def unsubscribe(self, callback):
- with self._lock:
- for index, (subscribed_callback, unused_connectivity
- ) in enumerate(self._callbacks_and_connectivities):
- if callback == subscribed_callback:
- self._callbacks_and_connectivities.pop(index)
- break
-
- def low_channel(self):
- return self._low_channel
diff --git a/src/python/grpcio/grpc/beta/_server_adaptations.py b/src/python/grpcio/grpc/beta/_server_adaptations.py
index 174af2d642..cf10c26d2f 100644
--- a/src/python/grpcio/grpc/beta/_server_adaptations.py
+++ b/src/python/grpcio/grpc/beta/_server_adaptations.py
@@ -41,6 +41,8 @@ from grpc.framework.foundation import logging_pool
from grpc.framework.foundation import stream
from grpc.framework.interfaces.face import face
+# pylint: disable=too-many-return-statements
+
_DEFAULT_POOL_SIZE = 8
@@ -78,7 +80,7 @@ class _FaceServicerContext(face.ServicerContext):
return _ServerProtocolContext(self._servicer_context)
def invocation_metadata(self):
- return _common.cygrpc_metadata(
+ return _common.to_cygrpc_metadata(
self._servicer_context.invocation_metadata())
def initial_metadata(self, initial_metadata):
@@ -179,7 +181,7 @@ def _run_request_pipe_thread(request_iterator, request_consumer,
return
request_consumer.terminate()
- def stop_request_pipe(timeout):
+ def stop_request_pipe(timeout): # pylint: disable=unused-argument
thread_joined.set()
request_pipe_thread = _common.CleanupThread(
@@ -351,27 +353,27 @@ class _GenericRpcHandler(grpc.GenericRpcHandler):
class _Server(interfaces.Server):
- def __init__(self, server):
- self._server = server
+ def __init__(self, grpc_server):
+ self._grpc_server = grpc_server
def add_insecure_port(self, address):
- return self._server.add_insecure_port(address)
+ return self._grpc_server.add_insecure_port(address)
def add_secure_port(self, address, server_credentials):
- return self._server.add_secure_port(address, server_credentials)
+ return self._grpc_server.add_secure_port(address, server_credentials)
def start(self):
- self._server.start()
+ self._grpc_server.start()
def stop(self, grace):
- return self._server.stop(grace)
+ return self._grpc_server.stop(grace)
def __enter__(self):
- self._server.start()
+ self._grpc_server.start()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
- self._server.stop(None)
+ self._grpc_server.stop(None)
return False
diff --git a/src/python/grpcio/grpc/beta/implementations.py b/src/python/grpcio/grpc/beta/implementations.py
index 7093852278..113fd38f8a 100644
--- a/src/python/grpcio/grpc/beta/implementations.py
+++ b/src/python/grpcio/grpc/beta/implementations.py
@@ -29,19 +29,20 @@
"""Entry points into the Beta API of gRPC Python."""
# threading is referenced from specification in this module.
-import abc
-import enum
import threading # pylint: disable=unused-import
-# cardinality and face are referenced from specification in this module.
+# interfaces, cardinality, and face are referenced from specification in this
+# module.
import grpc
from grpc import _auth
from grpc.beta import _client_adaptations
from grpc.beta import _server_adaptations
-from grpc.beta import interfaces
+from grpc.beta import interfaces # pylint: disable=unused-import
from grpc.framework.common import cardinality # pylint: disable=unused-import
from grpc.framework.interfaces.face import face # pylint: disable=unused-import
+# pylint: disable=too-many-arguments
+
ChannelCredentials = grpc.ChannelCredentials
ssl_channel_credentials = grpc.ssl_channel_credentials
CallCredentials = grpc.CallCredentials
@@ -218,7 +219,7 @@ def dynamic_stub(channel, service, cardinalities, options=None):
Returns:
A face.DynamicStub with which RPCs can be invoked.
"""
- effective_options = StubOptions() if options is None else options
+ effective_options = _EMPTY_STUB_OPTIONS if options is None else options
return _client_adaptations.dynamic_stub(
channel._channel, # pylint: disable=protected-access
service,
diff --git a/src/python/grpcio/grpc/framework/foundation/logging_pool.py b/src/python/grpcio/grpc/framework/foundation/logging_pool.py
index 7ee37373fa..0912fba139 100644
--- a/src/python/grpcio/grpc/framework/foundation/logging_pool.py
+++ b/src/python/grpcio/grpc/framework/foundation/logging_pool.py
@@ -39,7 +39,7 @@ def _wrap(behavior):
def _wrapping(*args, **kwargs):
try:
return behavior(*args, **kwargs)
- except Exception as e:
+ except Exception:
logging.exception(
'Unexpected exception from %s executed in logging pool!',
behavior)
diff --git a/src/python/grpcio/grpc/framework/interfaces/base/base.py b/src/python/grpcio/grpc/framework/interfaces/base/base.py
index cb3328296c..aa80e65f57 100644
--- a/src/python/grpcio/grpc/framework/interfaces/base/base.py
+++ b/src/python/grpcio/grpc/framework/interfaces/base/base.py
@@ -46,26 +46,29 @@ import six
# abandonment is referenced from specification in this module.
from grpc.framework.foundation import abandonment # pylint: disable=unused-import
+# pylint: disable=too-many-arguments
+
class NoSuchMethodError(Exception):
"""Indicates that an unrecognized operation has been called.
- Attributes:
- code: A code value to communicate to the other side of the operation along
- with indication of operation termination. May be None.
- details: A details value to communicate to the other side of the operation
- along with indication of operation termination. May be None.
- """
-
- def __init__(self, code, details):
- """Constructor.
-
- Args:
+ Attributes:
code: A code value to communicate to the other side of the operation
along with indication of operation termination. May be None.
details: A details value to communicate to the other side of the
operation along with indication of operation termination. May be None.
"""
+
+ def __init__(self, code, details):
+ """Constructor.
+
+ Args:
+ code: A code value to communicate to the other side of the operation
+ along with indication of operation termination. May be None.
+ details: A details value to communicate to the other side of the
+ operation along with indication of operation termination. May be None.
+ """
+ super(NoSuchMethodError, self).__init__()
self.code = code
self.details = details
diff --git a/src/python/grpcio/grpc/framework/interfaces/face/face.py b/src/python/grpcio/grpc/framework/interfaces/face/face.py
index 6c7e2a3af6..c6c44fe4e4 100644
--- a/src/python/grpcio/grpc/framework/interfaces/face/face.py
+++ b/src/python/grpcio/grpc/framework/interfaces/face/face.py
@@ -42,6 +42,8 @@ from grpc.framework.foundation import abandonment # pylint: disable=unused-impo
from grpc.framework.foundation import future # pylint: disable=unused-import
from grpc.framework.foundation import stream # pylint: disable=unused-import
+# pylint: disable=too-many-arguments
+
class NoSuchMethodError(Exception):
"""Raised by customer code to indicate an unrecognized method.
diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py
index c197e92ca5..267d848e74 100644
--- a/src/python/grpcio/grpc_version.py
+++ b/src/python/grpcio/grpc_version.py
@@ -29,4 +29,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!!
-VERSION='1.2.0.dev0'
+VERSION='1.3.0.dev0'
diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py
index c1807e9f1c..4ff5e266a1 100644
--- a/src/python/grpcio_health_checking/grpc_version.py
+++ b/src/python/grpcio_health_checking/grpc_version.py
@@ -29,4 +29,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
-VERSION='1.2.0.dev0'
+VERSION='1.3.0.dev0'
diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py
index 072c3263c6..52ee98a2d5 100644
--- a/src/python/grpcio_health_checking/setup.py
+++ b/src/python/grpcio_health_checking/setup.py
@@ -47,7 +47,7 @@ PACKAGE_DIRECTORIES = {
SETUP_REQUIRES = (
'grpcio-tools>={version}'.format(version=grpc_version.VERSION),)
-INSTALL_REQUIRES = ('protobuf>=3.0.0',
+INSTALL_REQUIRES = ('protobuf>=3.2.0',
'grpcio>={version}'.format(version=grpc_version.VERSION),)
COMMAND_CLASS = {
diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py
index 3778dcd3e0..8ffc08c04b 100644
--- a/src/python/grpcio_reflection/grpc_version.py
+++ b/src/python/grpcio_reflection/grpc_version.py
@@ -29,4 +29,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!!
-VERSION='1.2.0.dev0'
+VERSION='1.3.0.dev0'
diff --git a/src/python/grpcio_reflection/setup.py b/src/python/grpcio_reflection/setup.py
index 19aafe443a..e85092db57 100644
--- a/src/python/grpcio_reflection/setup.py
+++ b/src/python/grpcio_reflection/setup.py
@@ -47,7 +47,7 @@ PACKAGE_DIRECTORIES = {
SETUP_REQUIRES = (
'grpcio-tools>={version}'.format(version=grpc_version.VERSION),)
-INSTALL_REQUIRES = ('protobuf>=3.0.0',
+INSTALL_REQUIRES = ('protobuf>=3.2.0',
'grpcio>={version}'.format(version=grpc_version.VERSION),)
COMMAND_CLASS = {
diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py
index 33824b6b8f..ba82dce6f6 100644
--- a/src/python/grpcio_tests/grpc_version.py
+++ b/src/python/grpcio_tests/grpc_version.py
@@ -29,4 +29,4 @@
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!!
-VERSION='1.2.0.dev0'
+VERSION='1.3.0.dev0'
diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py
index b0c73fc575..b9f0264dae 100644
--- a/src/python/grpcio_tests/setup.py
+++ b/src/python/grpcio_tests/setup.py
@@ -56,7 +56,7 @@ INSTALL_REQUIRES = (
'grpcio>={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.0.0', 'six>=1.10',)
+ 'oauth2client>=1.4.7', 'protobuf>=3.2.0', 'six>=1.10',)
COMMAND_CLASS = {
# Run `preprocess` *before* doing any packaging!
diff --git a/src/python/grpcio_tests/tests/http2/negative_http2_client.py b/src/python/grpcio_tests/tests/http2/negative_http2_client.py
index b8adf093a5..b184e62cfd 100644
--- a/src/python/grpcio_tests/tests/http2/negative_http2_client.py
+++ b/src/python/grpcio_tests/tests/http2/negative_http2_client.py
@@ -31,6 +31,7 @@
import argparse
import grpc
+import time
from src.proto.grpc.testing import test_pb2
from src.proto.grpc.testing import messages_pb2
@@ -75,6 +76,7 @@ def _goaway(stub):
first_response = stub.UnaryCall(_SIMPLE_REQUEST)
_validate_payload_type_and_length(first_response, messages_pb2.COMPRESSABLE,
_RESPONSE_SIZE)
+ time.sleep(1)
second_response = stub.UnaryCall(_SIMPLE_REQUEST)
_validate_payload_type_and_length(second_response,
messages_pb2.COMPRESSABLE, _RESPONSE_SIZE)
diff --git a/src/python/grpcio_tests/tests/interop/client.py b/src/python/grpcio_tests/tests/interop/client.py
index 833818e662..97f6843d3c 100644
--- a/src/python/grpcio_tests/tests/interop/client.py
+++ b/src/python/grpcio_tests/tests/interop/client.py
@@ -45,7 +45,7 @@ def _args():
'--server_host',
help='the host to which to connect',
type=str,
- default="127.0.0.1")
+ default="localhost")
parser.add_argument(
'--server_port', help='the port to which to connect', type=int)
parser.add_argument(
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
index bcc01f3978..6f9269dd40 100644
--- a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
+++ b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
@@ -42,12 +42,15 @@ import sys
import tempfile
import threading
import unittest
+import platform
import grpc
from grpc_tools import protoc
from tests.unit.framework.common import test_constants
_MESSAGES_IMPORT = b'import "messages.proto";'
+_SPLIT_NAMESPACE = b'package grpc_protoc_plugin.invocation_testing.split;'
+_COMMON_NAMESPACE = b'package grpc_protoc_plugin.invocation_testing;'
@contextlib.contextmanager
@@ -148,6 +151,8 @@ class CommonTestMixin(object):
self.assertEqual(expected_response, response)
+@unittest.skipIf(platform.python_implementation() == "PyPy",
+ "Skip test if run with PyPy")
class SameSeparateTest(unittest.TestCase, SeparateTestMixin):
def setUp(self):
@@ -163,7 +168,10 @@ class SameSeparateTest(unittest.TestCase, SeparateTestMixin):
os.makedirs(self.grpc_python_out_directory)
same_proto_file = os.path.join(self.proto_directory,
'same_separate.proto')
- open(same_proto_file, 'wb').write(same_proto_contents)
+ open(same_proto_file, 'wb').write(
+ same_proto_contents.replace(
+ _COMMON_NAMESPACE,
+ b'package grpc_protoc_plugin.invocation_testing.same_separate;'))
protoc_result = protoc.main([
'',
'--proto_path={}'.format(self.proto_directory),
@@ -186,6 +194,8 @@ class SameSeparateTest(unittest.TestCase, SeparateTestMixin):
shutil.rmtree(self.directory)
+@unittest.skipIf(platform.python_implementation() == "PyPy",
+ "Skip test if run with PyPy")
class SameCommonTest(unittest.TestCase, CommonTestMixin):
def setUp(self):
@@ -199,7 +209,11 @@ class SameCommonTest(unittest.TestCase, CommonTestMixin):
os.makedirs(self.python_out_directory)
same_proto_file = os.path.join(self.proto_directory,
'same_common.proto')
- open(same_proto_file, 'wb').write(same_proto_contents)
+ open(same_proto_file, 'wb').write(
+ same_proto_contents.replace(
+ _COMMON_NAMESPACE,
+ b'package grpc_protoc_plugin.invocation_testing.same_common;'))
+
protoc_result = protoc.main([
'',
'--proto_path={}'.format(self.proto_directory),
@@ -219,6 +233,8 @@ class SameCommonTest(unittest.TestCase, CommonTestMixin):
shutil.rmtree(self.directory)
+@unittest.skipIf(platform.python_implementation() == "PyPy",
+ "Skip test if run with PyPy")
class SplitCommonTest(unittest.TestCase, CommonTestMixin):
def setUp(self):
@@ -240,8 +256,14 @@ class SplitCommonTest(unittest.TestCase, CommonTestMixin):
'split_common_messages.proto')
open(services_proto_file, 'wb').write(
services_proto_contents.replace(
- _MESSAGES_IMPORT, b'import "split_common_messages.proto";'))
- open(messages_proto_file, 'wb').write(messages_proto_contents)
+ _MESSAGES_IMPORT, b'import "split_common_messages.proto";')
+ .replace(
+ _SPLIT_NAMESPACE,
+ b'package grpc_protoc_plugin.invocation_testing.split_common;'))
+ open(messages_proto_file, 'wb').write(
+ messages_proto_contents.replace(
+ _SPLIT_NAMESPACE,
+ b'package grpc_protoc_plugin.invocation_testing.split_common;'))
protoc_result = protoc.main([
'',
'--proto_path={}'.format(self.proto_directory),
@@ -262,6 +284,8 @@ class SplitCommonTest(unittest.TestCase, CommonTestMixin):
shutil.rmtree(self.directory)
+@unittest.skipIf(platform.python_implementation() == "PyPy",
+ "Skip test if run with PyPy")
class SplitSeparateTest(unittest.TestCase, SeparateTestMixin):
def setUp(self):
@@ -285,8 +309,16 @@ class SplitSeparateTest(unittest.TestCase, SeparateTestMixin):
'split_separate_messages.proto')
open(services_proto_file, 'wb').write(
services_proto_contents.replace(
- _MESSAGES_IMPORT, b'import "split_separate_messages.proto";'))
- open(messages_proto_file, 'wb').write(messages_proto_contents)
+ _MESSAGES_IMPORT, b'import "split_separate_messages.proto";')
+ .replace(
+ _SPLIT_NAMESPACE,
+ b'package grpc_protoc_plugin.invocation_testing.split_separate;'
+ ))
+ open(messages_proto_file, 'wb').write(
+ messages_proto_contents.replace(
+ _SPLIT_NAMESPACE,
+ b'package grpc_protoc_plugin.invocation_testing.split_separate;'
+ ))
protoc_result = protoc.main([
'',
'--proto_path={}'.format(self.proto_directory),
diff --git a/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py b/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py
index f2e3898ed6..ee235032f0 100644
--- a/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py
+++ b/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py
@@ -249,3 +249,7 @@ class InvocationDefectsTest(unittest.TestCase):
with self.assertRaises(grpc.RpcError):
for _ in range(test_constants.STREAM_LENGTH // 2 + 1):
next(response_iterator)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests/unit/_metadata_test.py b/src/python/grpcio_tests/tests/unit/_metadata_test.py
index 53fe7ba8aa..035d87e3cf 100644
--- a/src/python/grpcio_tests/tests/unit/_metadata_test.py
+++ b/src/python/grpcio_tests/tests/unit/_metadata_test.py
@@ -32,7 +32,7 @@ import unittest
import weakref
import grpc
-from grpc import _grpcio_metadata
+from grpc import _channel
from grpc.framework.foundation import logging_pool
from tests.unit import test_common
@@ -49,8 +49,6 @@ _UNARY_STREAM = '/test/UnaryStream'
_STREAM_UNARY = '/test/StreamUnary'
_STREAM_STREAM = '/test/StreamStream'
-_USER_AGENT = 'Python-gRPC-{}'.format(_grpcio_metadata.__version__)
-
_CLIENT_METADATA = (('client-md-key', 'client-md-key'),
('client-md-key-bin', b'\x00\x01'))
@@ -76,7 +74,7 @@ def validate_client_metadata(test, servicer_context):
_CLIENT_METADATA, servicer_context.invocation_metadata()))
test.assertTrue(
user_agent(servicer_context.invocation_metadata())
- .startswith('primary-agent ' + _USER_AGENT))
+ .startswith('primary-agent ' + _channel._USER_AGENT))
test.assertTrue(
user_agent(servicer_context.invocation_metadata())
.endswith('secondary-agent'))
diff --git a/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py b/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py
index be3522f46f..eb5f459848 100644
--- a/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py
+++ b/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py
@@ -35,8 +35,8 @@ import unittest
from grpc import _common
_SHORT_TIME = 0.5
-_LONG_TIME = 2.0
-_EPSILON = 0.1
+_LONG_TIME = 5.0
+_EPSILON = 0.5
def cleanup(timeout):
diff --git a/src/ruby/ext/grpc/extconf.rb b/src/ruby/ext/grpc/extconf.rb
index 66c54aa3e0..ecb66239b9 100644
--- a/src/ruby/ext/grpc/extconf.rb
+++ b/src/ruby/ext/grpc/extconf.rb
@@ -27,6 +27,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+require 'etc'
require 'mkmf'
LIBDIR = RbConfig::CONFIG['libdir']
@@ -80,7 +81,9 @@ ENV['BUILDDIR'] = output_dir
unless windows
puts 'Building internal gRPC into ' + grpc_lib_dir
- system("make -j -C #{grpc_root} #{grpc_lib_dir}/libgrpc.a CONFIG=#{grpc_config}")
+ nproc = 4
+ nproc = Etc.nprocessors * 2 if Etc.respond_to? :nprocessors
+ system("make -j#{nproc} -C #{grpc_root} #{grpc_lib_dir}/libgrpc.a CONFIG=#{grpc_config}")
exit 1 unless $? == 0
end
@@ -102,7 +105,6 @@ $CFLAGS << ' -std=c99 '
$CFLAGS << ' -Wall '
$CFLAGS << ' -Wextra '
$CFLAGS << ' -pedantic '
-$CFLAGS << ' -Werror '
$CFLAGS << ' -Wno-format '
output = File.join('grpc', 'grpc_c')
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index d8d76cc1c5..3ef6f0eb29 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -107,6 +107,7 @@ grpc_channel_register_call_type grpc_channel_register_call_import;
grpc_channel_create_registered_call_type grpc_channel_create_registered_call_import;
grpc_call_start_batch_type grpc_call_start_batch_import;
grpc_call_get_peer_type grpc_call_get_peer_import;
+grpc_call_set_load_reporting_cost_context_type grpc_call_set_load_reporting_cost_context_import;
grpc_census_call_set_context_type grpc_census_call_set_context_import;
grpc_census_call_get_context_type grpc_census_call_get_context_import;
grpc_channel_get_target_type grpc_channel_get_target_import;
@@ -219,6 +220,7 @@ grpc_slice_buffer_move_first_into_buffer_type grpc_slice_buffer_move_first_into_
grpc_slice_buffer_take_first_type grpc_slice_buffer_take_first_import;
grpc_slice_buffer_undo_take_first_type grpc_slice_buffer_undo_take_first_import;
gpr_malloc_type gpr_malloc_import;
+gpr_zalloc_type gpr_zalloc_import;
gpr_free_type gpr_free_import;
gpr_realloc_type gpr_realloc_import;
gpr_malloc_aligned_type gpr_malloc_aligned_import;
@@ -294,6 +296,7 @@ gpr_ref_type gpr_ref_import;
gpr_ref_non_zero_type gpr_ref_non_zero_import;
gpr_refn_type gpr_refn_import;
gpr_unref_type gpr_unref_import;
+gpr_ref_is_unique_type gpr_ref_is_unique_import;
gpr_stats_init_type gpr_stats_init_import;
gpr_stats_inc_type gpr_stats_inc_import;
gpr_stats_read_type gpr_stats_read_import;
@@ -398,6 +401,7 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_channel_create_registered_call_import = (grpc_channel_create_registered_call_type) GetProcAddress(library, "grpc_channel_create_registered_call");
grpc_call_start_batch_import = (grpc_call_start_batch_type) GetProcAddress(library, "grpc_call_start_batch");
grpc_call_get_peer_import = (grpc_call_get_peer_type) GetProcAddress(library, "grpc_call_get_peer");
+ grpc_call_set_load_reporting_cost_context_import = (grpc_call_set_load_reporting_cost_context_type) GetProcAddress(library, "grpc_call_set_load_reporting_cost_context");
grpc_census_call_set_context_import = (grpc_census_call_set_context_type) GetProcAddress(library, "grpc_census_call_set_context");
grpc_census_call_get_context_import = (grpc_census_call_get_context_type) GetProcAddress(library, "grpc_census_call_get_context");
grpc_channel_get_target_import = (grpc_channel_get_target_type) GetProcAddress(library, "grpc_channel_get_target");
@@ -510,6 +514,7 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_slice_buffer_take_first_import = (grpc_slice_buffer_take_first_type) GetProcAddress(library, "grpc_slice_buffer_take_first");
grpc_slice_buffer_undo_take_first_import = (grpc_slice_buffer_undo_take_first_type) GetProcAddress(library, "grpc_slice_buffer_undo_take_first");
gpr_malloc_import = (gpr_malloc_type) GetProcAddress(library, "gpr_malloc");
+ gpr_zalloc_import = (gpr_zalloc_type) GetProcAddress(library, "gpr_zalloc");
gpr_free_import = (gpr_free_type) GetProcAddress(library, "gpr_free");
gpr_realloc_import = (gpr_realloc_type) GetProcAddress(library, "gpr_realloc");
gpr_malloc_aligned_import = (gpr_malloc_aligned_type) GetProcAddress(library, "gpr_malloc_aligned");
@@ -585,6 +590,7 @@ void grpc_rb_load_imports(HMODULE library) {
gpr_ref_non_zero_import = (gpr_ref_non_zero_type) GetProcAddress(library, "gpr_ref_non_zero");
gpr_refn_import = (gpr_refn_type) GetProcAddress(library, "gpr_refn");
gpr_unref_import = (gpr_unref_type) GetProcAddress(library, "gpr_unref");
+ gpr_ref_is_unique_import = (gpr_ref_is_unique_type) GetProcAddress(library, "gpr_ref_is_unique");
gpr_stats_init_import = (gpr_stats_init_type) GetProcAddress(library, "gpr_stats_init");
gpr_stats_inc_import = (gpr_stats_inc_type) GetProcAddress(library, "gpr_stats_inc");
gpr_stats_read_import = (gpr_stats_read_type) GetProcAddress(library, "gpr_stats_read");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index 4eab9639ea..ef9845dfe0 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -272,6 +272,9 @@ extern grpc_call_start_batch_type grpc_call_start_batch_import;
typedef char *(*grpc_call_get_peer_type)(grpc_call *call);
extern grpc_call_get_peer_type grpc_call_get_peer_import;
#define grpc_call_get_peer grpc_call_get_peer_import
+typedef void(*grpc_call_set_load_reporting_cost_context_type)(grpc_call *call, struct grpc_load_reporting_cost_context *context);
+extern grpc_call_set_load_reporting_cost_context_type grpc_call_set_load_reporting_cost_context_import;
+#define grpc_call_set_load_reporting_cost_context grpc_call_set_load_reporting_cost_context_import
typedef void(*grpc_census_call_set_context_type)(grpc_call *call, struct census_context *context);
extern grpc_census_call_set_context_type grpc_census_call_set_context_import;
#define grpc_census_call_set_context grpc_census_call_set_context_import
@@ -608,6 +611,9 @@ extern grpc_slice_buffer_undo_take_first_type grpc_slice_buffer_undo_take_first_
typedef void *(*gpr_malloc_type)(size_t size);
extern gpr_malloc_type gpr_malloc_import;
#define gpr_malloc gpr_malloc_import
+typedef void *(*gpr_zalloc_type)(size_t size);
+extern gpr_zalloc_type gpr_zalloc_import;
+#define gpr_zalloc gpr_zalloc_import
typedef void(*gpr_free_type)(void *ptr);
extern gpr_free_type gpr_free_import;
#define gpr_free gpr_free_import
@@ -833,6 +839,9 @@ extern gpr_refn_type gpr_refn_import;
typedef int(*gpr_unref_type)(gpr_refcount *r);
extern gpr_unref_type gpr_unref_import;
#define gpr_unref gpr_unref_import
+typedef int(*gpr_ref_is_unique_type)(gpr_refcount *r);
+extern gpr_ref_is_unique_type gpr_ref_is_unique_import;
+#define gpr_ref_is_unique gpr_ref_is_unique_import
typedef void(*gpr_stats_init_type)(gpr_stats_counter *c, intptr_t n);
extern gpr_stats_init_type gpr_stats_init_import;
#define gpr_stats_init gpr_stats_init_import
diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb
index 6934257cbc..d8de0beefb 100644
--- a/src/ruby/lib/grpc/generic/client_stub.rb
+++ b/src/ruby/lib/grpc/generic/client_stub.rb
@@ -84,7 +84,7 @@ module GRPC
# channel:
#
# - :channel_override
- # when present, this must be a pre-created GRPC::Channel. If it's
+ # when present, this must be a pre-created GRPC::Core::Channel. If it's
# present the host and arbitrary keyword arg areignored, and the RPC
# connection uses this channel.
#
diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb
index ce0892decf..9901158e73 100644
--- a/src/ruby/lib/grpc/version.rb
+++ b/src/ruby/lib/grpc/version.rb
@@ -29,5 +29,5 @@
# GRPC contains the General RPC module.
module GRPC
- VERSION = '1.2.0.dev'
+ VERSION = '1.3.0.dev'
end
diff --git a/src/ruby/qps/proxy-worker.rb b/src/ruby/qps/proxy-worker.rb
new file mode 100755
index 0000000000..077920d1d3
--- /dev/null
+++ b/src/ruby/qps/proxy-worker.rb
@@ -0,0 +1,160 @@
+#!/usr/bin/env ruby
+
+# Copyright 2017, 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.
+
+# Proxy of worker service implementation for running a PHP client
+
+this_dir = File.expand_path(File.dirname(__FILE__))
+lib_dir = File.join(File.dirname(this_dir), 'lib')
+$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
+$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
+
+require 'grpc'
+require 'optparse'
+require 'histogram'
+require 'etc'
+require 'facter'
+require 'qps-common'
+require 'src/proto/grpc/testing/services_services_pb'
+require 'src/proto/grpc/testing/proxy-service_services_pb'
+
+class ProxyBenchmarkClientServiceImpl < Grpc::Testing::ProxyClientService::Service
+ def initialize(port)
+ @mytarget = "localhost:" + port.to_s
+ end
+ def setup(config)
+ @config = config
+ @histres = config.histogram_params.resolution
+ @histmax = config.histogram_params.max_possible
+ @histogram = Histogram.new(@histres, @histmax)
+ @start_time = Time.now
+ # TODO(vjpai): Support multiple client channels by spawning off a PHP client per channel
+ command = "php " + File.expand_path(File.dirname(__FILE__)) + "/../../php/tests/qps/client.php " + @mytarget
+ puts "Starting command: " + command
+ @php_pid = spawn(command)
+ end
+ def stop
+ Process.kill("TERM", @php_pid)
+ Process.wait(@php_pid)
+ end
+ def get_config(_args, _call)
+ puts "Answering get_config"
+ @config
+ end
+ def report_time(call)
+ puts "Starting a time reporting stream"
+ call.each_remote_read do |lat|
+ @histogram.add((lat.latency)*1e9)
+ end
+ Grpc::Testing::Void.new
+ end
+ def mark(reset)
+ lat = Grpc::Testing::HistogramData.new(
+ bucket: @histogram.contents,
+ min_seen: @histogram.minimum,
+ max_seen: @histogram.maximum,
+ sum: @histogram.sum,
+ sum_of_squares: @histogram.sum_of_squares,
+ count: @histogram.count
+ )
+ elapsed = Time.now-@start_time
+ if reset
+ @start_time = Time.now
+ @histogram = Histogram.new(@histres, @histmax)
+ end
+ Grpc::Testing::ClientStats.new(latencies: lat, time_elapsed: elapsed)
+ end
+end
+
+class ProxyWorkerServiceImpl < Grpc::Testing::WorkerService::Service
+ def cpu_cores
+ Facter.value('processors')['count']
+ end
+ # Leave run_server unimplemented since this proxies for a client only.
+ # If the driver tries to use this as a server, it will get an unimplemented
+ # status return value.
+ def run_client(reqs)
+ q = EnumeratorQueue.new(self)
+ Thread.new {
+ reqs.each do |req|
+ case req.argtype.to_s
+ when 'setup'
+ @bmc.setup(req.setup)
+ q.push(Grpc::Testing::ClientStatus.new(stats: @bmc.mark(false)))
+ when 'mark'
+ q.push(Grpc::Testing::ClientStatus.new(stats:
+ @bmc.mark(req.mark.reset)))
+ end
+ end
+ @bmc.stop
+ q.push(self)
+ }
+ q.each_item
+ end
+ def core_count(_args, _call)
+ Grpc::Testing::CoreResponse.new(cores: cpu_cores)
+ end
+ def quit_worker(_args, _call)
+ Thread.new {
+ sleep 3
+ @server.stop
+ }
+ Grpc::Testing::Void.new
+ end
+ def initialize(s, bmc)
+ @server = s
+ @bmc = bmc
+ end
+end
+
+def proxymain
+ options = {
+ 'driver_port' => 0
+ }
+ OptionParser.new do |opts|
+ opts.banner = 'Usage: [--driver_port <port>]'
+ opts.on('--driver_port PORT', '<port>') do |v|
+ options['driver_port'] = v
+ end
+ end.parse!
+
+ # Configure any errors with client or server child threads to surface
+ Thread.abort_on_exception = true
+
+ s = GRPC::RpcServer.new
+ port = s.add_http2_port("0.0.0.0:" + options['driver_port'].to_s,
+ :this_port_is_insecure)
+ bmc = ProxyBenchmarkClientServiceImpl.new(port)
+ s.handle(bmc)
+ s.handle(ProxyWorkerServiceImpl.new(s, bmc))
+ s.run
+end
+
+proxymain
diff --git a/src/ruby/qps/src/proto/grpc/testing/proxy-service_pb.rb b/src/ruby/qps/src/proto/grpc/testing/proxy-service_pb.rb
new file mode 100644
index 0000000000..d238198cca
--- /dev/null
+++ b/src/ruby/qps/src/proto/grpc/testing/proxy-service_pb.rb
@@ -0,0 +1,17 @@
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: src/proto/grpc/testing/proxy-service.proto
+
+require 'google/protobuf'
+
+require 'src/proto/grpc/testing/control_pb'
+Google::Protobuf::DescriptorPool.generated_pool.build do
+ add_message "grpc.testing.ProxyStat" do
+ optional :latency, :double, 1
+ end
+end
+
+module Grpc
+ module Testing
+ ProxyStat = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ProxyStat").msgclass
+ end
+end
diff --git a/src/ruby/qps/src/proto/grpc/testing/proxy-service_services_pb.rb b/src/ruby/qps/src/proto/grpc/testing/proxy-service_services_pb.rb
new file mode 100644
index 0000000000..37ddbf5b03
--- /dev/null
+++ b/src/ruby/qps/src/proto/grpc/testing/proxy-service_services_pb.rb
@@ -0,0 +1,55 @@
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# Source: src/proto/grpc/testing/proxy-service.proto for package 'grpc.testing'
+# Original file comments:
+# Copyright 2017, 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.
+#
+
+require 'grpc'
+require 'src/proto/grpc/testing/proxy-service_pb'
+
+module Grpc
+ module Testing
+ module ProxyClientService
+ class Service
+
+ include GRPC::GenericService
+
+ self.marshal_class_method = :encode
+ self.unmarshal_class_method = :decode
+ self.service_name = 'grpc.testing.ProxyClientService'
+
+ rpc :GetConfig, Void, ClientConfig
+ rpc :ReportTime, stream(ProxyStat), Void
+ end
+
+ Stub = Service.rpc_stub_class
+ end
+ end
+end
diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb
index 8f3d2ba81c..632c0100bd 100644
--- a/src/ruby/tools/version.rb
+++ b/src/ruby/tools/version.rb
@@ -29,6 +29,6 @@
module GRPC
module Tools
- VERSION = '1.2.0.dev'
+ VERSION = '1.3.0.dev'
end
end